• 締切済み

VBAでテキストファイル中の文字列を抽出したい

説明が冗長になりそうですが・・・ たとえば「日別訪問動物」というフォルダがあるとします。 その中には、 20140206.txt 20140205.txt 20140204.txt ・・・ と、日別に名前がつけられたテキストファイルが複数入っています。 それぞれのテキストファイルは、以下のような内容が書き込まれています。  ○20140206.txtの中身  今日わが家を訪問してきた動物は次の通りです。  3匹・・・イヌ、カエル  2匹・・・カワウソ  1匹・・・ライオン、ゾウ、オオカミ  ○20140205.txtの中身  今日わが家を訪問してきた動物は次の通りです。  5匹・・・トラ  2匹・・・ネコ、イヌ  1匹・・・クマ  ○20140204.txtの中身  今日わが家を訪問してきた動物は次の通りです。  3匹・・・ネコ、ライオン  1匹・・・カバ このときに、”最新の日付で、ネコが訪れてきたときのネコの数”をエクセルVBAで抽出し、任意のセル(たとえばA1など)に貼りつけたいと考えています。 上記の例では、「2匹」を抽出したいと考えています(2月5日に訪れたネコ2匹)。 どのようにすればうまくいくでしょうか?

みんなの回答

  • 30246kiku
  • ベストアンサー率73% (370/504)
回答No.3

私もやってみました 操作として、A列のどこかに「ネコ」と入力したら、 その横、B列に日付を、C列にx匹 を表示するものです。 フォルダの対象ファイル一覧を作った後、直近から Open 探す方法なので ファイル数が多ければ、それなりに遅くなると思います。 ファイル内の解釈は、 1行づつ読み込みます 「・」が無い行はスキップ 「・」があれば、「・」区切りの最後を「、」区切りで その区切ったものがA列に入力されたものだったら・・・・ という流れになっています。 (ベタな処理と思います) Private Sub Worksheet_Change(ByVal Target As Range)  Dim sKey As String  Dim oFso As Object  Dim sS As String  Dim sBuf As String  Dim sAry() As String  Dim v As Variant  Const CPATH = "D:\Hoge\日別訪問動物\"  Const CCHKMOJI = "・"  Const CSEPMOJI = "、"  Const adVarChar = 200  Const adUseClient = 3  Const adOpenStatic = 3  Const adLockOptimistic = 3  With Target   If ((.Count <> 1) Or (.Column <> 1)) Then Exit Sub   sKey = .Value   If (Len(sKey) = 0) Then Exit Sub   Application.EnableEvents = False   .Offset(, 1) = ""   .Offset(, 2) = ""   Application.EnableEvents = True  End With  Set oFso = CreateObject("Scripting.FileSystemObject")  With CreateObject("ADODB.Recordset")   .Fields.Append "F1", adVarChar, 255   .CursorLocation = adUseClient   .CursorType = adOpenStatic   .LockType = adLockOptimistic   .Open   For Each v In oFso.GetFolder(CPATH).Files    If (oFso.GetExtensionName(v.Name) = "txt") Then     sS = oFso.GetBaseName(v.Name)     If ((Len(sS) = 8) And (Not sS Like "*[!0-9]*")) Then      .AddNew      .Fields(0) = v.Name      .Update     End If    End If   Next   If (.RecordCount > 0) Then    .Sort = "F1 DESC"    Do While (Not .EOF)     sS = .Fields(0)     With oFso.OpenTextFile(CPATH & sS)      Do While (Not .AtEndOfStream)       sBuf = .ReadLine       If ((InStr(sBuf, CCHKMOJI) > 0) _        And (InStr(sBuf, sKey) > 0)) Then        sAry = Split(Trim(sBuf), CCHKMOJI)        For Each v In Split(sAry(UBound(sAry)), CSEPMOJI)         If (v = sKey) Then          Application.EnableEvents = False          With Target           .Offset(, 1) = Format(oFso.GetBaseName(sS), "@@@@/@@/@@")           .Offset(, 2) = sAry(0)          End With          Application.EnableEvents = True          Exit For         End If        Next        If (Not IsEmpty(v)) Then Exit Do       End If      Loop      .Close     End With     If (Not IsEmpty(v)) Then Exit Do     .MoveNext    Loop   End If   .Close  End With  Set oFso = Nothing End Sub

  • cj_mover
  • ベストアンサー率76% (292/381)
回答No.2

#1、cjです。追加レスです。 うっかり、安直過ぎました。 #1は、「"ネコ"を含む行の先頭文字列(数字)」を返すものなので、 "ネコ"に部分一致する"ヤマネコ"等にもヒットしてしまいますから、実用的でありませんでした。 完全一致版を(性質が大きく異なる)2種、挙げておきます。 "・"や"、"が区切り文字として(確実に)(全角で)使われていることが絶対条件になります。 「Sub testA()」「Sub testC()」を実行してテストしてみてください。 (◆の行の指定は確実に、、、) /// ' ' 次行以下、標準モジュール の先頭から 不足なく Option Explicit Private Const sFolPath As String = "D:\日別訪問動物\"  '  ◆ フォルダパス&\ 正しく指定 Private Const sKeysA = "サル,イヌ,カエル,カワウソ,ライオン,ゾウ,オオカミ,トラ,ネコ,クマ,カバ"  '  ← テスト用便宜上の定数 Private cn As Long  '  ← テスト用便宜上の変数 Sub testA()   For cn = 0 To 10     Re8464141a   Next cn End Sub Sub Re8464141a()   Dim rtn  '  戻り値   Dim sKey As String  '  検索キーワード   Dim sFormatPtr As String  '  日付値を基に各テキストファイル名(フルパス)を整形するパターン   Dim sMatchPtr As String  '  検索キーワードを区切り文字で挟んで完全一致を図る検索パターン   Dim sFile As String  '  各テキストファイル名   Dim sTempLine As String  '  各テキストデータを行単位で読込む変数   Dim nlen As Long  '  検索キーワードの文字長   Dim nPos As Long  '  検索キーワードがヒットした桁位置   Dim i As Long  '  ループ用(日付値相当)   Dim nFree As Integer  '  テキスト読み込み用空きナンバー   sFormatPtr = """" & sFolPath & """yyyymmdd"".txt"""   sKey = Split(sKeysA, ",")(cn)  '  ←テスト用便宜上の記述。  ◆ 検索キーワード、正しく指定   sMatchPtr = "*・*[・、]" & sKey & "、*"   nlen = Len(sKey)   nFree = FreeFile   For i = Date To Date - 365 Step -1     sFile = Format(i, sFormatPtr)     If Dir(sFile) <> "" Then       Open sFile For Input As #nFree       Do While Not EOF(nFree)         ' ' テキストデータを一行ずつ変数に読み込む         Line Input #nFree, sTempLine         nPos = InStr(sTempLine, sKey)         If sTempLine & "、" Like sMatchPtr Then           rtn = Trim$(Split(sTempLine, "・")(0))           Close #nFree           Exit For         End If       Loop       Close #nFree     End If   Next i   Dim nR As Long   If IsEmpty(rtn) Then     MsgBox "notfound"   Else '    Debug.Print "■"; rtn; "■"; sKey; "■"; Format(i, "yyyymmdd")     With Sheets("Sheet1")  '  ◆ シート名、正しく指定       nR = .Cells(Rows.Count, 1).End(xlUp).Row + 1       .Cells(nR, 1) = rtn  '  A列 に "何匹?"       .Cells(nR, 2) = sKey  '  B列 に "どの動物?"       .Cells(nR, 3) = Format(i, "yyyymmdd")  '  C列 に "いつ?"     End With   End If End Sub Sub testC()   For cn = 0 To 10     Re8464141c   Next cn End Sub Sub Re8464141c()   Dim rtn  '  戻り値   Dim oFSO As Object  '  As Scripting.FileSystemObject  '   Dim oRegExp As Object  '  As VBScript_RegExp_55.RegExp  '     Dim sKey As String  '  検索キーワード   Dim sFormatPtr As String  '  日付値を基に各テキストファイル名(フルパス)を整形するパターン   Dim sFile As String  '  各テキストファイル名   Dim sBuf As String  '  各テキストデータを流し込む変数   Dim i As Long  '  ループ用(日付値相当)   Dim flgHit As Boolean  '  各テキストファイルでマッチするかどうかフラグ   sFormatPtr = """" & sFolPath & """yyyymmdd"".txt"""   sKey = Split(sKeysA, ",")(cn)  '  ←テスト用の記述。  ◆ 検索キーワード、正しく指定 ' ' RegExp(正規表現)   Set oRegExp = CreateObject("VBScript.RegExp") ' New VBScript_RegExp_55.RegExp   With oRegExp     .Global = True     .Pattern = "(^|[\r\n])[\s\t ]*([^\s\t ・]+)・[^\n]+[・、]" & sKey & "([\r\n、]|$)"   End With ' ' FSO(ファイルシステムオブジェクト)   Set oFSO = CreateObject("Scripting.FileSystemObject")  ' New Scripting.FileSystemObject   For i = Date To Date - 365 Step -1     sFile = Format(i, sFormatPtr)     If oFSO.FileExists(sFile) Then       With oFSO.GetFile(sFile).OpenAsTextStream         sBuf = .ReadAll         .Close       End With       flgHit = oRegExp.test(sBuf)       If flgHit Then Exit For     End If   Next i   Dim nR As Long   If flgHit Then     rtn = oRegExp.Execute(sBuf)(0).SubMatches(1) '    Debug.Print "■"; rtn; "■"; sKey; "■"; Format(i, "yyyymmdd")     With Sheets("Sheet1")  '  ◆ シート名、正しく指定       nR = .Cells(Rows.Count, 1).End(xlUp).Row + 1       .Cells(nR, 1) = rtn  '  A列 に "何匹?"       .Cells(nR, 2) = sKey  '  B列 に "どの動物?"       .Cells(nR, 3) = Format(i, "yyyymmdd")  '  C列 に "いつ?"     End With   Else     MsgBox "notfound:" & sKey   End If   Set oFSO = Nothing:  Set oRegExp = Nothing End Sub

  • cj_mover
  • ベストアンサー率76% (292/381)
回答No.1

こんにちは。 比較的ベーシックなやり方で、、、。 (◆の行は運用に合わせて正しく指定。さもないとエラー。) (△の行は必要に合わせる為のオプション。) Sub Re8464141()   Const sFolPath As String = "D:\日別訪問動物\"  '  ◆ フォルダパス&\ 正しく指定   Dim rtn  '  戻り値   Dim arrS() As String  '  テキストを行ごとに区切って配列として格納   Dim sKey As String  '  検索キーワード   Dim sCurDir As String  '  現在のフォルダパスを確保   Dim sFile As String  '  各テキストファイルのファイル名   Dim sBuf As String  '  各テキストファイルのテキスト全文   Dim i As Long  '  ループ用   Dim nFree As Integer  '  テキスト読み込み用空きナンバー '  sKey = "サル" '  sKey = "カエル"   sKey = "ネコ" '  sKey = "クマ" '  sKey = "カバ"   sCurDir = CurDir()   ChDir sFolPath   nFree = FreeFile   For i = Date To Date - 365 Step -1     sFile = Format(i, "yyyymmdd"".txt""")     If Dir(sFile) <> "" Then       Open sFile For Input As #nFree       sBuf = StrConv(InputB(LOF(nFree), #nFree), vbUnicode)       Close #nFree       arrS() = Split(sBuf, vbCrLf)  '  ◆ 改行文字、正しく指定       arrS() = Filter(arrS(), sKey, True) '      arrS() = Filter(arrS(), sKey, True, vbTextCompare)  '  ←△ op.全角カナの徹底が怪しい場合       If UBound(arrS()) <> -1 Then         rtn = Split(Trim$(arrS(0)), "・")(0) '        rtn = Val(Trim$(arrS(0))) & "匹"  '  ←△ op.区切り文字"・"の徹底が怪しい場合         Exit For       End If     End If   Next i   If IsEmpty(rtn) Then     MsgBox "notfound"   Else     With Sheets("Sheet1")  '  ◆ シート名、正しく指定       .Cells(1, 1) = rtn  '  A1 に "何匹?" '      .Cells(1, 2) = sKey  '  △ B1 に "どの動物?" '      .Cells(1, 3) = sFile  '  △ C1 に "いつ?"     End With   End If        ChDir sCurDir End Sub

関連するQ&A

専門家に質問してみよう