こんにちは、Ryoです。
今回はVBAの配列に焦点を絞ってご紹介していきたいと思います。
使い慣れると大丈夫なのですが、やはり配列って最初のころは???な感じになって
わかりにくかったりイメージしにくかったりしますよね。
配列自体の基本的な部分等、詳細な解説から入るのが本来良いのだろうとは思いますが、
業務上必要があって検索してる時というのは、どちらかというと「自身のやりたいことは
どうすれば具現化できるのか?」というのが優先されるように思います。(私もそうです)
その観点で、配列自体の詳細な解説は簡単に済ませ、私が実務上使用する例に合わせて
配列の使い方や記述等々の解説に焦点を当てていきたいと思います。
1.配列について
先ず配列は1次元配列と2次元配列があります。
この時点で聞き慣れないと??ってなりますが、以下に簡単にご説明します。
配列は指定しなければ「0」から始まります。
1次元配列はその名の通りで配列1個に対し、格納できるのも1個ですから判りやすいですね。
2次元配列は縦(赤字:1次元)×横(青字:2次元)の複数で、多次元配列とも言います。
例えばA(9,9)であれば10×10を指定しており、略図の様な配列となります。
要するに、1次元配列や二次元配列を宣言して指定した範囲の箱を準備し、そこに入れる
データを変数で扱う=配列となります。
1次元配列を例えると「10段(0~9)のチェスト」があって、「各ドロワーに1個」
収納できるというイメージです。
2次元配列は先程の例で言えば、「10段(0~9)のチェスト」があり、「各ドロワーに
10個」収納できる仕切りがある状態をイメージしていただければ想像しやすいかと思います。
1次元、2次元配列共に格納した場所を示す為にA(9)やA(9,9)という数字があり、
これをインデックスと言います。
二次元配列でA(5,4)であれば、チェスト6段目ドロワーの手前から5番目に格納した
ということを示すということですね。
ざっくりとした概要ですが、これがイメージ出来れば後はそれほど難しくないと思います。
次に配列の宣言や実用例を交えて解説していきます。
2.配列の宣言
基本的な宣言は以下の通りになります。
「1次元配列」・・・Dim 変数名(要素数)As Type(型)
「2次元配列」・・・Dim 変数名(1次元要素数,2次元要素数)AS Type(型)
上述の略を例にすると、
Dim A(9) As String・・・1次元配列
Dim A(9,9) As String・・・2次元配列 となります。
Type(型)については格納したいデータによって変わります。
整数であればIntegerやLong、文字ならString、浮動小数点数型ならSingleやDoubleですね。
オールラウンドなVariant(格納したデータによって自動的に型を選択)もあります。
又、配列要素の開始番号を指定する方法もあります。
【1次元配列】・・・番号指定
Dim A(2 To 7)As String
この場合はA(2)~A(7) を使うという宣言になります。
【2次元配列】・・・番号指定
例えばA(0,0)の様な0部分を使わずに10×10としたい場合は、
Dim A(1 To 10, 1 To 10) As String
この様に記述することで配列は1から始まります。
他には不確定要素数の場合に使用する動的配列の定義がありますが、
そこは後述する実用例を兼ねたサンプル等で合わせてご説明します。
3.配列の実使用例と解説
例1)Sheet内図形や写真等の名前を格納し、写真以外を削除する。
Sub Ex_Picture() Dim Pic_Name(1 To 10) As Variant 'ここでは例として配列インデックスを1~10と指定 For i = ActiveSheet.Shapes.Count To 1 Step -1 Pic_Name(i) = ActiveSheet.Shapes(i).Name If InStr(Pic_Name(i), "Picture") <> 1 Then ActiveSheet.Shapes(Pic_Name(i)).Delete End If Next i Erase Pic_Name End Sub
本例ではアクティブシート内に10ヶ以下の写真や図形がある場合としています。
このコードを実行すると、シート内の対象を配列変数Pic_Nameに格納し、
“Picture”が含まれないものを削除します。
用途例としては、特定の図等を残して他を消去したい場合等に使えます。
例2)特定のセル範囲データを配列に格納し別Sheetに書き込む
Sub Ex() Dim Ex(30) As Long Dim i,Cnt As Integer Cells(6, 3).Select Do While ActiveCell <> "" i = i + 1 Ex(i) = ActiveCell ActiveCell.Offset(1, 0).Select Cnt = i Loop '別シートに書き出す WorkSheets("Sheet2").Activate Cells(1, 1).Select For i = 1 To cnt ActiveCell = Ex(i) ActiveCell.Offset(1, 0).Select Next i Erase Ex End Sub
対象Sheetのセル「C6」から縦にデータ入力(配列要素数内)されている場合、直接セルを
指定しセルに空欄が出来るまでループで回しながら配列に順次データを格納し、別Sheetに
書き出す例ですが、この場合はデータ読み書き範囲が常に固定されていることが前提です。
現実的には、Sheet内の配置を変えることやデータ数の変化が発生することもありますので、
柔軟に対応する為には配列を「動的配列」として定義する必要があります。
例3)動的配列の利用
動的配列を使用する場、冒頭は配列であることのみを宣言します。
Sub Dynam_Array() Dim Ex_D() As Double Dim Title, cell_Ad, Col As String Dim Row_Pos, Col_Num, LastRow, Count, i As Integer For Each Title In Range("A1:N50") 'Sheet全体範囲指定 If Title = "Data" Then Title.Select Row_Pos = ActiveCell.Row cell_Ad = Title.Address(True, False) Col = Left(cell_Ad, InStr(cell_Ad, "$") - 1) Col_Num = Asc(Col) - 64 '列番号アルファベットを数値化 LastRow = Cells(Rows.Count, Col_Num).End(xlUp).Row 'データ入力最終行 Count = LastRow - Row_Pos 'データ数 End If Next ReDim Ex_D(Count) As Double For i = 1 To Count Ex_D(i) = Cells(Row_Pos + i, Col_Num) Next i '//以降は別Sheetに書き出す部分として例2)同様 Worksheets("Sheet2").Activate Cells(1, 1).Select For i = 1 To Count ActiveCell = Ex_D(i) ActiveCell.Offset(1, 0).Select Next i Erase Ex_D End Sub
このコードは下図の様な”Data”の下部に記載されたデータを抽出・格納するものです。
入力されるデータ数や入力された範囲も動的に対処する必要がありますので、
For Eachで検索範囲をRange指定し、その中でキーとなる語句(この場合はData)
を抽出します。
その後、その位置を選択して行番号とセルアドレスを取得し、そのアドレスから列番号
(アルファベット)を抜取ってAsc関数により数値化します。
次にデータが入力されている列の最終行を抽出して行番号を取得し、その行番号と”Data”を
抽出した行番号を引いてデータ数を算出します。
ここまででデータ数が判りましたので、ReDimにより配列要素数(=Count)を指定します。
後はFor文でデータ数分繰り返し処理を行い、先程までに数値として取得したRow_Pos
(=行番号)、Col_Num(列番号)をCellsで指定して繰り返し処理を行い配列にデータを
格納し、別Sheet等へ出力します。
この様な形で処理できる様に記述しておくと、ある程度の変化には柔軟に対応出来るので
比較的使いやすいのではないかと思います。
例4)2次元配列の一括データ格納
Sub Arry_bulk() Dim SN As Variant Dim In_data As Variant '//S/Nの表記をアクティブシート内から探しアドレスを取得 For Each SN In Range("A1:L30") If SN = "S/N" Then SN.Select '選択したセルを基点に空白セルに囲まれた範囲を選択する Selection.CurrentRegion.Select '選択した範囲を配列に格納する In_data = Range(Cells(Selection(1).Row, Selection(1).Column), _ Cells(Selection(Selection.Count).Row, Selection(Selection.Count).Column)) End If Next End Sub
例3)と同様にキーとなる語句(この場合は”S/N”)を抽出します。
次のSelection.CurrentRegion.Selectは空白セルに囲まれた領域を自動的に選択してくれる
ものなので、その選択した範囲から基点位置(左上)と最終位置(右下)を指定し配列に格納しています。
こうすることで2次元配列に指定範囲を一括で格納することが出来ます。
この場合、配列は1から始まりますのでご注意ください。
以上、実際に私が実用しているコードの中から抽出してご紹介しましたが、
何かお役に立てそうな部分があれば幸いです。
説明自体がかなりザクっとしてますから、今後それぞれの部分に特化して記事書いて
いこうと思ってますので、宜しくお願いします。
Ryo