エクセル2000を使い始めて10年ほどになるでしょうか、
ずっと勘違いしていたことをつい最近気付いたのでした。
一行で複数の変数を宣言することは一般的にもよくあることだと思うのですが
Dim i, j as Integer
のように宣言すると
i は Integer ではなく データ型を指定していない変数、
すなわち Variant として扱われてしまうのです。
基礎をしっかりと学んだ方はじゅうぶん承知されているのだろうけど、
独学自己流のワタクシ、複数のループ用変数を使うときなどしたり顔で
Dim i, j, k as Integer とかやってました。
もちろん k だけでなく、i も j も全部の変数を Integer として宣言したつもりでw
だってこの書き方そう思うよなぁw
ほとんどの場合、データ型がVariantであっても若干パフォーマンスが低下する
かもしれない、程度の影響しかなく、またエラーも発生しない場合が多い。
というか、あきらかに誤った書式であっても、アプリケーションが勝手にデータ型を
判断してなるべくエラーが起きないようになってしまっているんですね。
たとえば
Debug.Printで str を出力すると当然文字列として表示されますが
ByVal で他のプロシージャにこの変数を値渡しで渡すとき、受け側のデータ型指定が
異なっていても、そのまま通ってしまう場合が多々あります。
test02は受け取った変数をなぜだか数値の6として計算を行い、
その結果をちゃんとインデントを入れて数値として出力してしまいます。
test02が受ける変数 v を String にしてみました。
変数 v のTypeNameは String なのに、IsNumeric関数では True が返されます。
さらにユーザーから見て違和感を感じざるを得ない、v * 2 という文字列に対する
四則計算式ではエラーが起らず、 おそらく演算子である * が勝手に v を数値の
6 として型をキャストし、演算を行なってしまっているようです。
v にIsNumericでFalseが返されるような文字列を指定したときはさすがにエラーが起きます。
繰り返しますが以上は ByVal で変数を渡したときのみの話。
ByRef の場合は型が違うとエラーになります。
配列の場合は ByRef でないと他のプロシージャへ変数として渡すことができません。
一つのプロシージャにar01とar02という2つの配列を宣言し、
他のプロシージャにar01を渡してなんらかの処理をさせます。
'こう宣言すると配列ar01はVariant型の配列になりますが
'おれはString型として宣言できていると誤認しています。
'ついでにiもjもVariantだけどLongと思い込んでいますw
'-------------------------------------------------
Sub main()
Dim ar01(6), ar02(6) As String
Dim i, j, k As Long
Dim st As String
'配列になにかテキトーに要素を入れる
For i = LBound(ar01) To UBound(ar01)
ar01(i) = CStr((i + 1) * 2)
Next i
'使わない2個目の配列
For j = LBound(ar02) To UBound(ar02)
ar01(j) = CStr((j + 1) * 3)
Next j
'ar01の要素をテキスト化
For k = 0 To 6
st = st & ar01(k) & "/"
Next k
Debug.Print st
Call test00(ar01)
End Sub
'-------------------------------------------------
'なんでもいいから配列を受ける 配列はByRefでしか渡せません
Sub test00(ByRef ary() As String)
Debug.Print UBound(ary)
End Sub
'-------------------------------------------------
実行時エラーでなく、コンパイルエラーが起こります
これねー、ホントわかんなかったなんで動かないのかなーって
気付くのに丸一日以上かかった
誤 Dim ar01(6), ar02(6) As String
正 Dim ar01(6) as String , ar02(6) As String
10年使ってるけどいまだに慣れませんわw
ずっと勘違いしていたことをつい最近気付いたのでした。
一行で複数の変数を宣言することは一般的にもよくあることだと思うのですが
Dim i, j as Integer
のように宣言すると
i は Integer ではなく データ型を指定していない変数、
すなわち Variant として扱われてしまうのです。
基礎をしっかりと学んだ方はじゅうぶん承知されているのだろうけど、
独学自己流のワタクシ、複数のループ用変数を使うときなどしたり顔で
Dim i, j, k as Integer とかやってました。
もちろん k だけでなく、i も j も全部の変数を Integer として宣言したつもりでw
だってこの書き方そう思うよなぁw
ほとんどの場合、データ型がVariantであっても若干パフォーマンスが低下する
かもしれない、程度の影響しかなく、またエラーも発生しない場合が多い。
というか、あきらかに誤った書式であっても、アプリケーションが勝手にデータ型を
判断してなるべくエラーが起きないようになってしまっているんですね。
たとえば
![酢吉のブログ](https://stat.ameba.jp/user_images/20120417/22/sukiti/90/7b/j/t02200257_0319037211921962352.jpg?caw=800)
Debug.Printで str を出力すると当然文字列として表示されますが
ByVal で他のプロシージャにこの変数を値渡しで渡すとき、受け側のデータ型指定が
異なっていても、そのまま通ってしまう場合が多々あります。
test02は受け取った変数をなぜだか数値の6として計算を行い、
その結果をちゃんとインデントを入れて数値として出力してしまいます。
test02が受ける変数 v を String にしてみました。
![酢吉のブログ](https://stat.ameba.jp/user_images/20120418/20/sukiti/8d/08/j/t02200352_0284045411923389109.jpg?caw=800)
変数 v のTypeNameは String なのに、IsNumeric関数では True が返されます。
さらにユーザーから見て違和感を感じざるを得ない、v * 2 という文字列に対する
四則計算式ではエラーが起らず、 おそらく演算子である * が勝手に v を数値の
6 として型をキャストし、演算を行なってしまっているようです。
v にIsNumericでFalseが返されるような文字列を指定したときはさすがにエラーが起きます。
繰り返しますが以上は ByVal で変数を渡したときのみの話。
ByRef の場合は型が違うとエラーになります。
配列の場合は ByRef でないと他のプロシージャへ変数として渡すことができません。
一つのプロシージャにar01とar02という2つの配列を宣言し、
他のプロシージャにar01を渡してなんらかの処理をさせます。
'こう宣言すると配列ar01はVariant型の配列になりますが
'おれはString型として宣言できていると誤認しています。
'ついでにiもjもVariantだけどLongと思い込んでいますw
'-------------------------------------------------
Sub main()
Dim ar01(6), ar02(6) As String
Dim i, j, k As Long
Dim st As String
'配列になにかテキトーに要素を入れる
For i = LBound(ar01) To UBound(ar01)
ar01(i) = CStr((i + 1) * 2)
Next i
'使わない2個目の配列
For j = LBound(ar02) To UBound(ar02)
ar01(j) = CStr((j + 1) * 3)
Next j
'ar01の要素をテキスト化
For k = 0 To 6
st = st & ar01(k) & "/"
Next k
Debug.Print st
Call test00(ar01)
End Sub
'-------------------------------------------------
'なんでもいいから配列を受ける 配列はByRefでしか渡せません
Sub test00(ByRef ary() As String)
Debug.Print UBound(ary)
End Sub
'-------------------------------------------------
![酢吉のブログ](https://stat.ameba.jp/user_images/20120418/20/sukiti/a7/5b/j/o0419014211923444320.jpg?caw=800)
実行時エラーでなく、コンパイルエラーが起こります
これねー、ホントわかんなかったなんで動かないのかなーって
気付くのに丸一日以上かかった
誤 Dim ar01(6), ar02(6) As String
正 Dim ar01(6) as String , ar02(6) As String
10年使ってるけどいまだに慣れませんわw