【Excel VBA】別のモジュール・プロシージャの変数を使う方法|Public変数と引数での受け渡し

受講料の最大70%の給付金あり
経済産業省リスキリングを通じたキャリアアップ支援事業対象
サムライエンジニア「生成AI」コース

Excel VBAで、あるマクロで作った変数の値を、別のマクロや別のモジュールで使いたいことがあります。

変数をどこから使えるかは、「どこに」「何と」宣言するかで決まります。

宣言する場所書き方使える範囲
プロシージャ(Sub〜End Sub)の中Dimそのプロシージャの中だけ
モジュールの一番上(宣言セクション)Dim または Private同じモジュールのすべてのプロシージャ
標準モジュールの一番上(宣言セクション)Publicすべてのモジュールのすべてのプロシージャ

変数を共有する代わりに、「引数」で値を渡す方法もあります。この記事では、それぞれの書き方と使い分けを、そのまま動くコードで紹介します。

初心者の頃は一つのモジュールやマクロに長々とコードを書きがちでしたが、マクロが大きくなってくると、これらを分けたくなります。

そんな時、モジュールやマクロ間で変数を共有するのに便利です。



※本ページはプロモーションが含まれています

スポンサーリンク
スポンサーリンク

同じモジュールの他のプロシージャで使う(モジュールレベル変数)

モジュールの一番上、最初のプロシージャより前(宣言セクション)で変数を宣言すると、そのモジュールの中のすべてのプロシージャで使えます。

Option Explicit
Dim msg As String

Sub モジュールレベル変数1()
    msg = "変数"
    MsgBox "モジュールレベル変数1:" & msg
    Call モジュールレベル変数2
End Sub

Sub モジュールレベル変数2()
    MsgBox "モジュールレベル変数2:" & msg
End Sub

「モジュールレベル変数1」で入れた値を、「モジュールレベル変数2」でも表示できます。

Excel VBA モジュールの宣言セクションでDimを使って変数を宣言したVBEの画面

Excel VBA モジュールの宣言セクションでDimを使って変数を宣言したVBEの画面

宣言セクションのDimは、Privateと書いても同じ意味です。「このモジュールの中だけで使う」ことをはっきりさせたいときは、Privateと書くと分かりやすくなります。

別のモジュールでも使う(Public変数=グローバル変数)

別のモジュールからも使いたいときは、標準モジュールの宣言セクションで「Public 変数名 As 型」と宣言します。

このような変数は「パブリック変数」や「グローバル変数」と呼ばれます。

Module1に次のコードを書きます。

Option Explicit
Public num As Long

Sub パブリック変数1()
    num = 777
    MsgBox "パブリック変数1:" & num
    Call パブリック変数2
End Sub

Module2に次のコードを書きます。

Option Explicit

Sub パブリック変数2()
    MsgBox "パブリック変数2:" & num
End Sub

Module1の「パブリック変数1」を実行すると、Module2の「パブリック変数2」でも「777」が表示されます。Module2ではnumを宣言していませんが、Module1のPublic宣言をそのまま使えています。

Excel VBA Module1の「パブリック変数1」を実行すると、Module2の「パブリック変数2」でも「777」が表示

Excel VBA Module1の「パブリック変数1」を実行すると、Module2の「パブリック変数2」でも「777」が表示

モジュールを役割ごとに分けている場合は、Public変数を「mod_Common」のような共通用のモジュールにまとめて書くと、どこで宣言したか迷いません。

モジュール名の変え方はこちらです。

【Excel VBA】モジュール名を変更する方法|変更できないときの対処と名前のルール
Excel VBAで標準モジュールを追加すると、名前は「Module1」「Module2」…と自動で付きます。数が増えると、どれに何のマクロを書いたのか分からなくなります。 モジュール名は、次の3ステップで変更できます。 ...

引数で値を渡す(プロシージャ間の受け渡し)

変数を共有しなくても、呼び出すときに「引数」として値を渡すことができます。別のモジュールのプロシージャにも渡せます。

Sub 引数で渡す()
    Dim userName As String
    userName = "山田"
    Call 挨拶を表示(userName)
End Sub

Sub 挨拶を表示(ByVal targetName As String)
    MsgBox targetName & "さん、こんにちは"
End Sub

「挨拶を表示」のカッコの中のtargetNameが引数です。呼び出し側で渡した userName の値が、targetName に入ります。

計算した結果を返してほしいときは、SubではなくFunctionを使います。

Sub 結果を受け取る()
    Dim total As Long
    total = 合計を計算(100, 250)
    MsgBox total
End Sub

Function 合計を計算(ByVal a As Long, ByVal b As Long) As Long
    合計を計算 = a + b
End Function

ByValは「値だけを渡す」という意味で、受け取った側で値を変えても呼び出し側の変数は変わりません。

何も書かないとByRef(変数そのものを渡す)になり、受け取った側で値を変えると呼び出し側の変数も変わります。

意図せず値が変わるのを防ぐため、迷ったらByValを付けておきましょう。

定数を共有する(Public Const)

シート名や税率のように、途中で変わらない値を複数のモジュールで使いたいときは、標準モジュールの宣言セクションで定数にします。

Option Explicit
Public Const DATA_SHEET As String = "データ"
Public Const TAX_RATE As Double = 0.1

別のモジュールから Worksheets(DATA_SHEET) のように使えます。

シート名が変わったときも、この1行を直すだけで済みます。

定数は値が消える心配もないので、変わらない値はPublic変数より定数にするのがおすすめです。

Public変数の値が消えるタイミング

モジュールレベル変数やPublic変数は、マクロが終わった後も値を覚えています。ただし、次のようなときには値がリセットされます。

  • エラーで止まり、「終了」を押したとき
  • VBEの「リセット」(■)ボタンを押したとき
  • コードの中でEndステートメントを実行したとき
  • ブックを閉じたとき

ブックを閉じた後も値を残したい場合は、変数ではなくシートのセルに書いておき、次に使うときに読み込みましょう。

設定用のシートを作って非表示にしておく方法もよく使われます。

プロシージャの中で値を覚えておく(Static)

プロシージャの中でDimの代わりにStaticと書くと、そのプロシージャが終わっても値を覚えていて、次に実行したときに続きから使えます。

Sub 実行回数を数える()
    Static count As Long
    count = count + 1
    MsgBox count & "回目の実行です"
End Sub

実行するたびに「1回目」「2回目」…と数が増えます。

他のプロシージャからは使えないので、「そのプロシージャの中だけで値を持ち越したい」ときに向いています。

どの方法を使えばいい?

やりたいことおすすめ
あるマクロから別のマクロへ値を渡したい引数(ByVal)
計算結果を返してほしいFunction
シート名や税率など変わらない値を共有したいPublic Const
同じモジュールの中で値を共有したいモジュールレベル変数(Private)
ブック全体で値を共有したいPublic変数
ブックを閉じても値を残したいセルに保存

Public変数は便利ですが、どこからでも値を変えられるので、数が増えると「どこで値が変わったのか」が分からなくなります。

まずは引数で渡せないかを考え、本当に必要なものだけPublicにするのがおすすめです。

生成AIにコードを頼むときも、「Public変数は使わず、引数で渡して」と一言添えると、後から直しやすいコードになりやすいです。

まとめ

  • 同じモジュールの中で共有:宣言セクションでDimまたはPrivate
  • 別のモジュールとも共有:標準モジュールの宣言セクションでPublic
  • 変わらない値はPublic Const、マクロ間の受け渡しは引数がおすすめ
  • Public変数はエラーでの終了やブックを閉じると値が消える。残したい値はセルに保存
タイトルとURLをコピーしました