メッセージの「ステートメント」とは、Dimステートメントとか、For Nextステートメントなどのステートメントではなく、「1行分の命令」という意味だと思います。VBAでは、1つの完結した命令を1行に書くのが原則です。この「ステートメントの最後」というエラーは、要するに「その行の命令は、何か変だよ」という程度の意味にお考えください。たとえば、下図のようなケースでも、このエラーが発生します。
おそらく「Range("A1") = 100」のつもりで「=」を入力し忘れたのでしょう。こんなとき「修正候補: 代入演算子がありません」みたいなエラーを表示してくれれば分かりやすいのですが、VBAは「Range("A1") までは理解できる。その後は普通ピリオドとか演算子とかがくるはずなのに・・・理解できた命令(ステートメント)Range("A1") の後ろは、意味がわりませ~ん」と判断したんでしょうね。たぶん(^^;
また、このエラーは、括弧を付けなければいけないところで、括弧が不足しているケースでも発生します。
上図は、Book1.xlsを開いて、そのブックをオブジェクト変数wbに格納しようとしています。このように、メソッドや関数の返り値を利用する場合は、引数を括弧で囲むのがVBAのルールです。VBAの括弧ルールに関しては、下記を参照してください。
メソッドの括弧だけでなく、プロシージャの括弧が足りない場合にも発生します。
別のプロシージャを呼び出すには、2通りの方法があります。1つは、ただプロシージャ名を書くだけです。
Sub Sample1() Sample2 "tanaka" ''正常に動作します End Sub Sub Sample2(msg As String) MsgBox msg End Sub
もうひとつは、Callステートメントを使う方法です。
Sub Sample1() Call Sample2("tanaka") ''正常に動作します End Sub Sub Sample2(msg As String) MsgBox msg End Sub
呼び出すプロシージャに引数を渡す場合、Callステートメントを使わないときは引数を括弧で囲みません。対して、Callステートメントを使うときは、引数を括弧で囲みます。
他のプロシージャを呼び出すときの、この括弧ルールは少々ややこしいです。Callステートメントを使うときは、必ず括弧が必要です。括弧がないとエラーになります。しかし、Callステートメントを使わないときは、括弧を付けてもエラーにはなりません。
Sub Sample1() Sample2 ("tanaka") ''正常に動作します End Sub Sub Sample2(msg As String) MsgBox msg End Sub
ややこしいですね。でも心配はいりません。他のプロシージャを呼び出すときは必ずCallステートメントを使うと決めておけばいいんです。Callステートメントは、他のプロシージャを呼び出すためのステートメントです。コード中に「Call ○○」と書かれていたら、それは「○○プロシージャを呼び出している」とコードを見ただけですぐ理解できます。Callステートメントを省略して、ただ「○○」と書いてあったら、それが何の意味なのかを考えなければなりません。どちらが可読性に優れいているかは言うまでもありませんね。他のプロシージャを呼び出すときは必ずCallステートメントを使う。引数を渡すときは括弧で囲む。この、とてもシンプルな2つのルールを守ればいいですね。
なお、Callステートメントを使わないで他プロシージャを呼び出すとき、引数を括弧で囲むのと囲まないのでは、実は微妙に動作が異なります。本コンテンツとは関係のない話なので詳しくは書きませんが、興味のある方は、次のコードを実行して違いを確認してください。
Sub Sample1() Dim buf As String buf = "tanaka" Sample2 buf MsgBox buf End Sub Sub Sample2(ByRef msg As String) msg = "suzuki" End Sub
Sub Sample1() Dim buf As String buf = "tanaka" Sample2 (buf) MsgBox buf End Sub Sub Sample2(ByRef msg As String) msg = "suzuki" End Sub
Callステートメントを使わないで他プロシージャを呼び出すとき、呼び出し先の引数定義がByRef(参照渡し)だったとしても、引数を括弧で囲むとByVal(値渡し)で渡されます。まぁ、こんな使い方は、ほとんどしませんけど。