Split
Split関数は文字列を区切り文字で分割して配列に変換した結果を返します。CSVファイルの読み込み時にはお世話になる関数です。
基本的な使い方は単純で、分割したい文字列と、どの文字で分割するのかを引数で渡して、Variant型か動的配列の戻り値として受け取ります。
1 2 |
Dim v v = Split("111,2222,33333", ",") |
このようにカンマ区切りの文字列を、カンマで分割すると以下のように配列化されます。通常の配列と同じため、配列の先頭は0から始まります。
1 2 3 |
Degug.Print v(0) '// "111" Degug.Print v(1) '// "2222" Degug.Print v(2) '// "33333" |
また、配列化に変換したあとにループして入れるの要素を1つずつ処理したい場合があります。その場合に配列の添え字の最大値までループすることがほとんどです。上の場合であれば「v(2)」の「2」が知りたい場合ですね。このような場合はUBound関数を使います。
1 2 3 4 5 6 7 |
Dim v Dim i v = Split("111,2222,33333", ",") For i = 0 To UBound(v) Debug.Print v(i) Next |
UBound関数の詳細については「配列の要素数を取得する(UBound、LBound)」をご参照ください。
構文
1 |
Function Split(Expression As String, [Delimiter As String = " "], [Limit As Long = -1], [Compare As VbCompareMethod = vbBinaryCompare]) |
戻り値 | 戻り値は内部処理形式がStringのVariant型の一次元配列になります。
「Dim v As Variant」のようにVariant型の変数を宣言してもいいですし、「Dim v() As String」のようにString型の動的配列として変数宣言しても構いません。 |
||||||||||||
Expression | 分割したい文字列を指定します。長さが0の””の文字列を指定した場合は空配列を返します。 | ||||||||||||
Delimiter | 省略可能です。区切り文字列を指定します。省略時は半角スペース1文字が区切り文字になります。
カンマ「”,”」を指定することが多いと思いますが、タブ文字を表すvbTabなどの定数や、「”@@”」のような2文字以上での指定も可能です。 長さが0の””の文字列を指定した場合は空配列を返します。 |
||||||||||||
Limit | 省略可能です。何分割するのかを指定します。
省略時は-1が指定され、全ての要素の配列が返却されます。”1,2,3″をカンマで区切る場合に2を指定すると”1″と”2,3″の2つの要素の配列が返却されます。 |
||||||||||||
Compare | 省略可能です。分割対象文字列に含まれる区切り文字の識別方法をVbCompareMethod列挙型の定数で指定します。
省略時はバイナリモードになります。
|
サンプルコード
よくあるCSVファイル形式や、その他のパターンでのSplit関数の使い方のサンプルコードです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
Sub SplitTest() Dim s Dim v() As String Dim c '// CSVファイル形式 Debug.Print "CSVファイル形式" s = "1,2,3,4,5" v = Split(s, ",") For Each c In v Debug.Print c Next '// CSVファイル形式(Limit=3) Debug.Print "CSVファイル形式(Limit=3)" s = "1,2,3,4,5" v = Split(s, ",", Limit:=3) For Each c In v Debug.Print c Next '// タブ区切り形式 Debug.Print "タブ区切り形式" s = "1" & vbTab & "2" & vbTab & "3" v = Split(s, vbTab) For Each c In v Debug.Print c Next '// 文字区切り形式 Debug.Print "文字区切り形式" s = "1A2A3A4" v = Split(s, "A") For Each c In v Debug.Print c Next '// 文字区切り形式(テキストモード) Debug.Print "文字区切り形式(テキストモード)" s = "1A2A3A4" v = Split(s, "a", Compare:=vbTextCompare) For Each c In v Debug.Print c Next '// 複数文字区切り形式 Debug.Print "複数文字区切り形式" s = "1@@@2@@@3@@@4" v = Split(s, "@@@") For Each c In v Debug.Print c Next End Sub |
実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
CSVファイル形式 1 2 3 4 5 CSVファイル形式(Limit=3) 1 2 3,4,5 タブ区切り形式 1 2 3 文字区切り形式 1 2 3 4 文字区切り形式(テキストモード) 1 2 3 4 複数文字区切り形式 1 2 3 4 |
分割対象文字列と戻り値の変数を同じ変数にはしないようにする
分割対象文字列と戻り値用の変数を同じ変数で使いまわすことは可能ですが、プログラミングの作法として止めておいた方がいいです。
このような書き方ですね。
1 2 3 4 5 6 |
Sub SplitSameParam() Dim s s = "1,2,3" s = Split(s, ",") End Sub |
変数の用途が途中で変わってしまうようなプログラミングは混乱の元になります。ちゃんと変数を分けて書くようにしましょう。
ご自身が書かないとしてもSplit関数においてはこういう書き方をする方が結構おられますので注意しましょう。
戻り値の変数宣言でよくある間違い
Split関数の戻り値は上でも書いたとおりVariant型の一次元配列です。
そのため、Variant型ということから変数宣言時に型を宣言せずに以下の3行目のように暗黙Variantや As Variantと書いている方がおられます。
1 2 3 4 5 6 7 |
Sub SplitTest() Dim s Dim v s = "1,,2,,3" v = Split(s, ",,") End Sub |
いやいや、
3 |
Dim v As String |
って書くとエラーになるじゃん、という話があるのですが、この書き方では文字列変数に過ぎず、戻り値が配列であることを考慮できていないためエラーになっているのであって、
3 |
Dim v() As String |
とString型の配列として書けばエラーになりません。
ちなみに私はそれらを分かった上でSplit関数を使う場合は「Dim v」しか書かず暗黙のVariantにしていることがほとんどです。理由は特にないです。強いて言えば、Split=文字列分割、というのが分かっているので使うときに間違わないしそれでよくね?って感じですかね?
Split関数はFor Eachと相性がいい
そもそもの話として、Split関数を使うということは元の文字列をバラして1つずつ処理したい、という理由がほとんどです。
そのため、Split関数を使う場合はそのあとに分割した配列をループ処理することが多くなります。そこでループ処理をどのように書くか、ということになるのですがFor Eachで書くことをお勧めします。
以下はFor Eachで書いた場合の例です。
1 2 3 4 5 6 7 8 9 |
Sub SplitLoop1() Dim v Dim s v = Split("a,b,c", ",") For Each s In v Debug.Print s Next End Sub |
For Eachを使うと1行で配列の値も取得できるためループカウンタが不要になります。
以下のようにFor文などでループカウンタを使ってもいいですけどFor Eachに慣れると面倒に感じます。
1 2 3 4 5 6 7 8 9 10 11 |
Sub SplitLoop2() Dim v Dim s Dim i v = Split("a,b,c", ",") For i = 0 To UBound(v) s = v(i) Debug.Print s Next End Sub |
ループの書き方は好みの差もあるとは思いますが、配列の要素値の取得とループの記述が1行で書けるため、個人的には圧倒的にFor Eachで書くことがほとんどです。ForやDo Loopで書く場合は「配列の何番目の場合は特殊な処理が必要」などの場合でない限ります。それ以外はループカウンタは必要なくなります。