マクロってどこに書けばいいの?


「○○をするには、どうしたらいいですか?Excel初心者です。よろしくお願いいたします。」
そうした掲示板での質問に対して
「これでできますよ」
と、マクロのコードが提示されることがあります。てゆーか、よくあります。むしろ、よくあります。逆に、よくあります。

質問者がマクロを使えて、提示されたコードをコピーして、それでやりたいことが実現できれば、それはそれで、ある意味ヨカッタかもしれません。ですが、マクロとは無縁な暮らしをしてきて、でも何となく「マクロってすごいかも」と淡い期待を持っていて、提示されたコードに触発されて「よし、マクロにチャレンジしてみようかな」と清水の舞台からバンジージャンプしたとしても、はて?このマクロとやら、いったいどこにコピーすればいいんだろう・・・と、超素朴な疑問がわいてきます。VBEを起動したことすらないのですから、当然ですね。

「すみません、せっかくマクロを教えてもらったんですが、これをどうしたらいいんでしょう・・・」

1.VBEを起動する

まず、大事なことを2つ覚えてください。

  • マクロのコードは、セルに入力した文字や数値と同じように、ブックごとに保存される
  • マクロのコードを記述・編集するときは、Excelとは別のVBEという画面を使う

ではさっそく、VBEを起動してみましょう。え?VBEは何の略かって?そんなの、後で考えればいいです。

VBEを起動するには、ワークシートが表示されている画面でAltキーを押しながら[F11]キーを押します。これも覚えてください。Alt+F11、Alt+F11、Alt+F11・・・覚えましたか?このキーを押すと、次のようなVBEが起動します。

2.標準モジュールを挿入する

VBEが起動したら、[挿入]メニューの[標準モジュール]をクリックします。

実行すると、下図のように標準モジュール[Module1]が挿入されます。

標準モジュール[Module1]をダブルクリックすると、右側に白いページみたいなウィンドウが開きます。上図のようにウィンドウ状態かもしれませんし、最大化されているかもしれません。とにかく、その白いエリアにマクロを書きます

Option Explicitとは何かは、下記のページをご覧ください。

Option Explicitって何?

標準モジュールの[Module1]ではなく、[Sheet1]とか[ThisWorkbook]などをダブルクリックしても、同じようにマクロを記述するウィンドウが開きます。これらの、マクロを記述するウィンドウをモジュールと呼びます。マクロは、標準モジュールだけでなく、[Sheet1]などのモジュールにも書けますが「マクロってどこに書けばいいの」というレベルのビギナーは、マクロは標準モジュールに書く。ほかのモジュールは使わないと考えればいいです。もっともっとマクロのことを学習して、たとえばイベントなんてのを使うときに、[Sheet1]とか[ThisWorkbook]のモジュールを使います。

それでも知りたい人のために

イベントを使わないのでしたら、とにかく「マクロは標準モジュールに書く」と覚えておけばいいです。ああ、もちろんUserFormは別の話ですけど。それでも「[Module1]と[Sheet1]にマクロを書くのは、何が違うんだろう」という疑問を払拭できない、好奇心旺盛な方には、両者の違いだけ解説します。なぜ、そうなるのか。そもそもモジュールとは何か、というテーマは奥が深いので、そのうち一杯やりながら語り明かしましょう。

標準モジュール(Module1)とシートモジュール(Sheet1)に記述したマクロの違いは

  • Module1に記述したマクロで、シートを指定しないセルはアクティブシートのセルとみなされる
  • Sheet1に記述したマクロで、シートを指定しないセルはSheet1のセルとみなされる

ということです。たとえば次のようなコードがあったとき

Sub Sample1()
    Range("A1") = "tanaka"
End Sub

このSample1が、標準モジュールに書かれていると、このマクロを実行したときのアクティブシートにあるRange("A1")に代入されます。一方、同じSample1をSheet1モジュールに記述した場合、アクティブシートがどこであれ、常にSheet1のRange("A1")が対象になります。

掲示板の解答や、Webで紹介されているコードなどは、特別なことわりがない限り「標準モジュールに記述する」という前提で書かれていることが多いです。そのコードを、誤ってSheet1モジュールにコピーしてしまうと、ただRange(~)と書かれていた場合、アクティブシートがどこであれ、常にSheet1が対象になるので、エラーになったり誤動作を起こすなどの原因になります。

もうひとつ、標準モジュール(Module1)とシートモジュール(Sheet1)に記述したマクロの違いがあります。たとえば、APIの宣言を含む次のようなコードがあったとします。

Declare Function GetTickCount Lib "Kernel32" () As Long

Sub Sample1()
    Dim n As Long
    n = GetTickCount
    MsgBox n
End Sub

APIの宣言まで含めたこのコード、標準モジュールにコピーしたときは正常に動作しますが、もしこのコードをSheet1モジュールに貼り付けるとエラーになります。

もちろんこれは、APIの宣言だけでなく、変数や定数やユーザー定義型の定義などでも同様です。このエラーメッセージを見て「ああ、そうか、そうだよね。間違えちゃった、テヘっ」みたいに、エラーの原因と、その対処法を即座に思いつく人は、そう多くありません。つまり、こういうことです。

  • Declareステートメントは、その有効範囲を示すPublicかPrivateを指定できる
  • PublicとPrivateのどちらも指定せずに実行したDeclareステートメントはPublicとみなされる
  • でも、SheetモジュールではPublicの宣言が許されていないのでエラー ← 今ココ

というわけです。意味分かりますか?

ピンとこないようなら「マクロは標準モジュールに書く。ほかのモジュールは使わない」と思ってください。あなたのためです。[Sheet1]や[ThisWorkbook]などのモジュールを使うのは、もっとVBAを学習した後でも遅くありません。