検証環境: Excel 365 v2509 · Excel 2021 · Excel 2019 · 最終確認 2026-06-09
要点(TL;DR) — Split は1つの文字列を区切り文字のたびに切り分け、その断片を 0 始まりの配列 として返します。文字列を連結する操作のちょうど逆です。
Sub SplitDemo()
Dim parts() As String
parts = Split("Jones,Sarah,Finance", ",") ' カンマごとに切り分ける
Debug.Print parts(0) ' Jones ← 最初の要素はインデックス 1 ではなく 0
Debug.Print parts(2) ' Finance
Debug.Print UBound(parts) ' 2 ← 最後のインデックス。3 要素なら 0,1,2
End Sub
ほとんど誰も使わない2つの引数を含めた完全な構文:
Split(expression, [delimiter], [limit], [compare])
' 対象の文字列 既定は " " 最大要素数 vbTextCompare = 大文字小文字を無視
メンタルモデル:Split は「連結の逆操作」
"a" & "," & "b" が断片を1つの文字列に貼り合わせる操作なら、Split はそれを引き剥がす道具です。すでに構造が埋め込まれた文字列 — CSV の1行、ファイルパス、姓,名 の氏名、パイプ区切りのログ行 — を渡すと、各フィールドをループで回せる配列にして返してくれます。
この捉え方が大事なのは、Split を使うべき場面と、近い関数を使うべき場面を見分けられるからです。1つの区切り文字がすべての境界を示しているとき に Split を使います。位置で断片を取りたい(5〜8 文字目)なら Mid / Left / Right の仕事。切る前にマーカーが どこにあるか を探したいなら InStr の仕事です。Split は「この文字列はリストだ、リストとして寄こせ」というための関数です。
唯一の鉄則:配列は 常に 0 始まり — Option Base 1 でも変わらない
これは動くコードと静かなバグを分ける鉄則です。
モジュール先頭に
Option Baseを何と書いても、Splitが返す配列はインデックス 0 から始まります。最初のフィールドはparts(0)、最後はparts(UBound(parts))です。
ここで多くの人が午後をまるごと失うバグを紹介します。配列を知っているがゆえに、1 からループを始めてしまうのです:
' ⚠ 誤り — 最初のフィールドを静かに取りこぼす
For i = 1 To UBound(parts)
Debug.Print parts(i)
Next i
このループはエラーになりません。ただ parts(0) に一度も触れないだけ — だから "Jones" が消え、名前がすべて欠けたレポートが出るまで誰も気づきません。直し方は、必ず 0 から回すことです:
For i = 0 To UBound(parts) ' 0 To UBound — すべての断片をカバー
Debug.Print parts(i)
Next i
UBound が返すのは 最後のインデックス であって、要素数ではありません。3 要素なら UBound = 2。要素数が欲しいなら UBound(parts) + 1 です。これを叩き込んでください — Split は 0 始まり、UBound は最上位インデックス、ループは 0 To UBound。
2つ目の罠:Split は賢くなく、文字どおりに切る
Split は区切り文字を 書いたとおりに正確に 一致させます — 前後の空白を取り除いたりせず、引用符も理解せず、正規表現でもありません。この性質が2つの場面で人を刺します。
空白を残す。 "a, b, c" をカンマで分割すると "a"、" b"、" c" になります — 2 番目以降の断片には先頭に空白が付いたままです。これを "b" と比較すると一致しません。各断片を Trim するか、", " で分割して「1つでも書式が崩れたら壊れる」ことを受け入れます:
parts = Split("a, b, c", ",")
For i = 0 To UBound(parts)
parts(i) = Trim(parts(i)) ' 各フィールドを整える(vba-mid / Trim 参照)
Next i
一致しなくてもエラーにならない。 区切り文字を含まない文字列を分割すると 要素数 1 の配列 が返り、インデックス 0 に元の文字列がまるごと入ります。だから複数フィールドが取れたと決めつける前に必ずガードを:
parts = Split(userInput, ",")
If UBound(parts) < 1 Then
MsgBox "カンマ区切りの値を入力してください。"
Exit Sub
End If
そして鋭い落とし穴 — 空文字列に対する Split("") は UBound が −1 の配列を返します。0 To UBound のループは安全に何もしませんが、parts(0) に触ろうとすると「インデックスが有効範囲にありません」で落ちます。インデックスを取る前に、入力か UBound(parts) >= 0 を確認しましょう。
知っておく価値のある2つの引数:limit と compare
limit は取得する断片の数を制限し、最後の 要素には残り全部が分割されずに入ります。「キーだけ切り出し、値はそのまま残す」のに最適です:
parts = Split("error: file not found: budget.xlsx", ":", 2)
' parts(0) = "error"
' parts(1) = " file not found: budget.xlsx" ← 残りはコロンごと無傷
compare:=vbTextCompare は アルファベットの 区切り文字を大文字小文字を無視して扱います — "1xRED2Xblue" を "x" で分割するとき、テキスト比較を指定して初めて両方の x が見つかります。ニッチですが、文字を区切り文字にした分割が境界の半分を取りこぼすときの答えです。
意見:Split は CSV パーサーではない — 正規表現で継ぎ接ぎするのはやめる
CSV ファイルを目にした瞬間、本能的に Split(line, ",") と書きたくなります。これは、引用符の中にカンマを含むフィールド — "Smith, Jr.",Sales — が来る日まではうまく動きます。Split は嬉々として "Smith" と " Jr." を2つのフィールドに切り、以降の列をすべてずらします。データは静かに壊れます。
私のルール:Split は自分が管理する区切りデータのためのものであり、CSV 形式を解析するためのものではない。 社内のパイプ区切りログ、自分で組み立てた 姓,名 のセル、\ で割るパス — 完璧です。しかし出どころが他人のシステムの本物の CSV エクスポートになった瞬間、Split は誤った道具になり、答えは Split の上に 40 行の正規表現を貼ることではありません。引用符を理解する本物のパーサー(Power Query、まともな CSV ルーチン、ライブラリ)です。Split がどこで止まるかを知っていることが、堅牢なインポートと、本番で見つかる列ずれバグの分かれ目です。
使い分け
| こういうとき… | 使うもの | 理由 |
|---|---|---|
| 1つの文字列、すべての境界に1文字の明確な区切り | Split |
フィールドを配列で返す |
| 固定位置の断片(1〜3 文字目) | Left / Mid / Right | 区切り文字なしで位置で切る |
| まずマーカーが どこにあるか を探す | InStr | 切る位置を返す |
| 引用符付きフィールドのある本物の CSV | Power Query / CSV パーサー | Split は引用符を尊重できない |
| 配列を再び1つの文字列に戻す | Join(arr, ",") |
Split のちょうど逆 |
よくある Split のミス(と直し方)
| 症状 | 原因 | 直し方 |
|---|---|---|
| 最初のフィールドが結果から欠ける | ループを 0 でなく 1 から始めた |
For i = 0 To UBound(parts) |
parts(0) で「インデックスが有効範囲にない」 |
入力が空 → UBound = −1 |
先に If UBound(parts) >= 0 でガード |
| フィールドの先頭に空白が付く | "," で分割(", " でない)し Trim なし |
分割後に各断片を Trim() |
全文が parts(0) に、複数を期待していた |
入力に区切り文字が無かった | If UBound(parts) < 1 でガード |
| CSV の列が1つずれる | フィールドに引用符付きカンマがあった | Split でなく本物の CSV パーサー |
結果代入で Type mismatch |
代入先を配列でなく As String で宣言 |
Dim parts() As String で宣言 |
文字列処理が本題を上回ったら — 「やりたいこと」を伝える
分割そのものが目的なことはまずありません。目的は「この雑然としたエクスポートを取り込み、名前を整え、マスターリストに突き合わせる」ことです。分割を仕掛け、各フィールドを Trim し、空のケースをガードし、書式が崩れた行を処理し終える頃には、解析の配管が、本当にやりたかった1つのことを覆い隠してしまいます。ExcelMaster Agent なら、その目的を普通の言葉で — 「Name 列を姓と名に分割し、Trim して、収まらない行に印を付けて」 — と言うだけで、エッジケースを処理し、まずファイルをバックアップしてから動く Python を生成します。無料で試す →
関連ガイド
- VBA Mid・Left・Right — 位置で部分文字列を取り出す
- VBA Replace — テキストを置換、その引数の罠
- VBA InStr — 文字列の中を探す
- Excel VBA の For ループ — 実例 8 選
FAQ
VBA の Split は何をする関数ですか?
Split は1つの文字列を、区切り文字(既定は空白)のたびに切り分けて部分文字列の配列にします。Split("a,b,c", ",") は "a"・"b"・"c" の3要素配列を返します。配列は 0 始まりなので、最初の要素はインデックス 0 です。
VBA の Split 配列で最初の要素が欠けるのはなぜ?
ほぼ確実にループを 1 から始めているからです。Split は Option Base 1 に関係なく 0 始まりの配列を返すので、最初のフィールドはインデックス 0 です。For i = 0 To UBound(arr) で回せば含まれます。
Split の要素数を取得するには?
UBound(arr) + 1 を使います。UBound は最大インデックスを返すのであって、要素数ではありません — 3 要素なら UBound = 2。空の入力文字列では UBound が −1 になるので、要素 0 を取る前にガードしてください。
VBA の Split で複数の区切り文字を使える?
直接はできません — Split は区切り文字を1つだけ取ります。よくある回避策は、他の区切り文字を先に Replace でメインの区切り文字に置き換えてから1回 Split することです。それ以上に複雑なら、置換を連ねるより正規表現かパーサーを使いましょう。
VBA の Split は大文字小文字を区別する?
区切り文字が文字(アルファベット)のときだけ関係します。既定では Split は区切り文字を厳密に(バイナリ)一致させます。4 番目の引数に compare:=vbTextCompare を渡すと、アルファベットの区切り文字を大文字小文字を無視して一致させます。
