VBAで自動化 VBA一覧 データ整形・分割 分割・区切り

【VBA】特定の文字から特定の文字までを抽出する方法|Mid・InStrで実務対応

「文字列の中から必要な部分だけを取り出したい」
VBAで文字列を扱っていると、この処理は非常によく登場します。

たとえば、

  • 商品コードの中から管理番号だけを抜き出したい
  • ファイル名の中から日付部分だけを取得したい
  • メール本文やログの中から、特定の記号に囲まれた文字だけを抽出したい
  • 「開始文字」と「終了文字」の間にある値だけを使って別処理をしたい

といった場面です。

一見すると単純そうに見える処理ですが、実務では
「開始文字が見つからない」
「終了文字が複数ある」
「想定外の文字列でエラーになる」
といった問題が起きやすく、雑に書くと後で必ず困ります。

この記事では、VBAで特定の文字から特定の文字までを抽出する方法について、単に動くコードを示すのではなく、実務で再利用しやすい考え方を含めて整理します。
InStrMidLen を中心に、基本形から応用、よくある失敗、保守しやすい関数化まで丁寧に解説します。

目次

✅ VBAで特定の文字から特定の文字までを抽出する基本の考え方

文字列抽出は、VBA初心者が「なんとなく動いた」で済ませてしまいやすい処理の1つです。しかし実務では、文字列の形式が毎回完全に同じとは限りません。たまたまテストデータで動いても、本番データで開始文字や終了文字が見つからず止まることはよくあります。また、1回だけ使うつもりで書いたコードが、後から別の処理でも流用されることも珍しくありません。ここを雑に作ると、後で修正範囲が広がりやすくなります。まずは「何文字目から始まり、何文字分を切り出すのか」を落ち着いて考えることが重要です。

・VBAで文字列抽出を行うときの基本構造

特定の文字から特定の文字までを抽出する処理は、次の流れで考えると整理しやすいです。

  1. 開始文字の位置を探す
  2. 終了文字の位置を探す
  3. 開始位置と終了位置の差から文字数を求める
  4. Mid 関数で必要な部分を取り出す

つまり、抽出そのものは Mid で行いますが、どこから何文字取るかを決めるために InStr を使うというのが基本です。

・なぜMidだけではなくInStrが必要なのか

Mid は「何文字目から何文字分取るか」を指定する関数です。
一方で、実務では「3文字目から10文字取る」のように位置が固定されているとは限りません。

たとえば次のような文字列があるとします。

"商品コード[ABC123]在庫あり"

このとき欲しいのは [ ] の中にある ABC123 です。
しかし ABC123 が必ず同じ位置にあるとは限らないため、まず [] の位置を探す必要があります。

このときに使うのが InStr です。


✅ VBAで特定の文字から特定の文字までを抽出する基本コード

最初に押さえたいのは、まず確実に動く基本形です。ここで基本形を理解せずにいきなり応用コードへ進むと、少し条件が変わっただけで対応できなくなります。特に Mid の開始位置と文字数の考え方は、慣れないうちは混乱しやすいポイントです。また、開始文字そのものを含めるのか含めないのかでも式が変わります。ここを曖昧にしたまま進むと、1文字ずれたまま気付かず運用してしまうことがあります。まずは最も基本的な書き方をしっかり押さえましょう。

・開始文字と終了文字の間を抽出する基本コード

以下は、[] の間にある文字を抽出する基本コードです。

Sub ExtractBetweenBrackets()

    Dim sourceText As String
    Dim startPosition As Long
    Dim endPosition As Long
    Dim extractedText As String
    
    sourceText = "商品コード[ABC123]在庫あり"
    
    startPosition = InStr(sourceText, "[")
    endPosition = InStr(sourceText, "]")
    
    extractedText = Mid(sourceText, startPosition + 1, endPosition - startPosition - 1)
    
    MsgBox extractedText
    
End Sub

このコードを実行すると、ABC123 が表示されます。

・この書き方を採用する理由

この書き方の良い点は、処理の意図が見てすぐ分かることです。

  • sourceText:元の文字列
  • startPosition:開始文字の位置
  • endPosition:終了文字の位置
  • extractedText:抽出結果

このように意味のある変数名にしておくと、後から見返したときに理解しやすくなります。

たとえば a, b, c のような変数名でも動きますが、それでは仕様変更時に読み解くコストが高くなります。実務では「一度書いて終わり」よりも「後で読み直せる」ことの方が重要です。

・Midの文字数指定が分かりにくいときの考え方

この部分が最も混乱しやすいです。

Mid(sourceText, startPosition + 1, endPosition - startPosition - 1)

考え方は次のとおりです。

  1. startPosition + 1
    → 開始文字 [ 自体は不要なので、その次の文字から始める
  2. endPosition - startPosition - 1
    → 開始文字と終了文字の位置の差から、不要な1文字分を引く

つまり、[] 自体を除いた中身だけを抽出しています。


✅ VBAで開始文字または終了文字が見つからないときの対処法

実務で本当に困るのは、「想定どおりの文字列だけが来る」と思い込んでコードを書いてしまうことです。テストでは問題なくても、本番では区切り記号が欠けているデータや、形式が崩れた文字列が混ざることがあります。そのときにエラーで処理全体が止まると、抽出ロジックそのものより影響が大きくなります。また、エラーにならずとも空文字やおかしな値を返して気付きにくいケースもあります。ここを読まずに実装すると、後で原因調査に時間を取られやすくなります。抽出処理では「見つからない場合」を先に考えておくことが重要です。

・開始文字が見つからない場合の確認方法

InStr は、対象の文字が見つからないとき 0 を返します。
そのため、いきなり Mid を使うのではなく、先にチェックを入れる必要があります。

Sub ExtractWithCheck()

    Dim sourceText As String
    Dim startPosition As Long
    Dim endPosition As Long
    Dim extractedText As String
    
    sourceText = "商品コードABC123在庫あり"
    
    startPosition = InStr(sourceText, "[")
    endPosition = InStr(sourceText, "]")
    
    If startPosition = 0 Or endPosition = 0 Then
        MsgBox "開始文字または終了文字が見つかりません。"
        Exit Sub
    End If
    
    extractedText = Mid(sourceText, startPosition + 1, endPosition - startPosition - 1)
    
    MsgBox extractedText
    
End Sub

・終了文字が開始文字より前にある場合の対策

実務では、文字列の形式が崩れていることがあります。
たとえば終了文字の方が先に見つかるケースです。

この場合も、そのまま Mid を使うと不正な文字数になることがあります。

If startPosition = 0 Or endPosition = 0 Then
    MsgBox "開始文字または終了文字が見つかりません。"
    Exit Sub
End If

If endPosition <= startPosition Then
    MsgBox "終了文字の位置が不正です。"
    Exit Sub
End If

このように、抽出前の前提条件を確認するのが実務では重要です。

・On Error Resume Nextでごまかさない方がよい理由

この種の処理で On Error Resume Next を使ってしまう人もいますが、基本的にはおすすめしません。

理由は次のとおりです。

  • 何が原因で失敗したのか分かりにくくなる
  • 想定外のデータを見逃しやすい
  • 後続処理で別の不具合を生みやすい

抽出処理は、エラーをごまかすよりも条件分岐で明示的に守る方が保守しやすいです。

抽出処理で想定外のデータに遭遇したとき、
エラーを無視して処理を進めるのか、それとも原因を明示して止めるのかは、
VBAの設計方針そのものに関わる重要な判断です。
On Error Resume Next の便利さと危険性を正しく理解しておきたい方は、
【VBA】On Error Resume Nextでエラーを無視してエラーの制御|危険な理由もぜひ確認してみてください。


✅ VBAで特定の文字を含めて抽出する方法

抽出処理では「囲まれた中身だけ」が欲しい場合もあれば、「開始文字と終了文字も含めて欲しい」場合もあります。ここを曖昧にすると、要件と違う結果を返しやすくなります。特に実務では、区切り記号込みで保存したいケースや、そのまま別システムへ渡したいケースもあります。また、要件変更で「やはり記号も必要」となることもよくあります。最初からこの違いを理解しておくと、後の修正がかなり楽になります。同じ抽出でも、含める範囲で式が変わる点を押さえておきましょう。

・開始文字と終了文字を含めて抽出するコード

[] を含めたまま抽出したい場合は、開始位置と文字数の考え方を少し変えます。

Sub ExtractIncludingMarkers()

    Dim sourceText As String
    Dim startPosition As Long
    Dim endPosition As Long
    Dim extractedText As String
    
    sourceText = "商品コード[ABC123]在庫あり"
    
    startPosition = InStr(sourceText, "[")
    endPosition = InStr(sourceText, "]")
    
    If startPosition = 0 Or endPosition = 0 Or endPosition <= startPosition Then
        MsgBox "抽出できる形式ではありません。"
        Exit Sub
    End If
    
    extractedText = Mid(sourceText, startPosition, endPosition - startPosition + 1)
    
    MsgBox extractedText
    
End Sub

この場合、結果は [ABC123] になります。

・中身だけ抽出する場合との違い

中身だけの場合:

Mid(sourceText, startPosition + 1, endPosition - startPosition - 1)

記号を含める場合:

Mid(sourceText, startPosition, endPosition - startPosition + 1)

違いは次の2点です。

  • 開始位置を +1 しない
  • 文字数は +1 する

ここは1文字ずれやすいので、実務ではコメントで意図を残しておくと親切です。

特定の文字を含めて抽出する処理は、
単発のテクニックとして覚えるのではなく、
MidLeftRight といった基本関数の組み合わせとして理解しておくことで、
後から別の業務にも流用しやすくなります。
文字列操作の土台をしっかり整理しておきたい方は、
【VBA】文字列操作関数【Mid・Left・Right】|実務で使い倒す完全ガイドもぜひ確認してみてください。


✅ VBAで複数ある終了文字のうち最初のものまで抽出する方法

文字列の中に似た区切りが複数含まれるケースでは、「どの終了文字までを対象にするか」を意識せずにコードを書くと誤抽出しやすくなります。特にログやメッセージ文、複数の括弧を含むデータでは、最初の終了文字までを取りたいのか、最後までを取りたいのかで結果が大きく変わります。また、開始位置より前にある文字を拾ってしまうミスも起きやすいです。ここを理解していないと、テストでは通っても実データでズレが出ます。開始位置を起点にして次の文字を探す考え方を押さえておくことが重要です。

・開始位置以降から終了文字を探す書き方

InStr には、検索開始位置を指定する書き方があります。
これを使うことで、開始文字の後ろから終了文字を探せます。

Sub ExtractUsingNextEndMarker()

    Dim sourceText As String
    Dim startPosition As Long
    Dim endPosition As Long
    Dim extractedText As String
    
    sourceText = "区分[ABC123]補足[XYZ]"
    
    startPosition = InStr(sourceText, "[")
    
    If startPosition = 0 Then
        MsgBox "開始文字が見つかりません。"
        Exit Sub
    End If
    
    endPosition = InStr(startPosition + 1, sourceText, "]")
    
    If endPosition = 0 Or endPosition <= startPosition Then
        MsgBox "終了文字が見つかりません。"
        Exit Sub
    End If
    
    extractedText = Mid(sourceText, startPosition + 1, endPosition - startPosition - 1)
    
    MsgBox extractedText
    
End Sub

このコードでは、最初の [ の後ろにある最初の ] までを対象にします。

・この書き方の実務上のメリット

この書き方のメリットは、対象範囲を明確に限定できることです。

もし単純に

endPosition = InStr(sourceText, "]")

としてしまうと、ケースによっては意図しない ] を拾うことがあります。
特に複雑な文字列では、検索開始位置を指定する方が安全です。

このような抽出処理では、
InStr 関数を使って検索位置を正確に制御できるかどうかが、
コードの再利用性や保守性に大きく影響します。
文字列検索の基本をしっかり理解しておきたい方は、
【VBA】(セル内)特定の文字の最初の位置を検索(InStr関数の使用方法)もぜひ確認してみてください。


✅ VBAで抽出処理を関数化して再利用しやすくする方法

文字列抽出は一度だけ使って終わることもありますが、実務では似た処理が別のマクロにも広がりやすいです。そのたびに同じロジックをコピペしていると、修正が必要になったときに複数箇所を直すことになります。また、開始文字や終了文字だけ違うパターンも多く、関数化しておくと圧倒的に流用しやすくなります。ここを読まずに都度書きしてしまうと、後でコードが散らかりやすくなります。VBAでは「動くこと」以上に「後で使い回せること」が実務では大切です。

・再利用しやすい抽出関数の作り方

以下は、開始文字と終了文字を引数で渡せる関数の例です。

Function GetTextBetween(ByVal sourceText As String, _
                        ByVal startMarker As String, _
                        ByVal endMarker As String) As String

    Dim startPosition As Long
    Dim endPosition As Long
    
    startPosition = InStr(sourceText, startMarker)
    
    If startPosition = 0 Then
        GetTextBetween = ""
        Exit Function
    End If
    
    endPosition = InStr(startPosition + Len(startMarker), sourceText, endMarker)
    
    If endPosition = 0 Or endPosition <= startPosition Then
        GetTextBetween = ""
        Exit Function
    End If
    
    GetTextBetween = Mid(sourceText, _
                         startPosition + Len(startMarker), _
                         endPosition - startPosition - Len(startMarker))

End Function

・この関数の設計意図

この関数では、単に [] だけを前提にしていません。
引数として開始文字・終了文字を受け取ることで、次のような文字列にも対応できます。

  • 商品コード[ABC123]
  • 顧客ID:<C001>
  • 開始~終了
  • No.1234 / 完了

つまり、抽出ルールだけを差し替えて使える構成にしています。

・なぜ引数をByValにしているのか

ここでは ByVal を使っています。
これは、関数内で引数を書き換えても呼び出し元に影響させないためです。

今回のような抽出関数では、元の文字列や記号を変更する必要はありません。
そのため、値渡しの方が意図が明確です。

実務では「書き換えない前提の引数」は ByVal にしておくと、関数の役割が分かりやすくなります。

・関数を使った呼び出し例

Sub SampleUseFunction()

    Dim sourceText As String
    Dim resultText As String
    
    sourceText = "商品コード[ABC123]在庫あり"
    resultText = GetTextBetween(sourceText, "[", "]")
    
    MsgBox resultText
    
End Sub

このように書いておけば、別のマクロでも簡単に再利用できます。

再利用しやすい関数を作るためには、
処理内容だけでなく、引数の扱い方まで含めて設計しておくことが重要です。
とくに ByVal を使った値渡しは、
他の処理へ影響を与えない安全な関数設計の基本になります。
引数設計の考え方を整理しておきたい方は、
【VBA】ByValの基本と複数の値渡しの使用方法|引数の安全な扱い方もぜひ確認してみてください。


✅ VBAでセルの文字列から必要部分を抽出する実務例

抽出ロジックはメッセージボックスで確認して終わりではなく、最終的にはセルの値を加工する業務で使われることが多いです。たとえば商品コード、顧客情報、ファイル名、伝票番号など、セルに入った文字列から一部だけ抜き出して別列へ出力する場面は非常に多くあります。ここでよくある失敗は、関数だけ作って実際のループ処理や空白セル対応まで考えていないことです。また、シート上のどこに結果を出すかによっても保守性が変わります。実務に近い形で見ておくことで、記事の内容をそのまま業務へ落とし込みやすくなります。

・セルごとに抽出して別列へ出力するコード

Sub ExtractFromCells()

    Dim targetSheet As Worksheet
    Dim lastRow As Long
    Dim rowIndex As Long
    Dim sourceText As String
    Dim extractedText As String
    
    Set targetSheet = ThisWorkbook.Worksheets("データ")
    
    lastRow = targetSheet.Cells(targetSheet.Rows.Count, "A").End(xlUp).Row
    
    For rowIndex = 2 To lastRow
        
        sourceText = targetSheet.Cells(rowIndex, "A").Value
        extractedText = GetTextBetween(sourceText, "[", "]")
        
        targetSheet.Cells(rowIndex, "B").Value = extractedText
        
    Next rowIndex
    
End Sub

・このコードをこの形にしている理由

このコードでは、次の点を意識しています。

  • targetSheet を使って対象シートを明示する
  • rowIndex という意味の分かる変数名にする
  • 抽出処理は関数に分離し、ループ側をシンプルに保つ

もし抽出ロジックをループ内に直接書いてしまうと、後で修正しにくくなります。
一方、関数化しておけば、抽出ルールの変更があっても1か所直せば済みます。

・実務で気をつけたいポイント

実務では、空白セルや形式が異なるセルが混ざることがあります。
そのため、必要に応じて次のようなガードを追加すると安全です。

If Trim(sourceText) <> "" Then
    extractedText = GetTextBetween(sourceText, "[", "]")
    targetSheet.Cells(rowIndex, "B").Value = extractedText
End If

これにより、無駄な処理や意図しない空文字の連続出力を減らせます。


✅ VBAで特定の文字から最後まで抽出したい場合との違い

「特定の文字から特定の文字まで」ではなく、「特定の文字から最後まで」を取りたいケースもよくあります。この2つは似ていますが、終了位置を探すかどうかで考え方が変わります。ここを混同すると、不要に複雑なコードを書いてしまったり、逆に汎用性の低いロジックになったりします。また、関連する別記事や別処理とのつながりも理解しやすくなります。抽出の種類を整理しておくことで、どの関数をどう組み合わせるべきか判断しやすくなります。同じ文字列処理でも、要件によって使い分ける視点を持つことが大切です。

・終了文字が不要な場合の基本コード

たとえば = の後ろをすべて取りたい場合は、終了位置を探す必要はありません。

Sub ExtractFromMarkerToEnd()

    Dim sourceText As String
    Dim startPosition As Long
    Dim extractedText As String
    
    sourceText = "担当者=田中太郎"
    
    startPosition = InStr(sourceText, "=")
    
    If startPosition = 0 Then
        MsgBox "開始文字が見つかりません。"
        Exit Sub
    End If
    
    extractedText = Mid(sourceText, startPosition + 1)
    
    MsgBox extractedText
    
End Sub

このように、終了文字が不要な場合は Mid の第3引数を省略できます。

・使い分けの考え方

  • 区切られた中身だけ欲しい
    → 開始文字と終了文字の両方を探す
  • 特定の文字以降を全部取りたい
    → 開始文字だけ探して Mid で最後まで取得する

この違いを整理しておくと、文字列処理全体の設計が分かりやすくなります。


✅ VBAで特定の文字から特定の文字までを抽出するときの実務上の注意点

文字列抽出はコード自体は短く書けますが、短いからこそ油断しやすい処理でもあります。実務で問題になるのは、抽出ロジックの数行ではなく、その前提条件が崩れたときの対応不足です。また、コピペで増殖した似たコードが後から足を引っ張ることもよくあります。ここを読まずに実装すると、最初は楽でも後の保守で苦労しやすくなります。特に、文字列処理はデータ形式変更の影響を受けやすいため、将来の仕様変更まで少し意識しておくことが重要です。

・開始文字と終了文字が複数文字の場合も考えておく

実務では区切り文字が1文字とは限りません。

たとえば:

  • <開始><終了>
  • start:end

といったケースです。

今回の関数 GetTextBetweenLen(startMarker) を使っているため、複数文字にも対応できます。
ここを最初から考えておくと、後で作り直す必要がありません。

・データ形式の揺れを前提にする

実務データでは、次のような揺れが起こります。

  • 全角と半角が混在する
  • 終了記号が抜けている
  • 不要な空白が混ざる
  • 同じ列に別形式のデータが混在する

このため、抽出前に Trim や置換処理を組み合わせることもあります。

・抽出処理は単独でテストしやすい形にしておく

関数化のもう1つのメリットは、単独テストしやすいことです。
ループやシート操作と分離しておけば、文字列だけを渡して結果を確認できます。

これは実務で非常に大きいです。
不具合が出たときに、「抽出ロジックの問題なのか」「シート処理の問題なのか」を切り分けやすくなるからです。

抽出処理を安定させるためには、
文字列の形式をあらかじめ整えておくことが重要です。
とくに不要なスペースの混在は、条件判定や抽出結果の不一致を引き起こす原因になります。
データ整形の基本として、
【VBA】スペースを一括で削除【Replace関数:Trim関数】もぜひ確認してみてください。


✅ VBAで文字列抽出を自動化するときに考えたいこと

今回のような抽出処理は、単体で終わるというより、データ整形の一部として組み込まれることが多いです。たとえばCSV取込後の整形や、ファイル名から管理情報を抜き出す処理など、他のロジックと組み合わせて使われる場面が非常に多くあります。そのため、今は小さな処理でも、後で自動化全体の一部になる前提で書いておくと強いです。ここを意識せずにその場しのぎで作ると、後からマクロ全体が読みにくくなります。文字列抽出は小さな処理ですが、設計の差が出やすい部分でもあります。

・抽出処理を業務フローの中でどう使うか

たとえば次のような流れです。

  1. CSVや一覧データを取り込む
  2. 特定列から必要な値を抽出する
  3. 抽出結果を別列へ出力する
  4. その値をもとに集計・分類・照合する

このように、抽出処理は後続の業務ロジックにつながります。
だからこそ、空文字が返る場合の扱いや、不正形式をどう扱うかを決めておくことが大切です。

・実務でVBA化する価値が高いケース

次のようなケースではVBA化の価値が高いです。

  • 毎回同じ形式の文字列を何百件も処理する
  • 手作業でコピーしているとミスが起きる
  • 抽出後にさらに分類や出力処理が続く
  • 毎月・毎週の定型業務になっている

このような場面では、単なる文字列抽出でも十分に自動化効果があります。


 

✅ まとめ:VBAで特定の文字から特定の文字までを抽出する方法を実務で使いこなそう

  • 特定の文字から特定の文字までを抽出するときは、InStr で位置を探し、Mid で取り出すのが基本
  • Mid だけでは柔軟に対応しにくいため、開始位置と終了位置の考え方が重要
  • 開始文字や終了文字が見つからない場合を必ず考慮する
  • On Error Resume Next でごまかすより、条件分岐で守る方が保守しやすい
  • 開始文字・終了文字を含めるかどうかで式が変わる
  • 関数化しておくと、他のマクロでも再利用しやすい
  • 実務ではセル処理やループ処理と組み合わせることが多いため、抽出ロジックは分離しておくと強い
  • 「動けばOK」ではなく、後から読める・直せる・流用できる形で書くことが大切

VBAでの文字列抽出は、見た目以上に実務で出番の多い処理です。
そして、この処理を丁寧に作れるかどうかで、後続のデータ整形全体の安定性が大きく変わります。

特に、今回のような「開始文字から終了文字までを抜き出す」処理は、商品コード、ファイル名、メール文、ログ解析など幅広い場面で応用できます。
まずは基本形をしっかり理解し、次に関数化して再利用できる形へ育てていくのがおすすめです。

さらに実務では、このような抽出処理を他の整形処理や分割処理と組み合わせることで、手作業では面倒だった業務をかなり効率化できます。
文字列処理を単発のテクニックで終わらせず、業務の中で再利用できる部品として持つことを意識すると、VBAの使い方が一段深くなります。

    -VBAで自動化, VBA一覧, データ整形・分割, 分割・区切り