VBからエクセルファイルを読込み、エクセル内の文字を検索したい

解決


超初心者  2005-07-28 02:26:26  No: 123790

VBを利用して、あるフォルダ内のエクセルファイルを検索しファイルを読込み、その読込んだエクセルファイル内のA列を検索した、その結果を表示したいのですが、どの様なソースにしたら良いのか全くわからないので、どなたか教えていただけにでしょうか?よろしくお願いします。

1.フォルダ内のエクセルファイルを検索する。(任意の文字を入力し検索する)
2.検索完了したらファイルを読込む。(エクセルは起動しない)
3.読込んだエクセルファイルの内A列を検索する。(任意の文字を入力し検索する)
4.検索結果を表示する。(A列、B列、C列を表示)

環境は、VB6.0  エクセル2003です。  Win XP Pro


特攻隊長まるるう  2005-07-28 02:48:32  No: 123791

掲示板で1から教えるのは量的に無理ですから、基礎を学んでくる
ことをお勧めします。
[VBレスキュー(花ちゃん)Excel・Word関係]
http://www.bcap.co.jp/hanafusa/VBHLP/excelframe.htm
その後で過去ログ
http://madia.world.coocan.jp/cgi-bin/VBBBS2/wwwlng.cgi?print+200406/04060060.txt


超初心者  2005-08-11 07:55:19  No: 123792

2週間かかり下記ソースができました。

マイドキュメント内のエクセルファイルが開くようになりました。
しかし、あるサーバー内のあるフォルダの中のファイルを検索したいのですが、パスを指定する箇所がわかりません。
また、利用したいフォルダ内にはいくつかフォルダがあり階層にもなっているのでそれも検索できるようにしたいのです。

エクセル内をFindメソッドとRangeを利用して、A列(A1:A10)を検索できるようになり、MsgBoxに検索結果を表示できるようになったのですが、検索結果としてB列やC列もMsgBoxに表示できるようにしたいのですが、どなたかアドバイスをよろしくお願いします。

Private Sub Command1_Click()
    On Error Resume Next

Dim xlApp   As Excel.Application
Dim xlBook  As Excel.Workbook
Dim xlSheet As Excel.Worksheet
Dim xlInput As String

' Inputでファイルを任意のファイル名を検索し
'見つかったらファイルを開く

xlInput = InputBox("機種")

Set xlApp = CreateObject("Excel.Application") 'エクセル起動
Set xlBook = xlApp.Workbooks.Open(xlInput)

'試し:正常に指定したファイルが開いているか確認するため   xlApp.Visible = True  

Dim myRange As Range
Dim xlFind  As String     

xlFind = InputBox("部番")
    
Set myRange = Worksheets("Sheet1").Range("A1:A10")
     answer = Application.WorksheetFunction.Find(Sheet1, "A1:A10", xlFind)

MsgBox answer

If vbOKOnly = 0 Then xlApp.Quit
   
Set xlSheet = Nothing
Set xlBook  = Nothing
Set xlApp   = Nothing

End Sub


特攻隊長まるるう  2005-08-11 19:14:12  No: 123793

お、すごい♪

とりあえず
>サーバー内のあるフォルダ
ってのが初耳なんで、ちょっと確認。ローカルのフォルダではなく、
外部のコンピュータを覗く場合、セキュリティ関係の問題が出てくる
場合があります。その辺りの話はネットワーク管理者の方とよく確認
しておいて下さい。今後とも、マイクロソフトはセキュリティ面を強化
していくと思われますので、そちらのお勉強も必要になるかもしれません。

ま、今のところ、対象フォルダの参照権限を持ってれば(エクスプローラ
で対象フォルダを閲覧できていれば)大丈夫でしょう。

>しかし、あるサーバー内のあるフォルダの中のファイルを検索したいのですが、パスを指定する箇所がわかりません。
昨日、似たような質問がありました。自分以外の質問にも関連しそうな質問には
目を通しておきましょう。
http://madia.world.coocan.jp/cgi-bin/VBBBS2/wwwlng.cgi?print+200508/05080020.txt
こちらの方はネットワークドライブを割り当てて、ローカルのフォルダと同じ様な
処理をされたようです。
基本的にネットワーク越しのアドレスは
  \\コンピュータ名\ドライブ名\フォルダ名\ファイル名
という形式で扱えます。

>利用したいフォルダ内にはいくつかフォルダがあり階層にもなっているので
>それも検索できるようにしたいのです。
これはよくあるサンプルですね。色々な場面で使えますのでサンプルを
公開している方は多いでしょう。今回はじゃんぬさんのページをリンク
させて貰いましょうか。感謝です♪
[ディレクトリ (フォルダ) 以下のファイルを最下層まで検索または取得する]
http://jeanne.wankuma.com/tips/directory/15-getallfiles.html
リンク先の一番下が[VB6.0]のコードです。

>検索結果としてB列やC列もMsgBoxに表示できるようにしたいのですが
Range の指定時に列も指定すれば簡単に実現できますね。
変数の接頭詞の xl はエクセルの定数で使われているので使わないほうが
いいです。ボクはローカル変数は work の意味で w を付けてます。
(モジュールレベル変数は m)
あと、入力エラーチェックがありませんね。ファイルが存在しなかった時など
標準のエラー処理に任せず、自分でチェックするようにしましょう。
[VB6.0]
    Dim wMyRange As Range
    Dim wAnswerRange As Range
    Dim wColAlphabet As String
    Dim wFindAddress As String
    Dim wFindString  As String
    Dim wFirstAddress As String

    wColAlphabet = InputBox("検索する列名をアルファベットで入力して下さい。")
    'ここで入力エラーチェックするべきです。
    wFindAddress = wColAlphabet & "1:" & wColAlphabet & "10"
    wFindString = InputBox("部番")
    
    Set wMyRange = Worksheets("Sheet1").Range(wFindAddress)
'    answer = Application.WorksheetFunction.Find("Sheet1", wFindAddress, wFindString)
    With wMyRange
        Set wAnswerRange = .Find(wFindString, lookin:=Excel.XlFindLookIn.xlValues)
        If Not wAnswerRange Is Nothing Then
            wFirstAddress = wAnswerRange.Address
            MsgBox wFirstAddress
            Do
                Set wAnswerRange = .FindNext(wAnswerRange)
                If Not wAnswerRange Is Nothing And wAnswerRange.Address <> wFirstAddress Then
                    MsgBox wAnswerRange.Address
                Else
                    Exit Do
                End If
            Loop 'While Not wAnswerRange Is Nothing And wAnswerRange.Address <> wFirstAddress
        Else
            MsgBox "見つかりませんでした。"
        End If
    End With


特攻隊長まるるう  2005-08-11 20:56:08  No: 123794

あ"っ、[VB6.0]のサンプルで
>    Set wMyRange = Worksheets("Sheet1").Range(wFindAddress)
はマズいねぇ。
    Set wMyRange = xlBook.Worksheets("Sheet1").Range(wFindAddress)
かな?なんか提示されたコードがVBAのコードと混ざってる気が…(^^;)


超初心者  2005-08-24 10:09:10  No: 123795

>サーバー内のあるフォルダ
 に関しては、自部署のサーバー内を検索する予定であったことを思い出したので・・・改めて追記しました。

>しかし、あるサーバー内のあるフォルダの中のファイルを検索したいのですが、パスを指定する箇所がわかりません。
に関しては、パスを指定する箇所がわかりませんでした。

>利用したいフォルダ内にはいくつかフォルダがあり階層にもなっているので
>それも検索できるようにしたいのです。
リンクして頂いたサンプルコードを利用して、検索可能になりました。またパスの指定箇所もわかりました。

>検索結果としてB列やC列もMsgBoxに表示できるようにしたいのですが
この件なのですが、特攻隊長まるるうさんにサンプルコードを提示して頂いた内容丸々そのまま入れさせてもらい、そこから色々いじって理解してきました。(下記のようになりました。)

どうしてもMsgBoxに表示させる内容が、うまくいきません。Rangeの使用方法を調べては見たのですが下記点がうまくできません。
●B列を検索し、抽出できた内容がどの位置にあるかAdrress表示していることがわかりましたが、そのときのA列やC列も同時にMsgBoxに表示しようとヘルプでRangeの使い方を調べながらやっているのですがうまくいきません。
(Findの検索結果をRangeの引数に代入したらよいのか困ってます。)
例えばAdrressで$B$3と表示されるとき、A3,B3.C3も表示したいのですが・・・
教えていただきたいのですがよろしくお願いします。

    Dim lIndex        As Long
    Dim nPrompt       As String
    Dim nFilePath     As String
    Dim nFilePathes() As String
    Dim strFile       As String
    Dim xlApp         As Excel.Application
    Dim xlBook        As Excel.Workbook
    Dim xlSheet       As Excel.Worksheet
  
        ' InputBoxで検索したいファイル名を入力し、エクセルファイルを最下層まで検索し取得する
        strFile = "NTL302M"
        'strFile = InputBox("機種")
        nFilePathes() = GetFilesMostDeep("D:\VB\", "" & strFile & ".xls")
 
                ' 取得したファイル名を列挙する (※ 添字が 1 からであることに注意)
                For lIndex = 1 To UBound(nFilePathes())
                    nPrompt = nPrompt & nFilePathes(lIndex) & vbNewLine
                Next lIndex
    
        ' 取得したすべてのファイルパス(機種ファイル)を表示する【確認】
        If nPrompt <> "" Then
            Call MsgBox(nPrompt)
        End If
    
        '取得したパス(ファイル)を開く
        For lIndex = 1 To UBound(nFilePathes())
           nPrompt = nPrompt & nFilePathes(lIndex) & vbNewLine
             
                 Set xlApp = CreateObject("Excel.Application") 'エクセル起動
                 Set xlBook = xlApp.Workbooks.Open(nFilePathes(lIndex))  '開くファイルパスをOpenメソッドに代入
                 'xlApp.Visible = True
        Next lIndex
    
'開いたファイル内を検索
    Dim wMyRange As Range
    Dim wAnswerRange As Range
    Dim wColAlphabet As String
    Dim wFindAddress As String
    Dim wFindString  As String
    Dim wFirstAddress As String

    'wColAlphabet = InputBox("検索する列名をアルファベットで入力して下さい。")
    wColAlphabet = "B"  '部番で設定
    'ここで入力エラーチェックするべきです。
    wFindAddress = wColAlphabet & "1:" & wColAlphabet & "10000"
    wFindString = "0002"
    'wFindString = InputBox("部番")
    
    
    Set wMyRange = xlBook.Worksheets("Sheet1").Range(wFindAddress)
'    answer = Application.WorksheetFunction.Find("Sheet1", wFindAddress, wFindString)
    
    With wMyRange
        Set wAnswerRange = .Find(wFindString, lookin:=Excel.XlFindLookIn.xlValues)
        If Not wAnswerRange Is Nothing Then
            'wFirstAddress = wAnswerRange.Address
            wFirstAddress = wAnswerRange
            MsgBox wFirstAddress
            Do
                Set wAnswerRange = .FindNext(wAnswerRange)
                'If Not wAnswerRange Is Nothing And wAnswerRange.Address <> wFirstAddress Then
                If Not wAnswerRange Is Nothing And wAnswerRange <> wFirstAddress Then
                   MsgBox wAnswerRange
                Else
                    Exit Do
                End If
            Loop 'While Not wAnswerRange Is Nothing And wAnswerRange.Address <> wFirstAddress
        Else
            MsgBox "見つかりませんでした。"
        End If
    End With

    ' Quit メソッドを使って Excel を終了します。
    xlApp.Quit

    ' オブジェクトを解放します。
       Set xlSheet = Nothing
       Set xlBook = Nothing
       Set xlApp = Nothing


魔界の仮面弁士  2005-08-24 10:37:58  No: 123796

> '取得したパス(ファイル)を開く
> For lIndex = 1 To UBound(nFilePathes())
>    nPrompt = nPrompt & nFilePathes(lIndex) & vbNewLine
>    Set xlApp = CreateObject("Excel.Application") 'エクセル起動
>    Set xlBook = xlApp.Workbooks.Open(nFilePathes(lIndex))
>    'xlApp.Visible = True
> Next lIndex

上記の部分が気になります。

ループ中で、Excel.Applicationインスタンスを随時生成していますが、
それを受け取る変数が、xlApp一つしか用意されていませんよね。

Excel.Applicationのインスタンスを複数扱うのであれば、
  For n = LBound(X) To UBound(X)
     Set xlApp(n) = CreateObject("Excel.Application")
     Set xlBook(n) = xlApp(n).Workbooks.Open( X(n) )
  Next n
のようにして、それを受け取るための変数も、(配列などを使って)
用意するべきですし、逆に、インスタンスを1つだけにしたいなら
  Set xlApp = CreateObject("Excel.Application")
  For n = LBound(X) To UBound(X)
     Set xlBook(n) = xlApp.Workbooks.Open( X(n) )
  Next n
のように、ループの外に出すべきかと思いますよ。

あるいは、ワークブックを受け取る変数も1つだけにするために、
  Set xlApp = CreateObject("Excel.Application")
  For n = LBound(X) To UBound(X)
     Set xlBook = xlApp(n).Workbooks.Open( X(n) )
     '(xlBookに対する検索処理)
     xlBook.Close
     Set xlBook = Nothing
   Next n
   xlApp.Quit
   Set xlApp = Nothing
のように、検索部分もループの中に含めるようにするとか。


超初心者  2005-08-24 17:42:14  No: 123797

魔界の仮面弁士さんありがとうございます。
確かにループ内で随時生成されている状態でした。
さっそく修正してみました。
勉強になました。m(__)m


特攻隊長まるるう  2005-08-24 21:02:44  No: 123798

>例えばAdrressで$B$3と表示されるとき、A3,B3.C3も表示したいのですが・・・
Excel VBA のヘルプで Cells プロパティのサンプルに『セルの値が 1 つ上の
セルの値と同じ場合』の比較をしているサンプルコードが載っていると思います。

…普通に Range コレクションの説明を上から順に読んでいけば辿り着けそう
なんですが…(^^;)…初心者にはピンとこないものなんですねぇ。
・範囲の指定→Range
・セルの指定→Cells
けっこう英単語の和訳そのままですので、プロパティ名からどんな動作を
するか?予想できる訓練をしておいて下さい。


特攻隊長まるるう  2005-08-25 00:07:18  No: 123799

…あ。
>            'wFirstAddress = wAnswerRange.Address
>            wFirstAddress = wAnswerRange
wFirstAddress はループの終了判定↓で利用してますので
>                'If Not wAnswerRange Is Nothing And wAnswerRange.Address <> wFirstAddress Then
>                If Not wAnswerRange Is Nothing And wAnswerRange <> wFirstAddress Then
このままでは誤動作を引き起こします。
勝手な改造での誤動作の文句は受け付けませんのであしからず
ご了承下さい。


超初心者  2005-08-26 04:15:13  No: 123800

ループの箇所は、どんな動きをしているのか確かめ、コードの役割を確認し
ていました。
確かに、指摘の箇所で誤動作しておりました。
元に戻しました。

特攻隊長まるるうさんのおかげで、やっと自分のやりたかった内容が完成し
無事問題なく使用できるようになりました。ありがとうございました。

まだVBを使ってやらなきゃならないこともあるので、さらに勉強して活用し
たいです。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加