【Excel】VBAのPublicとPrivateの使い分け!Excelマクロの適用範囲を制御する方法

【Excel】VBAのPublicとPrivateの使い分け!Excelマクロの適用範囲を制御する方法
🛡️ 超解決

Excel VBAでマクロを作成する際、PublicとPrivateというキーワードを目にする機会があるでしょう。これらは、変数の適用範囲やプロシージャ(SubやFunction)の呼び出し元を制御するために使用されます。これらの使い分けを理解しないと、意図しない動作を引き起こしたり、コードの保守性が低下したりする可能性があります。本記事では、VBAにおけるPublicとPrivateの役割と、それぞれの適切な使い分けについて解説します。

PublicとPrivateを理解することで、より安全で効率的なExcelマクロ開発が可能になります。コードの可読性を高め、意図しないエラーを防ぐための重要な知識です。

【要点】VBAのPublicとPrivateによる適用範囲の制御

  • Publicキーワード: モジュール、クラス、プロシージャの適用範囲をグローバルに設定し、どこからでもアクセス可能にします。
  • Privateキーワード: モジュール、クラス、プロシージャの適用範囲を限定し、同じモジュール内からのみアクセス可能にします。
  • 使い分けの原則: 基本的にPrivateを使用し、外部からのアクセスが必要な場合のみPublicを使用することで、コードの安全性を高めます。

ADVERTISEMENT

PublicとPrivateの基本的な役割

Excel VBAにおいて、PublicとPrivateは主に以下の要素の適用範囲(スコープ)を定義するために使用されます。

適用範囲とは、その変数やプロシージャがコードのどこから参照・呼び出し可能であるかを示すものです。適切に適用範囲を定義することで、意図しない変数の変更や、不正なプロシージャの呼び出しを防ぐことができます。

Publicの役割

Publicキーワードを付けると、その宣言された要素は「グローバルスコープ」となり、同じVBAプロジェクト内のどのモジュール、クラスモジュール、標準モジュール、フォームモジュール、あるいは標準モジュール内のどのプロシージャからでもアクセス可能になります。

例えば、Public変数として宣言された変数は、プロジェクト内のどのSubプロシージャやFunctionプロシージャからでも参照・変更できます。同様に、Publicで宣言されたSubプロシージャやFunctionプロシージャは、他のモジュールから直接呼び出すことができます。

Privateの役割

Privateキーワードを付けると、その宣言された要素は「プライベートスコープ」となり、基本的にはその要素が宣言されているモジュール内からのみアクセス可能になります。他のモジュールからは直接参照・呼び出しができません。

Private変数として宣言された変数は、その変数が宣言されたモジュール内のプロシージャからのみ参照・変更できます。Privateで宣言されたSubプロシージャやFunctionプロシージャも、同じモジュール内の他のプロシージャからのみ呼び出し可能です。

お探しの解決策が見つからない場合は、こちらの「Excelトラブル完全解決データベース」で他のエラー原因や解決策をチェックしてみてください。

変数の適用範囲(スコープ)におけるPublicとPrivate

変数の適用範囲は、どこで宣言されたかによっても決まりますが、PublicとPrivateキーワードを使用することで、その適用範囲を明示的に制御できます。

変数が宣言される場所は、プロシージャ内(ローカルスコープ)、モジュールの先頭付近(モジュールスコープ)、または標準モジュール全体(グローバルスコープ)のいずれかです。

モジュールレベルの変数

モジュールの先頭付近(SubやFunctionプロシージャの外)でDimステートメントを使用して変数を宣言した場合、その変数は「モジュールレベル変数」となります。

このモジュールレベル変数の適用範囲を制御するために、PublicまたはPrivateを使用します。

Public変数の例:

標準モジュール1(Module1)に以下のように記述します。

Public g_strUserName As String

この `g_strUserName` という変数は、同じVBAプロジェクト内のどのモジュールからでもアクセスできます。他のモジュールからこの変数に値を代入したり、参照したりすることが可能です。

Private変数の例:

標準モジュール1(Module1)に以下のように記述します。

Private g_lngCounter As Long

この `g_lngCounter` という変数は、`Module1` 内のプロシージャからのみアクセスできます。他のモジュールから `g_lngCounter` を直接参照・変更しようとすると、エラーが発生します。

宣言がない場合:

モジュールレベルで `Dim` ステートメントのみを使用して変数を宣言した場合、その変数はデフォルトで `Private` と同じ扱いになります。つまり、同じモジュール内からしかアクセスできません。

Dim lngLocalCounter As Long ' これは Private lngLocalCounter As Long と同じ

プロシージャレベルの変数

SubプロシージャやFunctionプロシージャの内部で `Dim` ステートメントを使用して宣言された変数は、「プロシージャレベル変数」または「ローカル変数」と呼ばれます。

これらの変数は、そのプロシージャが実行されている間だけ存在し、プロシージャの実行が終了すると破棄されます。プロシージャレベル変数は、そのプロシージャ内からしかアクセスできません。

プロシージャレベル変数には、PublicやPrivateキーワードを使用しても、その適用範囲はプロシージャ内に限定されるため、意味がありません。これらのキーワードは、モジュールレベル変数やクラスモジュール、プロシージャの適用範囲を制御するために使用されます。

プロシージャの適用範囲(スコープ)におけるPublicとPrivate

SubプロシージャやFunctionプロシージャにも、PublicとPrivateキーワードを使用して適用範囲を定義できます。これにより、他のモジュールからそのプロシージャを呼び出せるかどうかが決まります。

Publicプロシージャ

SubプロシージャやFunctionプロシージャの宣言時に `Public` キーワードを付けると、そのプロシージャは「パブリックプロシージャ」となり、同じVBAプロジェクト内のどのモジュールからでも呼び出し可能になります。

例:

' Module1.bas
Public Sub PublicMacroExample()
    MsgBox "これはPublicマクロです。"
End Sub

別のモジュール(例えばModule2)から、この `PublicMacroExample` を直接呼び出すことができます。

' Module2.bas
Sub CallPublicMacro()
    Call PublicMacroExample ' Module1 の PublicMacroExample を呼び出す
End Sub

Privateプロシージャ

SubプロシージャやFunctionプロシージャの宣言時に `Private` キーワードを付けると、そのプロシージャは「プライベートプロシージャ」となり、基本的にはそのプロシージャが定義されているモジュール内からのみ呼び出し可能になります。

例:

' Module1.bas
Private Sub PrivateMacroExample()
    MsgBox "これはPrivateマクロです。"
End Sub

Public Sub CallPrivateMacro()
    Call PrivateMacroExample ' Module1 内から PrivateMacroExample を呼び出す
End Sub

この場合、`Module2` から `PrivateMacroExample` を直接呼び出そうとすると、エラーが発生します。`CallPrivateMacro` のように、同じモジュール内のPublicプロシージャからのみ呼び出すことができます。

宣言がない場合:

プロシージャレベルで `Public` や `Private` キーワードを付けずに `Sub` や `Function` を宣言した場合、そのプロシージャはデフォルトで `Public` となります。つまり、他のモジュールから呼び出し可能になります。

' Module1.bas
Sub DefaultPublicMacro() ' これは Public DefaultPublicMacro と同じ
    MsgBox "これはデフォルトでPublicなマクロです。"
End Sub

ADVERTISEMENT

PublicとPrivateの使い分け原則

PublicとPrivateの適用範囲を理解した上で、どのような場合にどちらを使用すべきかの原則があります。これは、コードの保守性、安全性、再利用性を高めるために重要です。

原則1:必要最小限の公開(Least Privilege)

可能な限り `Private` を使用することが推奨されます。これは、「必要最小限の公開」の原則に基づいています。

ある変数やプロシージャが、そのモジュール内だけで完結する処理や、そのモジュール内の他のプロシージャを補助する役割しか持たない場合、それを `Private` に設定します。これにより、外部から意図せずアクセスされたり、変更されたりすることを防ぐことができます。

外部からアクセスする必要がない要素を `Public` にしてしまうと、コードの依存関係が複雑になり、後で修正する際に影響範囲の特定が困難になる可能性があります。

原則2:外部インターフェースとしてのPublic

逆に、他のモジュールや、Excelのボタン、フォームコントロールなどから直接呼び出される必要があるプロシージャや、他のモジュールで参照される必要がある変数は `Public` に設定します。

例えば、ユーザーがボタンをクリックしたときに実行されるマクロは、そのマクロがどのモジュールにあっても呼び出せるように `Public` である必要があります。また、複数のマクロ間で共通して使用する設定値などは、`Public` 変数として定義することがあります。

原則3:ヘルパープロシージャはPrivateに

メインとなる処理を行うPublicプロシージャの中で、さらに細分化された処理を行うための補助的なプロシージャ(ヘルパープロシージャ)は、原則として `Private` に設定します。

これにより、メインのPublicプロシージャがコードの全体像を把握しやすく、ヘルパープロシージャは内部的な実装の詳細として扱われます。外部からはメインの処理のみが見えれば十分な場合が多いです。

クラスモジュールにおけるPublicとPrivate

クラスモジュールでは、PublicとPrivateの概念はさらに重要になります。クラスモジュールは、オブジェクト指向プログラミングにおける「クラス」を定義するために使用されます。

クラスモジュール内で宣言された変数(プロパティ)やメソッド(プロシージャ)の適用範囲をPublicとPrivateで制御することで、クラスの外部からアクセスできるメンバーと、クラス内部でのみ使用するメンバーを明確に分けます。

クラスプロパティのスコープ

クラスモジュール内で `Public` で宣言された変数は、そのクラスのインスタンス(オブジェクト)の「パブリックプロパティ」となり、クラスの外部からアクセス・変更が可能です。

`Private` で宣言された変数は、クラス内部でのみ使用される「プライベートメンバー」となり、外部からは直接アクセスできません。これらのプライベートメンバーにアクセスするには、通常、PublicプロパティやPublicメソッドを介して行います。

クラスメソッドのスコープ

クラスモジュール内で `Public` で宣言されたSubやFunctionは、そのクラスの「パブリックメソッド」となり、クラスのインスタンスから呼び出すことができます。

`Private` で宣言されたメソッドは、クラス内部でのみ呼び出し可能な「プライベートメソッド」となります。これは、ヘルパーメソッドとして利用されることが多いです。

例:クラスモジュールでの使い分け

例えば、従業員を表すクラス `CEmployee` を作成する場合を考えます。

' クラスモジュール: CEmployee
' Public変数 (パブリックプロパティ)
Public EmployeeID As String
Public EmployeeName As String

' Private変数 (プライベートメンバー)
Private lngSalary As Long

' Publicメソッド (パブリックメソッド)
Public Sub SetSalary(ByVal SalaryAmount As Long)
    If SalaryAmount >= 0 Then
        lngSalary = SalaryAmount
    Else
        MsgBox "給与は0以上である必要があります。"
    End If
End Sub

Public Function GetSalary() As Long
    GetSalary = lngSalary
End Function

' Privateメソッド (プライベートメソッド)
Private Sub InternalLog(Message As String)
    ' 内部的なログ記録処理など
    Debug.Print Message
End Sub

Public Sub DisplayInfo()
    Call InternalLog("従業員情報表示開始")
    MsgBox "ID: " & EmployeeID & ", 名前: " & EmployeeName & ", 給与: " & lngSalary
End Sub

この例では、`EmployeeID` と `EmployeeName` は直接設定・参照できます。給与 (`lngSalary`) は `Private` になっており、直接アクセスできません。給与の設定と取得は、`SetSalary` メソッドと `GetSalary` 関数というPublicメソッドを介して行います。これにより、不正な値が設定されるのを防ぐことができます。`InternalLog` は、クラス内部でのみ使用されるプライベートメソッドです。

VBAマクロの適用範囲を制御するメリット

PublicとPrivateを適切に使い分けることは、VBAマクロ開発において多くのメリットをもたらします。

コードの安全性向上

Privateを使用することで、意図しない箇所からの変数やプロシージャへのアクセスを防ぐことができます。これにより、予期せぬバグの発生を抑制し、コードの安定性を高めることができます。

特に、複数の開発者が関わるプロジェクトや、長期間にわたってメンテナンスを行う必要があるコードでは、この安全性の確保が重要になります。

保守性の向上

コードの適用範囲が明確になることで、コードの理解が容易になります。あるモジュールやクラスの内部実装を知らなくても、Publicインターフェースを通じて正しく利用できるようになります。

また、ある要素を修正する際に、それがどこに影響を与えるかを把握しやすくなり、修正作業の効率が向上します。Privateに設定された要素は、そのモジュール内でのみ影響があるため、修正による影響範囲が限定されます。

再利用性の向上

クラスモジュールなどでPrivateメンバーを適切に定義し、Publicインターフェースを明確にすることで、そのクラスを他のプロジェクトや別の場所で再利用しやすくなります。利用者は、公開されているメソッドやプロパティのみを意識すればよいため、クラスの内部構造に依存せずに利用できます。

コードの可読性向上

PublicとPrivateの使い分けは、コードの意図を明確に示します。「この要素は外部から利用されるもの」「この要素は内部的な処理にのみ使われるもの」といった情報がコード自体に埋め込まれるため、他の人がコードを読んだときに、その役割を理解しやすくなります。

よくある誤解と注意点

PublicとPrivateの適用範囲に関して、いくつかの誤解や注意点があります。

標準モジュールのデフォルトはPublic

前述の通り、標準モジュール(Module)で `Sub` や `Function` を `Public` や `Private` を付けずに宣言した場合、デフォルトで `Public` となります。これは、他のモジュールから呼び出せることを意味します。意図せず他のモジュールから呼び出されたくないプロシージャは、明示的に `Private` と宣言する必要があります。

モジュールレベル変数のデフォルトはPrivate

標準モジュールで `Dim` を使ってモジュールレベル変数(プロシージャの外で宣言された変数)を宣言した場合、デフォルトで `Private` となります。これは、そのモジュール内からしかアクセスできないことを意味します。グローバル変数としてプロジェクト全体からアクセスできるようにしたい場合は、明示的に `Public` と宣言する必要があります。

ThisWorkbookモジュールと標準モジュールの違い

`ThisWorkbook` モジュールやシートモジュール(Sheet1など)に記述されたプロシージャも、デフォルトでは `Public` となります。しかし、これらのモジュールは特定のブックやシートに紐づいているため、標準モジュールとは少し異なる文脈で扱われます。

これらのモジュールで `Private` を使用した場合、そのモジュール自体からしか呼び出せなくなります。

セキュリティ警告への対応

マクロを含むExcelファイルを開いた際に、セキュリティ警告が表示されることがあります。これは、マクロが実行されることによる潜在的なリスクを防ぐための機能です。

信頼できるソースからのファイルであれば、セキュリティ警告が表示された際に「コンテンツの有効化」をクリックすることでマクロを実行できます。しかし、外部から受け取ったファイルのマクロは、安易に実行しないように注意が必要です。

Public/Privateの使い分け自体が直接セキュリティ警告の原因になるわけではありませんが、悪意のあるマクロが `Public` プロシージャを介して不正な処理を実行する可能性はあります。そのため、マクロの実行権限管理や、信頼できるソースからのファイルのみを扱うことが重要です。

まとめ

Excel VBAにおけるPublicとPrivateキーワードは、変数やプロシージャの適用範囲を制御するための基本的ながら非常に重要な要素です。Publicはどこからでもアクセス可能にし、Privateは宣言されたモジュール内に制限します。

「必要最小限の公開」の原則に従い、原則としてPrivateを使用し、外部からのアクセスが必要な場合にのみPublicを使用することで、コードの安全性、保守性、可読性を大幅に向上させることができます。

今回解説したPublicとPrivateの使い分けを意識することで、より堅牢で管理しやすいVBAマクロを作成できるようになります。ぜひ、今後のマクロ開発でこれらの知識を実践してみてください。

📊
Excelトラブル完全解決データベースこの記事以外にも、様々なエラー解決策をまとめています。困った時の逆引きに活用してください。

ADVERTISEMENT

この記事の監修者
📈

超解決 Excel・Word研究班

企業のDX支援や業務効率化を専門とする技術者チーム。20年以上のExcel・Word運用改善実績に基づき、不具合の根本原因と最短の解決策を監修しています。ExcelとWordを使った「やりたいこと」「困っていること」「より便利な使い方」をクライアントの視点で丁寧に提供します。

🏆
超解決 Excel検定 あなたのExcel実務能力を3分で測定!【1級・2級・3級】