二次元配列でJOIN関数が使えない

かつて、範囲から値だけを抜き出して、配列に格納できることを知った私は
思いました。

「これは良いことを学んだ。指定列の値を結合する際に使えそうだ」

具体的には、こんな感じです。

Sub JoinTest()
    Dim seq As Variant
        seq = Selection
        MsgBox Join(seq, vbLf)
End Sub

f:id:Infoment:20180801230437p:plain

イメージとして、こんな結果を期待しました。

f:id:Infoment:20180801230721p:plain

しかし、結果はエラー終了。

f:id:Infoment:20180802000012p:plain

長らく理由がわかりませんでしたが、偶然気が付きました。例え1列しかなくても、この配列は二次元配列であり、恐らくJoin関数は、一次元配列にしか使用できないのだと。

f:id:Infoment:20180801231040p:plain

原因がわかれば、あとは対策するだけです。そこで、二つの方法を考えてみました。

ユーザー定義関数で結合

Joinとは名ばかりで、愚直に処理(一つずつ結合)する関数です。

Public Function Joins(seq As Variant, _
                      Optional delimiter As String = "", _
                      Optional second_dimension_index As Long = 1) _
                      As String
    Dim i As Long
        Joins = seq(1, second_dimension_index)
        For i = 2 To UBound(seq, 1)
            Joins = Joins & delimiter & _
                    seq(i, second_dimension_index)
        Next
End Function

愚直ではありますが、一度に求める結果が得られるため、手軽に使える利点があります。

Join関数を使用できる形に変換

二次元配列だからJoin関数が使用できない。ならば、一次元配列にしてしまえばいい。
ということで、二段階で処理してみました。

  1. 指定範囲の値でコレクションを作成
  2. コレクションを配列に変換して結合
Sub JoinTest()
    Dim col As Collection
        Set col = New Collection        
    Dim r As Range
        For Each r In Selection
            col.Add r.Value
        Next        
        MsgBox Join(ToArray(col), vbLf)
End Sub

↓ 他言語には「ToArray メソッド」が有るらしく、そこから名付けたようです(※)。
※この関数については、直属の部下から知恵を拝借しました。

Public Function ToArray(col As Collection) As Variant
    Dim seq As Variant
        ReDim seq(col.Count - 1)        
    Dim i As Long
        For i = 0 To col.Count - 1
            seq(i) = col.Item(i + 1)
        Next
        ToArray = seq
End Function

どちらの場合も、求める結果が得られました。

f:id:Infoment:20180801230721p:plain

正しい結果が得られれば、どちらの手法でも良いと思います。個人的にはコレクションを配列に変換する関数の利便性が高いため、後者を好んで使用しています。

参考まで。


追記
今回の記事について、Thomさんに取り上げていただきました。今回の内容も、大変参考になります。いつも有難うございます。

thom.hateblo.jp

改めて見てみるとブログのデザインがThomさんと被っていて、自分でも一瞬、どちらを見ているか分からなくなりました。そこで、皆さんがThomさんのページと見間違えては申し訳ないので、取り急ぎ背景色を変えてみました。

デザインを変えると句読点代わりに入れた改行が、かえって読みにくさを助長する結果になったので、まずはここまでm(_ _)m