VBA使ってますか?
使いやすいですか?
VBAは簡単にユーザーフォームを作れて、とっても便利なんですが、1つだけモヤモヤする部分があるんですよね。
それが今回紹介する配列の使い方。
他のプログラミング言語をやった事ある人だと、VBAの配列について「分かりづらい」と共感してくれるかなと思います。
宣言の仕方と使える要素数が、なんかモヤモヤするんですよね~
慣れちゃえば問題ないのですが。
そんなVBAで配列を使う方法と注意点を紹介します。
配列の宣言と初期化の方法
配列の宣言・初期化の方法は主に2つあります。
どちらが使いやすいか、好みの方を見つけてください。
配列として宣言
オーソドックスな配列の宣言と初期化方法です。
'配列として宣言
Dim b(3) As Integer
'初期化
b(0) = 0
b(1) = 1
b(2) = 2
b(3) = 3
例ではInteger(整数)型として宣言しましたが、Double型でもString型でもOKです。
重要なのは、宣言時の要素数は最後の要素番号を書くこと。
Dim b(3) As Integer
さて、C言語とか他のプログラミング言語をやったことある方なら、少し困惑するかもしれません。
私もそうでした。
VBAの配列は他の言語と違って、b(3)と宣言したら要素番号0から3まで使用できます。
つまり、4つ格納できるのです。
C言語なら、b[3]と宣言したら、使うのはb[0]からb[2]までで3つですよね。
なんというか、ややこしい。。。
ここが冒頭で書いた“モヤモヤ”する点です。
私は個人的に、b(3)と定義したらb(0)~b(2)まで使用して、b(3)は使用しない方針で統一していました。
その方が頭がこんがらがらないので。
でも、人によってはb(1)~b(3)を使用する人、b(0)~b(3)まで全部使用する人がいるはずです。
もし他の人が書いたVBAのコードを手直ししなければならない場合、配列は要注意です。
どのように配列の番号を使用しているか、注意して読み解いていく必要があります。
自分しか見ることがないコードなら自分のルールに則って書けばいいですが、そうでない場合は配列の使い方をコメントに書き残しておくことをおススメします。
Variant変数で宣言する場合
Variant変数は何でも入れられる便利な変数です。
もちろん配列もOK。
文字列を分割する際などはVariant変数を使います。
Variant変数として変数を定義する場合の宣言と初期化方法はこちらです。
'Variantで宣言
Dim a As Variant
'初期化
a = Array(0, 1, 2, 3)
初期化はArrayでサクッとできて楽ですね。
こちらも配列の要素数はa(0)~a(3)までの4つです。
Variant変数は楽ですが、個人的には、どの要素番号にどの値を代入したかがパッと見で分かる配列として宣言する方が好きです。
どちらがいいかは個人の好みですので、使いやすい方を使ってください。
要素数の取り出し
Variant変数で宣言された場合は特に、配列の要素数が何個なのか、最大要素番号が何なのか知りたくなる時があります。
そんな時に使用するのがこちらです。
配列の始めの要素番号を取得する:LBound(配列変数名)
配列の最後の要素番号を取得する:UBound(配列変数名)
実際に使ってみたのがこちら
MsgBox "配列aの" + vbCrLf _
+ "始めの要素番号:" + CStr(LBound(a)) _
+ vbCrLf _
+ "終わりの要素番号:" + CStr(UBound(a))
CStrは文字列に変換する関数です。
配列の中身の取り出しでもLBound,UBoundは使えます。
また、For文でLBoundからUBoundまでループしてあげると、全部の要素をまわることができます。
MsgBox "配列bの" + vbCrLf _
+ "始めの要素の中身:" + CStr(b(LBound(b))) _
+ vbCrLf _
+ "終わりの要素の中身:" + CStr(b(UBound(b)))
Dim str As String
str = "配列bの中身一覧" + vbCrLf
For i = LBound(b) To UBound(b)
str = str + CStr(b(i)) + vbCrLf
Next i
MsgBox str
LBound,UBoundで配列の最初と最後の要素を取得した結果
Forループで配列の中身を取得した結果
動的配列の使い方
コードを書いている時点で配列の要素数が分からない場合がありますよね。
そんな時は動的配列を使います。
今回は、以下のようにExcelシートに数字を適当に羅列して、それを配列に格納してみます。
配列は動的配列で宣言して、要素数はシートの最終行から自動で決まるようにしました。
動的配列を使ってシートのA列の数字を配列に格納したコードがこちら。
'動的配列
Dim c() As Integer 'cは要素番号1から使用する
Dim erow As Integer
erow = Cells(Rows.Count, 1).End(xlUp).Row 'A列の最終行
ReDim c(erow) As Integer '動的配列cの再定義
str = "動的配列cの中身" + vbCrLf
For i = 1 To erow
c(i) = Cells(i, 1).Value 'A列の値を配列に格納
str = str + CStr(c(i)) + ","
Next i
MsgBox "配列cの" + vbCrLf _
+ "始めの要素番号:" + CStr(LBound(c)) _
+ vbCrLf _
+ "終わりの要素番号:" + CStr(UBound(c))
MsgBox str
まず動的配列cを
Dim c() As Integer
で要素数を決めないで宣言します。
そして、A列の最終行(要素数)が分かった時点で
ReDim c(要素数) As Integer
と、要素数を指定して再定義します。
※今回、シートの行番号と配列の要素番号を同じにしたかったので、配列のc(0)には値を代入していません。(For文をi=1から始めている)
こういったことをコメントに残しておくと、後で他の人が見て分かり易いですね。
配列cは要素番号1から15までに数字を代入しましたが、配列としては要素番号0も存在しているため、LBoundの戻り値は0になります。
配列cの中身を取得した結果はこちらです。
要素数を再定義する際の注意点
動的配列は、その要素数を途中で増やせるのが便利ですよね。
動的配列cにシートのA列の数字15個を格納した後、B列の数字7個を追加で格納するために動的配列cを再定義してみます。
str = str + vbCrLf
'要素を追加
Dim erow2 As Integer
erow2 = Cells(Rows.Count, 2).End(xlUp).Row 'B列の最終行
ReDim Preserve c(erow + erow2) As Integer '再定義
For i = 1 To erow2
c(erow + i) = Cells(i, 2).Value 'B列の値を配列に格納
str = str + CStr(c(erow + i)) + ","
Next i
MsgBox "配列c(redim後)の" + vbCrLf _
+ "始めの要素番号:" + CStr(LBound(c)) _
+ vbCrLf _
+ "終わりの要素番号:" + CStr(UBound(c))
MsgBox str
ここで大事なのは、動的配列の要素数を再定義する際に、Preserveを入れること。
ReDim Preserve c(新しい要素数) As Integer
Preserveを入れない場合、事前に動的配列に格納されていた値がクリアされてしまいます。
Preserveを入れて再定義したら、事前に格納された値は保持されたままになります。
再定義後の動的配列cの要素数はこちら。
再定義後の動的配列cの中身はこちら。
シートのA列とB列の数字が格納できていることが確認できました。
まとめ:VBAの配列は要素数に注意しよう
VBA歴が長い私ですが、配列の要素の始まりや宣言の仕方がよく分からなくなって、いつも調べていたので、自分へのメモとしてまとめました。
大事なのは、
「VBAの配列はa(3)と宣言したらa(0)~a(3)が使える」
これを覚えておけば大丈夫でしょう。
他の言語と違うので紛らわしいですね。
配列を0から使うのか、1から使うのか、最後の要素まで使うのかはコメントにメモを残しておくと良いでしょう。
そんなわけで、あなたも素敵なVBAの配列使いになりましょう♪
んじゃ、また~
プログラミングはどう勉強しますか?
おススメの方法をまとめました。
コメント