範囲取得した二次元配列どうしを結合する方法が思いつかなかったので、
一時格納用と結合用の2つの二次元配列を用意して無理やり合体させる方法を編み出した。
何らかの理由、例えばSelenium BasicでWEBページのTABLEを一括で範囲取得した二次元配列どうしを結合しようとする場合など、配列のマージと言う作業が必要になるらしいのだが、ぶっちゃけよく分からなかった。
なので、以前開発(?)した二次元配列の行を削除するときに2つの二次元配列を使って処理した方法を応用して、むりやり結合させるコードを書いたところうまくいった。
結合させるついでに不要なデータを削除するところまで一気にできたので、せっかくなのでご紹介する。
まずは結果を見ていただこう。
配列に入れたい表①~③を結合し、さらに「種類」が「A」のものだけを抽出する、という前提で作った。
最終的にM2:O18の範囲の形にすることを目標とした。
作成した二次元配列をQ2:S18の範囲に出力したが、結果としてうまくいった。
M2:O18とQ2:S18が等しければセルが緑色、異なっていればピンクになるよう条件書式を設定しているが、すべてのセルの値が緑色になり、望みどおりに出力されたことが分かる。
それではさっそくコードを見てみよう。
◆配列の疑似結合と抽出コード
Sub 配列の疑似結合() Dim preArr() As Variant Dim mainArr(1 To 24, 1 To 3) As Variant Dim i As Long, j As Long Dim cnt As Long Dim arrNum As Long Dim dCol As Long dCol = 0 cnt = 1 For arrNum = 1 To 3 preArr() = Range("A2:C9").Offset(0, dCol).Value For i = 1 To UBound(preArr, 1) If preArr(i, 2) = "A" Then For j = 1 To 3 mainArr(cnt, j) = preArr(i, j) Next j cnt = cnt + 1 End If Next i dCol = dCol + 4 Next arrNum Range("Q2").Resize(UBound(mainArr, 1), 3) = mainArr End Sub
◆解説
1)変数の宣言
各変数の説明は下記の通り
Dim preArr() As Variant
⇒表①~③を順番に一時格納する使い回し用の二次元配列
Dim mainArr(1 To 24, 1 To 3) As Variant
⇒preArrから必要なデータのみを格納して結合する二次元配列。今回はmainArrの最大値が(24,3)だと分かっているためこの表記。
Dim i As Long, j As Long
⇒preArr内の行(i)と列(r)をFor~NextでmainArrに代入するのに使用
Dim cnt As Long
⇒mainArrの代入する行を決定するのに使用
Dim arrNum As Long
⇒表①~③を順番にpreArrに代入するのに使用
Dim dCol As Long
⇒表①~③を順番にpreArrに代入する際、列方向に範囲を移動させるのに使用
2)手順について
以降の作業についてざっくりと説明すると、
- 表①をpreArrに範囲指定して代入する。
- preArr( i , 2 )が"A"の場合のみ、preArr( i , j )の値をmainArr( cnt , j )に代入して cntに+1する
- 表①~③はそれぞれ列方向に4つズレているため、dColに4を足してOffset( dCol, 4)で範囲を移動させる。
- 以降、表②~③についても同様に処理することで、最終的に表①~③が全てmainArrに格納される。
- 最後に指定したセルに値を出力する。
上記の説明で、特に2番が分かりづらいと思う。
その場合は下記の記事で詳しく解説しているので参照されたし。
今回は8×3の二次元配列が3つだということが分かっているので、あらかじめmainArrのサイズを指定しているが、分からない場合は最初に全ての二次元配列の合計を調べる処理をはさむ必要がある。
配列を一括で取得する必要がない場合は、例えばFor~next文で表①~③を直接mainArrに代入すればよく、そもそも結合は必要ない。
今回はなんらかの理由で範囲指定で二次元配列を一括で取得しなければならない場合にむりやり結合するという、ものすごく限定的な事例なので、あえてこのような回りくどい方法で配列を操作してみた。
ほぼ独学なので本職の人から見たらものすごく遠回りで変な方法なのかもしれない。
また、For~nextが2段階で入れ子になっているので、今回みたいな少ないデータなら一瞬で終わるが、数万行レベルの大きなデータでやろうと思うと処理が重くなるかもしれない。
と言うか、たぶんかなり重くなる非効率な方法だと思う。
…その辺はまだ「とりあえす動けばいい」クラスのエセVBAerなので、ご容赦いただきたい。