🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

Excel VBA の Mid・Left・Right — 位置で部分文字列を取り出す

|

Excel VBA の Mid・Left・Right — 位置で部分文字列を取り出す

検証環境: Excel 365 v2509 · Excel 2021 · Excel 2019 · 最終確認 2026-06-09

要点(TL;DR)MidLeftRight位置 で文字列から断片を取り出します — 開始位置と長さの指定です。LeftRight は、Mid を片端に固定しただけのものです。

Sub SliceDemo()
    Dim s As String
    s = "INV-2026-0042"

    Debug.Print Left(s, 3)      ' INV       ← 先頭 3 文字
    Debug.Print Right(s, 4)     ' 0042      ← 末尾 4 文字
    Debug.Print Mid(s, 5, 4)    ' 2026      ← 5 文字目から 4 文字
    Debug.Print Mid(s, 5)       ' 2026-0042 ← 長さ省略 = 末尾まで
End Sub

何より先に覚えること — VBA の文字列は 0 ではなく 1 から始まる。

メンタルモデル:内容ではなく「定規で切る」

Mid は定規です。どこから 始めて 何文字 取るかを伝えると、そこを切ります。文字が何であるかは見ず、位置を数えるだけです。Left(s, n) は「先頭からの定規」、Right(s, n) は「末尾からの定規」、Mid(s, start, len) はその2つが省略形になっている一般形です。

この1つの考え方が、これらが適切な場面とそうでない場面を正確に教えてくれます。狙う対象が 固定された既知の位置 にあるとき — 3 文字の接頭辞、末尾 4 桁、固定幅レポートの列 — に輝きます。対象が動きうる瞬間に崩れます。定規は適応しないからです。これが本記事全体の緊張点であり、InStrSplit が存在する理由です。

唯一の鉄則:1 始まり。その off-by-one が最頻バグ

ほとんどの言語から来ると、指が 0 始まりの位置を打ち込みます。VBA はそうではありません。

Mid(string, start, length)start = 1最初の 文字です。Mid("Excel", 1, 2)"xc" ではなく "Ex" です。

これを間違えてもエラーは出ません — 1 つずれた誤った文字が返るだけで、これはクラッシュよりはるかに厄介です。もっともらしく見えるからです:

Debug.Print Mid("Excel", 1, 2)   ' "Ex"  (正しい — 1 が最初の文字)
Debug.Print Mid("Excel", 0, 2)   ' 実行時エラー 5 — 位置 0 は存在しない
Debug.Print Mid("Excel", 2, 2)   ' "xc"  (2 文字目から開始)

対になる鉄則:Mid で長さを省略すると start から末尾まで返す。 これは回避すべきバグではなく、「ここから残り全部」を最もきれいに言う方法です:

extension = Mid(filename, InStrRev(filename, ".") + 1)   ' 最後のドット以降すべて

ほとんど誰も知らないこと:Midステートメント でもある

Mid は2つあります。関数 は文字を読み出します。ステートメント は文字をその場で書き込みます — 長さを変えずに文字列の一部を上書きします:

Dim s As String
s = "2026-00-15"
Mid(s, 6, 2) = "06"      ' 6 文字目から 2 文字を上書き
Debug.Print s            ' "2026-06-15"  ← 同じ長さのまま、その場で修正

= の左辺にある Mid(s, 6, 2) = "06" がステートメントです。Left & 新文字列 & Right で組み直すより速く、固定幅フィールドを修正する慣用句です。メンタルモデルに沿った注意点 — 長さは決して変わらない。長い置換文字列を代入すると、VBA は窓に合わせて単純に切り詰めます。定規は伸びません。

Left/Right/Mid ファミリーを1ブロックで

Left(s, n)          ' 先頭 n 文字
Right(s, n)         ' 末尾 n 文字
Mid(s, start)       ' start から末尾まで
Mid(s, start, len)  ' start から len 文字
Len(s)              ' 総文字数(切り取り範囲の上限に使う)

LeftRight は別の概念ではありません — 片方の座標を固定した Mid です。Left(s, n)Mid(s, 1, n)Right(s, n)Mid(s, Len(s) - n + 1)。Mid が腑に落ちれば、残り2つはおまけです。

意見:位置のハードコードは、マクロで最も脆い1行

Mid(s, 5, 4) は、テストした1行ではきれいに読めます。やがて1文字短い値が来て全位置がずれ、「年」の抽出が "026-" を返します。位置指定の切り取りは前提 — データは常に私のサンプルと同じ形をしている — を埋め込んでおり、実データは最初の機会にそれを破ります。

私のルール:位置が本当に固定のときだけ Left/Right/Mid を使う — 自分が管理する書式、固定幅エクスポート、レイアウトが保証されたコード。境界が 内容 に依存する瞬間(最初の空白の前のテキスト、ダッシュの後の部分、2つのマーカーの間)には、数字のハードコードをやめます。InStr で境界を見つけて それ を Mid に渡すか、きれいな区切りがあれば Split を使います:

' 脆い:ダッシュが常に 4 文字目だと仮定
code = Left(s, 3)

' 堅牢:ダッシュを見つけてそこで切る — 長さに関係なく動く
code = Left(s, InStr(s, "-") - 1)

2つ目は関数1つ分長いだけで、現実との接触に耐えます。その取引はほぼ常に価値があります。

使い分け

こうしたい… 使うもの 注意点
先頭 N 文字 Left(s, n) N が Len(s) より大きくても全文を返すだけ(安全)
末尾 N 文字 Right(s, n) 同上 — N が大きすぎてもエラーにならない
固定位置から N 文字 Mid(s, start, n) start は 1 始まり、start = 0 はエラー
ある位置から末尾まで全部 Mid(s, start) 長さ引数を完全に省略する
文字をその場で上書き Mid(s, start, n) = "…" 長さは変わらない — はみ出す文字は捨てられる
位置が動きうる断片 InStr + Mid、または Split 数字をハードコードしない

よくある Mid/Left/Right のミス(と直し方)

症状 原因 直し方
結果が1文字ずれる start を 0 始まりと扱った start = 1 が最初の文字
「プロシージャの呼び出し、または引数が不正」(エラー 5) Mid(s, 0, …) または負の長さ start ≥ 1、長さ ≥ 0
短い値で抽出が壊れる 位置をハードコード Mid(s, 5, 4) まず InStr で境界を特定
Mid ステートメントで文字列が伸びなかった 仕様どおり — その場で上書き 長さを変えるなら Left & 新 & Right で組み直す
Left(s, 50) で全文が返った N が長さを超えた 期待どおりの動作。必要なら Len(s) で上限を

切り出しロジックが主役を奪ったら — 「結果」を伝える

1つのセルから請求番号を取り出すのは2行です。微妙に異なる3つの書式で来る 4 万行から取り出すのは — ダッシュ付き、ダッシュ無し、余計な接頭辞付き — InStrMid・長さチェック・フォールバックの絡まりとなり、本来の意図を埋めてしまいます。ExcelMaster Agent なら「請求コードから 4 桁の年を、周りの書式がどうあれ抽出して」と言うだけで、バリエーションを処理し、まずブックをバックアップしてから動く Python を生成します — off-by-one も、位置のハードコードもなしで。無料で試す →

関連ガイド

FAQ

VBA の Mid・Left・Right の違いは? 3 つとも位置で部分文字列を取り出します。Left(s, n) は先頭 n 文字、Right(s, n) は末尾 n 文字、Mid(s, start, len)start から len 文字を取ります。Left と Right は、Mid を文字列の片端に固定した特殊形です。

VBA の Mid は 0 始まりですか、1 始まりですか? 1 始まりです。Mid("Excel", 1, 2)"Ex" を返します — 位置 1 が最初の文字です。0 を開始位置にすると実行時エラー 5 になります。この off-by-one は、0 始まりの言語から来た人にとって最頻の Mid バグです。

Mid である位置以降をすべて取得するには? 長さ引数を省略します — Mid(s, start)start から末尾までの部分文字列を返します。InStr と組み合わせれば、Mid(s, InStr(s, "-") + 1) で最初のダッシュ以降がすべて取れます。

VBA の Mid ステートメントとは? 代入の左辺にある Mid(s, start, length) = "text" は、文字列の長さを変えずに文字をその場で上書きします。組み直すより速く、固定幅フィールドの修正に最適です — ただし窓より長い置換文字列は切り詰められます。

一部の行で Mid の抽出が誤るのはなぜ? ほぼ常に、すべての値が同じ長さだと仮定した位置のハードコードです。境界が固定オフセットでなく内容に依存するなら、InStr で見つけて Mid に渡すか、区切りがあれば Split を使いましょう。