Valueプロパティの省略
セルの値を参照する際に「Range(“A1”).Value」のようにValueプロパティを使って書きますが、.Valueを省略して「Range(“A1”)」と書いてもセルの値を参照することが出来ます。
ありがちなのが「付け忘れてたけど、たまたま動いてた」って奴です。
ただ、先に結論から書くと、.Valueの省略はお勧めしません。むしろ、ちゃんと「.Value」と書きましょう。もっと言うと、「こんな余計な機能を入れるから初学者が混乱すんだよ」というのが本音です。Valueの省略禁止の理由については後述します。
以下のコードは.Valueを付けた場合と付けない場合の書き方で、どちらもA1セルの値をイミディエイトウィンドウに出力します。
1 2 3 4 |
Sub RangeValueTest1() Debug.Print Range("A1").Value Debug.Print Range("A1") End Sub |
同じことをやってるのに書き方が違う、というのは特に初学者には大変苦痛です。なんでもいいから正解を1つ教えてくれ、というのが心情でしょう。
Valueを省略してもセルの値が参照できる理由
言語仕様の話になりますが、Valueプロパティを書かなくてもセルの値が参照されるのには理由があります。
それは、Rangeクラスに対して引数無しで渡された場合、Valueプロパティの呼び出しを行うようにRangeクラスの内部処理で実装されているためです。ちなみに、省略した場合と省略しなかった場合での処理速度の差はありません。省略したからと言って遅くなるようなことは無いです。
VBAのクラスモジュールでは引数なしのコンストラクタは実装できないため、VBAではRangeクラスの内容を表現できないのですが、他プログラミング言語が分かる方に向けて言えば、C++で言えば以下のような感じです。Rangeクラスのコンストラクタに引数で座標アドレスの文字列を渡されたら、Valueメソッドを呼び出すような考え方です。
一応ですが、考え方が分かればOKな例として書いてるだけでC++のコンパイルは通してないです。通す気もないのでご了承を。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
class Range { private: char sCellAddress[10]; public: // Rangeクラスのコンストラクタ:引数はセル座標文字列 Range(char *psCellAddress) { // Valueメソッドを呼び出し Value(psCellAddress); memset(sCellAddress, 0x00, sizeof(sCellAddress)); strcpy(sCellAddress, psCellAddress); } // Valueメソッド:引数はセル座標文字列 char* Value(char *psCellAddress) { return GetCellValue(psCellAddress); } // Valueメソッド:引数なし char* Value() { return GetCellValue(sCellAddress); } } |
Valueを省略しない方がいい理由
上記の通り、.Valueを書かなくてもセルの値を参照することは出来るのですが、.Valueを省略した場合にはRangeオブジェクトを返すという役割も持っています。
書き方が同じなのに、.Valueを省略した場合には2つの用途があります。
以下のコードは「Range(“A1”)」を2か所で使っていますが、1つはセル自体を表すRangeオブジェクトとして使っており、もう1つはValueプロパティを省略した場合のセルの値の取得に使っています。言い方を変えると「Range(“A1”)」という書き方は同じでも違う用途で使っているということです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Sub RangeTest2() Dim r As Range '// セル自体 Dim s As String '// セル値 '// A1セルのRangeオブジェクトを取得 Set r = Range("A1") '// 取得したRangeオブジェクトの座標を出力 Debug.Print r.Address '// A1セルの値を取得 s = Range("A1") '// セルの値を出力 Debug.Print s End Sub |
このように、「Range(“A1”)」という書き方だけでセルの値を取得しているのか、それともRangeオブジェクトを取得しているのかがすぐに分かる方は相当VBAのコードに慣れている方です。
これが.Valueを省略しない方がいい一番の理由です。オブジェクトとセル値のどちらの代入をやっているのかわかりにくいのです。
おそらく言語仕様を決める当初は「省略して書けるように言語設計しておけばプログラミングをしたことがない人でも動くプログラムになるからお助け機能としてValueを省略してもOKにしよう」とか考えたのだと思いますが、結果としてそれが余計な混乱を生むだけになっています。
Valueを省略する場合としない場合の書き分け
プログラミングに慣れている方であればあるほど、.Valueプロパティの省略はしない傾向が強くなると思われます。その理由は、プログラミング上級者であればあるほど不確定要素を排除し、より安全なコードを書こうとする意識が働くからです。上級者は「Valueを省略するとあまり詳しくない人が見たときや自分が将来忘れたときに勘違いするかもしれんから避けておこう」と考えます。そのため、Valueを省略して書くのは初学者の方が多いはずです。
以降は初学者向けの説明です。
セルの値を参照したい場合は.Valueを付けるようにした方がいいです。
.Valueを付けない場合はRangeオブジェクトとして扱う場合のみです。具体的には以下のようにRangeクラス型の変数に代入するときだけです。
1 2 |
Dim r As Range Set r = Range("A1") |
もしあなたがVBAに慣れていなかったり、「Rangeオブジェクト」と言われてもよく分からない、というのであれば、そもそもこのコードのようなSetでのRangeオブジェクトの代入をするようなコードを自分で書く機会はまずありません。
基本的にはValueを付けておいて、なんかエラーが出たら外してみる、ぐらいで構いません。
段階ごとに単純に書くと以下のようになります。
- よくわからんのならとりあえず.Valueを付ける。
- セルの値を使うときは.Valueを付ける。
- =での代入の場合は.Valueを付ける。
- Setでの代入の場合は.Valueは付けない。
- 関数の引数の場合は.Valueを付けて、エラーが出たら外してみる。(引数の説明で「Rangeオブジェクト」と書いてあったら外すのが正解です)
繰り返しになりますが、Valueはきちんと書きましょう。省略禁止です。