Excel VBA > VBA:実務活用 > 文字列の連結で時間がかかるとき
このエントリーをはてなブックマークに追加

文字列の連結で時間がかかるとき

文字列の連結は文字数が長くなるほど時間がかかる

ある程度のプログラムをしていると、文字列を連結する場面はよくあると思いますが、それが恐ろしく時間がかかるということはないでしょうか?
そんな時に有効な方法です。

MIDステートメントを使って高速化

VBAにはMIDステートメントがあります(MID関数ではないので注意です)。
これを使うことで、文字連結に費やす処理時間を大幅に改善できます。
手順としては下記のとおりです。
1.あらかじめ必要な文字数の文字を変数に埋め込む
(下記は文字列「a」を100個変数に格納した場合)

strChar = VBA.String(100, “a”)

この変数の中をのぞいてみると・・

2.埋め込んだ文字をMidステートメントで入れ替える(置換するイメージ)
(下記は上記の変数を1文字目~10文字目までに右辺の文字を格納)

Mid(strChar, 1, 10) = “あいうえおかきくけこ”

この変数の中をのぞいてみると・・

このように先頭から文字を置換するようなイメージを繰り返します。

実際にテストしてみる

実際に「通常の連結」と「MIDステートメント使用」の違いを見てみます。

Sub 文字列連結でMidステートメントとの比較()

    Dim strChar As String
    Dim lng As Long
    Dim strTime As String
    Dim dblTimer As Double

    ‘―――――――――――――――-
    ‘通常の連結
    ‘―――――――――――――――-
    dblTimer = Time

    For lng = 1 To 100000
        strChar = strChar & “あいうえおかきくけこ”
    Next lng

    strTime = “通常:” & Time – -dblTimer

    ‘―――――――――――――――-
    ‘Midステートメント使用
    ‘―――――――――――――――-
    Dim lngPos As Long

    dblTimer = Time

    ‘あらかじめ必要な文字数分を確保
    strChar = VBA.String(10 * 100000, “a”)

    lngPos = 1 ‘ループ内で開始する文字位置

    For lng = 1 To 100000
        Mid(strChar, lngPos, 10) = “あいうえおかきくけこ”
        lngPos = lngPos + 10
    Next lng

    strTime = strTime & vbCrLf & “Mid:” & Time – -dblTimer

    ‘時間発表
    MsgBox strTime

End Sub

結果はこんな感じでした。驚くほど速いですね。

実務上での可変対応という課題

先のサンプルでは下記のようにあらかじめ必要な文字数の部分で、「入れ替える文字数」と「ループ回数」を入れています。

strChar = VBA.String(10 * 100000, “a”)

しかし実際にはループ回数が可変、格納する文字数も可変だったりするため、事前にどの程度文字を確保しておくのかが難しい場合が多かったりします。
このような場合、(私の場合は)一定の文字数を推測して確保しておきます。
そして処理の途中で、必要に応じて確保する領域を拡大するようにしていします。

    For lng = 1 To 100000
        Mid(strChar, lngPos, 10) = “あいうえおかきくけこ”
        lngPos = lngPos + 10

        ‘残りの「a」の文字をカウント
        If UBound(VBA.Split(strChar, “a”)) < 100 Then
            strChar = strChar & VBA.String(10 * 100000, “a”)
        End If

    Next lng

要は残り(変換前)の文字数が何文字かがわかれば、どんな形でもよいと思いますが、このようにして確保した領域が少ない場合に拡張しています。
上記の方法は、文字列を配列化するための時間がかかるため効率的ではなく、lngPosなどで対処したほうが良さそうですが、最近のお気に入りだったので使いました(笑)。

ただし、この場合だと今度はループ終了後に変換されなかった文字が余る場合も出てきます。そのため最後の処理で必要な文字列にしています。また文字数を確保するために使用した「a」という文字も実際には使われてない文字(空白)などにするほうが都合がよい場合もありいます。それに合わせた形で下記のようにしています。

strChar = VBA.Replace(strChar, “a”, “”)

カテゴリ:VBA:実務活用