質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.14%

  • VBA

    1240questions

    VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

  • マクロ

    156questions

    定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

Excelマクロでテキストファイルから特定文字列を含む1レコードを取得する方法

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 284

dai3922

score 17

Excelマクロで下記のようなテキストファイルから、
「Release」から始まるレコードを取得する方法を教えて頂けますでしょうか?

テキストファイルの仕様として、
1.テキストファイルによって「Version」を含むレコードが増減します。
2.「Release」で始まるレコードは必ず1レコードのみです。
3.「Release」レコードが何行目に位置するかは変わります。
4.「Release」レコードの文字列長は可変です。(「4.7.1 Windows hogehoge edition」などと記載される場合もあります。)

以上です。
instr関数とMid関数を使用していましたが、
「4.7」は取得できるものの、上記カッコ内の様にその後に文字列が続く場合があり、
理想としては「Release」で示されるValue値を改行コード手前まで取得したいと考えております。

恐れ入りますが、宜しくお願い致します。

=テキストファイルの内容=
Type    Value         
----    -----         
Version 2.0.50727.5420
Version 3.0.30729.5420
Version 3.0.4506.5420 
Version 3.0.6920.5011 
Version 3.5.30729.5420
Version 4.0.0.0       
Release 4.7           
Version 4.7.02053

'2017/12/22追記
'Alllog4は本テキストファイルの全文を格納しています。
 With fso.OpenTextFile(logPath & buf4, 1) '
  Alllog4 = .ReadAll
  .Close
 End With
'現状使用しているinstr関数とMid関数のコードです
 Net_ver = Mid(Alllog4, InStr(1, Alllog4, "Release") + 8, 7) '「Release」表記のあとのバージョンを求める。

※皆様どうもありがとうございました。
皆様のご指摘どおり、「vbCrLf」の指定で行を区切ることで実現することが出来ました。
ベストアンサーは非常に迷いましたが、現コードの一文をそのまま修正して実現することが出来ましたので
h.horikoshi様とさせて頂きました。
他の回答者の皆様には申し訳ございませんが、一つ一つのご回答がとても参考になりました。
本来、お礼をこちらに記載することは不適切かもしれませんが
記載する場所が分かりませんでしたのでこちらで述べさせて頂きます。
貴重なお時間を割いて頂き、ありがとうございました。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • ExcelVBAer

    2017/12/01 09:18

    Instr Mid で処理している部分のコードをご提示ください

    キャンセル

  • dai3922

    2017/12/22 11:43

    ご連絡が遅くなりすみません。追記致しました。

    キャンセル

回答 4

+2

instr関数とMid関数を使用していましたが、

とあるので、一連の処理はできているものと判断します。
であれば、単に行データからどう抜き出すかの回答でよいですよね。
Line変数に行データがあると仮定して、次のようにすればRelease以降の文字列が取得できます。

Mid(Line, Len("Release ") + 1)

更新された質問の回答です。
ReadAllでまとめて変数に保持しているのであれば、改行コード単位で分割してから処理するのが良いと思います。

    Const WORD = "Release"       ' 検索対象の文字列
    Dim wordlen As Integer       ' 検索対象の文字列の長さ
    Dim lines As Variant         ' 分割した行を格納する変数
    Dim line As String           ' 1行分

    ' 改行コードで分割
    lines = Split(Alllog4, vbCrLf)

    ' 検索対象の文字列の長さを取得
    strlen = Len(WORD)

    ' 行ごとにループ
    For Each line In lines
        ' 行の先頭に検索対象文字列があるか
        If Left(line, wordlen) = WORD Then
            ' 検索対象文字列以降を抽出
            Debug.Print Mid(line, wordlen + 2)
        End If
    Next

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/22 11:56

    ご連絡が遅くなりすみません。
    ご回答ありがとうございます。
    上記で追記しました「Alllog4」という変数には本テキストファイルのデータ全行が格納されている状態です。
    そのためか、Mid関数でうまく取得できていないのが現状です。

    情報が足らず申し訳ありませんでした。

    キャンセル

  • 2017/12/22 13:24

    追記しましたのでご確認ください。

    キャンセル

  • 2017/12/26 15:53

    当初よりご親切に再度ご回答頂き、ありがとうございます。
    「vbCrLf」の部分、ご指摘の通りここの単位で区切ることが出来ていなかったことが原因でした。
    コード内のコメントも非常に分かりやすくご記載頂き、感謝しております。
    今後の学習で参考にさせて頂きます。
    どうもありがとうございました。

    キャンセル

+2

Split を使用して、改行コードで分割し、該当行を探す方法が一般的かと。

Dim SplitAry() As String
SplitAry = Split(Alllog4,vbCrLf) ’改行コードによって調整

Dim i As long
for i  = Lbound( SplitAry ,1) to Ubound( SplitAry ,1)
    If Instr(1,SplitAry(i),"Release") <> 0 Then
        Net_ver = SplitAry(i)
     Exit For
    End if
Next

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/26 15:50

    ご回答頂き、ありがとうございます。
    「vbCrLf」の部分を考慮できていなかったことが原因でした。
    シンプルでわかりやすいコーディングを教えて頂きありがとうございました。
    参考にさせて頂きます。

    キャンセル

checkベストアンサー

+1

質問者さんの考え方でいいと思いますけど… 

Net_ver = Split(Mid$(vbLf & Alllog4, InStr(Alllog4, vbLf & "Release") + 2), vbLf)(0)

テキスト中にReleaeが1つしかないならInstrで十分。
Releaeの前に改行つけるのは行頭検出。
Alllog4の前に改行つけるのはReleaseがテキストの先頭にあるときの対策。
Relase以降を改行でsplitしてその最初の要素をとればよい。 

※vbLfはテキストの改行コードにあわせてください。
※上記の他、正規表現を使うともっと簡単です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/26 15:32

    ありがとうございます、まさに実現したいことが出来ました!

    キャンセル

+1

テキストファイルを取得する際に行単位で読むようにすれば話は早いです。

    Const CS_SEARCH As String = "Release"

    Dim sLine As String
    Dim f
    Set f = fso.OpenTextFile(logPath & buf4, 1)

    'ファイルの終わりまでループ処理
    Do Until f.AtEndOfLine
        '1行ずつ読み込む
        sLine = f.ReadLine
        If InStr(sLine, CS_SEARCH) > 0 Then
            Net_ver = Mid(sLine, InStr(1, sLine, CS_SEARCH) + Len(CS_SEARCH)) '「Release」表記のあとのバージョンを求める。
            Exit Do
        End If
    Loop

もし後続処理との兼ね合いなどでどうしても全文で取得しておく必要があるのであれば、Split関数を使い改行で区切るという方法もあります。

    'Alllog4は本テキストファイルの全文を格納しています。
    With fso.OpenTextFile(logPath & buf4, 1) '
        Alllog4 = .ReadAll
        .Close
    End With

    Const CS_SEARCH As String = "Release"
    Dim sLine As String

    Dim ary, i
    '改行で分割した文字列配列を作成
    ary = Split(Alllog4, vbCrLf)

    '文字列配列の数だけループ(行ループ)
    For i = 0 To UBound(ary) - 1
        '配列から1行分取り出す
        sLine = ary(i)
        '"Releace"の文字列が見つかれば
        If InStr(sLine, CS_SEARCH) > 0 Then
            Net_ver = Mid(sLine, InStr(1, sLine, CS_SEARCH) + Len(CS_SEARCH)) '「Release」表記のあとのバージョンを求める。
            Exit For
        End If
    Next

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/26 15:53

    ご親切にご回答頂きありがとうございました。
    ご指摘の通り、全文取得する必要はそもそもありませんでした。
    (別の箇所の別の処理にはなりますが全文取得で成功していたため、効率を捨てて安全に走ってしまいました。)
    お教え下さった「vbCrLf」の指定で実現することが分かりました。
    どうもありがとうございました。
    助かりました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

ただいまの回答率

91.14%

関連した質問

同じタグがついた質問を見る

  • VBA

    1240questions

    VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

  • マクロ

    156questions

    定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。