[[20180804135830]] 『VBAの二次元配列の文字列化について』(にゅるん) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『VBAの二次元配列の文字列化について』(にゅるん)

お世話になっております。

Excel VBAでよく使う
 Dim Data as Variant
 Data = Range("A1:C3")
のような二次元配列データを任意の区切り文字で、単一の文字列化する関数Join2()を自作してみました。
(デフォルト値はCSV向けの設定ですが、あくまで汎用的のものを作るのが目的です)

質問1.もっと高速に二次元配列を結合する方法はありますか?
質問2.VBAには二次元配列を一気に代入する構文はないのでしょうか。
たとえば一次元配列向けのArray()を使って記述を簡素化する方法はありますか?

拙いですが現時点で完成済みのコード全文を載せます。

 '二次元配列をCSV等の文字列に変換する。
Function Join2(arr As Variant, Optional Delimiter1 As String = ",", Optional Delimiter2 As String = vbCrLf) As Variant
    Dim i As Long, j As Long
    Dim arr1() As Variant
    Dim arr2() As Variant
    ReDim arr1(1 To UBound(arr, 1))
    ReDim arr2(1 To UBound(arr, 2))
    For i = 1 To UBound(arr, 1)
        For j = 1 To UBound(arr, 2)
            arr2(j) = arr(i, j)
        Next
        arr1(i) = Join(arr2, Delimiter1)
    Next
    Join2 = Join(arr1, Delimiter2)
End Function

 'テスト用コード
Sub test_Join2()
    Debug.Print vbLf & "test_Join2 - " & Format(Now, "hh:mm:ss")

    Dim TestPattern As Dictionary
    Dim arr() As Variant
    Dim S As Variant
    Dim V As Variant

    Set TestPattern = New Dictionary

    ReDim arr(1 To 3, 1 To 3)
    arr(1, 1) = "aaa": arr(1, 2) = "bbb": arr(1, 3) = "ccc"
    arr(2, 1) = "ddd": arr(2, 2) = "eee": arr(2, 3) = "fff"
    arr(3, 1) = "ggg": arr(3, 2) = "hhh": arr(3, 3) = "iii"
    TestPattern.Add "Normal", arr

    ReDim arr(1 To 3, 1 To 3)
    arr(1, 1) = "aaa": arr(1, 2) = "": arr(1, 3) = "ccc"
    arr(2, 1) = "ddd": arr(2, 2) = "eee": arr(2, 3) = ""
    arr(3, 1) = "": arr(3, 2) = "hhh": arr(3, 3) = "iii"
    TestPattern.Add "Irregular", arr

    For Each S In TestPattern.Keys
        V = Join2(TestPattern(S))
        Debug.Print "[" & S & "]" & " >> [" & V & "]"
    Next
End Sub

以上、よろしくお願いいたします。

< 使用 Excel:Excel2016、使用 OS:unknown >


 速くしたいのか、記述を簡素化したいのかわからないけど。

 Sub test_Join2()
     Debug.Print vbLf & "test_Join2 - " & Format(Now, "hh:mm:ss")
     Dim TestPattern As Dictionary
     Dim i As Long, txt As String, e
     Dim arr() As Variant
     Const delim As String = ","
     Set TestPattern = New Dictionary
     ReDim arr(1 To 3, 1 To 3)
     arr(1, 1) = "aaa": arr(1, 2) = "bbb": arr(1, 3) = "ccc"
     arr(2, 1) = "ddd": arr(2, 2) = "eee": arr(2, 3) = "fff"
     arr(3, 1) = "ggg": arr(3, 2) = "hhh": arr(3, 3) = "iii"
     TestPattern.Add "Normal", arr
     arr(1, 1) = "aaa": arr(1, 2) = "": arr(1, 3) = "ccc"
     arr(2, 1) = "ddd": arr(2, 2) = "eee": arr(2, 3) = ""
     arr(3, 1) = "": arr(3, 2) = "hhh": arr(3, 3) = "iii"
     TestPattern.Add "Irregular", arr
     For Each e In Array("Normal", "Irregular")
         For i = 1 To UBound(TestPattern(e))
             txt = txt & IIf(txt <> "", vbCrLf, "") & Join(Application.Index(TestPattern(e), i, 0), delim)
         Next
         MsgBox txt, , e: txt = ""
     Next
 End Sub
(seiya) 2018/08/04(土) 14:38

seiya様
質問2は質問の仕方が悪かったようです。
VBAで二次元配列に定数を投入する時にに私は
     arr(1, 1) = "aaa": arr(1, 2) = "bbb": arr(1, 3) = "ccc"
     arr(2, 1) = "ddd": arr(2, 2) = "eee": arr(2, 3) = "fff"
     arr(3, 1) = "ggg": arr(3, 2) = "hhh": arr(3, 3) = "iii"
と書きましたが、C#とかでは
{{"aaa","bbb","ccc"},{"ddd","eee","fff"},{"ggg","hhh","iii"}}
と、添字を書かないで代入出来ますよね。

VBAでも一次元配列であれば
arr = Array("aaa","bbb","ccc")
のようにして一括で代入できるので、二次元配列の代入方法も実はあるのだろうか?
というのが質問2になります。

質問1の解については頂いたコードを関数化して試したいと思います。
(にゅるん) 2018/08/04(土) 16:16


 文字数に制限(256)はありますが、

 arr1 = [{"aaa","bbb","ccc";"ddd","eee","fff";"ggg","hhh","iii"}]

 こんな感じでできます。
(seiya) 2018/08/04(土) 16:22

なるほど。Evaluateという手がありましたか!
今後使わせて頂きたいと思います。

それと頂いたコードを検証してみました。
よく見ると「txt = txt & ○」を使っているのでとてつもなく遅いですね。

10文字データを10000件×100列のデータ結合を10回したところ
私のものは0.04秒
頂いたものは70.1秒

他に良い方法がありましたらよろしくお願いいたします。
(にゅるん) 2018/08/04(土) 17:00


 その部分は私も配列に入れてJoinする方法を取ります。
 もう一つは文字列の Memeory Management という方法もありますが速度的に速くなるかはわかりません。

 参考にしてください。
http://www.moug.net/tech/exvba/0140045.html
(seiya) 2018/08/04(土) 17:11

 Evaluate 以外にこんなこともできます。
 この方法では要素が1つでも256文字以上になるとTransposeメソッドがエラーになりますが、それ以外は
 此方の方が使い勝手が良いでしょう。

     arr1 = Application.Transpose(Array(Array("aaa", "ddd", "ggg"), _
            Array("bbb", "eee", "hhh"), Array("ccc", "fff", "iii")))
(seiya) 2018/08/04(土) 17:51

seiya様
度々ありがとうございます。
頂いた情報を今後に活かしたいと思います。

ひとまずこの質問は〆ますが、時々確認に来ますので他に情報がありましたらよろしくお願いいたします。
(にゅるん) 2018/08/04(土) 18:59


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.