配列の次元数を取得するFunction
配列の次元数を取得する
何気なく配列をぐりぐりいじくっていたときに、ちょっとした間違いで
こんなエラーが出た。まあ、よくあるエラーなんだが、このときは要素数を超えたのではなくて、存在しない次元を指定していたのだった。
ということは、LBoundとかUBoundみたいな
配列の次元数(Dimension)を引数に持つ関数
に 1 づつインクリメントした数を渡していけば、配列次元数を超えたところでエラーが出るということだ。
というわけで、配列の次元数を取得するFunctionを作ってみた。
配列の次元数を返すFunction
リスト1 標準モジュール
Public Function getArrayDimension( _ ByRef targetArray As Variant) As Long '……(1)' If Not IsArray(targetArray) _ Then getArrayDimension = False: Exit Function '……(2)' Dim n As Long '……(3)' n = 0 Dim tmp As Long On Error Resume Next '……(4)' Do While Err.Number = 0 n = n + 1 tmp = UBound(targetArray, n) Loop Err.Clear getArrayDimension = n - 1 '……(5)' End Function
(1)の
Public Function getArrayDimension(ByRef targetArray As Variant) As Long
では、引数と返り値を設定。どんな配列が渡されるか分からないので、Variant型。返り値はInteger型でも良いと思うのだけれど、100万次元ぐらいの配列が渡されるかも知れないので(←ねえよw)Longにした。
追記
id:imihito さんによると、配列の次元数は60が最大、とのこと(コメント欄参照)。要するに、非常にマヌケなことを書いてしまっているということですね。まあ、大は小を兼ねるわけですから、このままLongっちゅうことにしときます。
(2)の
If Not IsArray(targetArray) Then getArrayDimension = False: Exit Function
はガード節。IsArray関数を使って配列かどうかを判定し、配列でなければ即Falseを返してFunctionを抜ける。
返り値は別に「0」で良いと思うが、Falseとした方が分かりやすいと思った。
(3)からの2行
Dim n As Long n = 0
では変数 n を用意して 0 で初期化。別にInteger型でも良いと思うのだけれど、100万(以下ry
この n は、後でインクリメントしてUBound関数に渡すために使う。
関係ないけれど、こういう野暮ったい書き方を見ると、
int n = 0;
みたいに書ける言語が羨ましくなる。
(4)からの6行
On Error Resume Next Do While Err.Number = 0 n = n + 1 tmp = UBound(targetArray, n) Loop Err.Clear
まず
On Error Resume Next
でエラーが出ても処理を続行するように指定しておく。
Do While Err.Number = 0
としているので、Doループのブロック突入時にErrオブジェクトのNumberプロパティを調べて、「0」すなわちエラーが出ていなければブロック内に突入することになる。
ブロック内に突入すると、まず
n = n + 1
で n をインクリメントし、
tmp = UBound(targetArray, n)
でUBound関数の引数Dimensionに渡す。
この段階で n が引数で渡された配列targetArrayの次元数を超えていたらエラーが発生して次へ進むことになる。
ちなみに、変数tmpはUBound関数を使うための単なるアテ馬w
Doループ内でエラーが発生したらループを抜けて、
Err.Clear
でErrオブジェクトをリセットしておく。
この段階で、変数 n には、引数で渡された配列targetArrayの要素数 + 1 が格納されているはずなので、(5)の
getArrayDimension = n - 1
をreturnしておしまい。
使ってみた
次のコードで実行。
リスト2 標準モジュール
Public Sub testGetArrayDimension() Dim ar1(1, 1, 1) As String Debug.Print getArrayDimension(ar1) Dim ar2(1, 1, 1, 1, 1, 1, 1) Debug.Print getArrayDimension(ar2) Debug.Print getArrayDimension("ち~んw") Debug.Print Not getArrayDimension("ち~んw") End Sub
リスト1のgetArrayDimensionを、それぞれ
- 3次元配列を渡す――(1)
- 7次元配列を渡す――(2)
- 配列でないただの文字列を渡す――(3)
- (3)の結果をNotする――(4)
形で実行している。
実行結果
意図したとおりの結果となった。
ちなみに、「0」はFalse、「ー1」はTrueなので、Not Falseの形でTrueも表現できる。
おわりに
相変わらず、何に使うのかは不明ですがw