VBEオブジェクトの使用準備
VBAプログラムによってワークブックのVBAコードを変更するためには,Application.VBEオブジェクトを使用します。VBEオブジェクトを使用するには,次の2つの準備が必要です。- VBEにおいてMicrosoft Visual Basic for Applications Extensibilityへの参照を追加する。
- 「VBAプロジェクト オブジェクトモデルへのアクセスを信頼する」オプションを指定する。
次に,「VBAプロジェクト オブジェクトモデルへのアクセスを信頼する」オプションの設定をExcelから行います。この設定が必要な理由は,標準ではセキュリティ上の理由によりVBAプログラムからVBAコードを操作することが許されていないためです。実際の運用においても,このオプションを有効にするのはVBAコード付きのExcelワークブックを生成するプログラムを実行するPCに限定すべきでしょう。 (このオプションをVBAコードから設定することはできません。悪用される危険のある機能を有効にするかどうかユーザーの明示的な判断を仰いでいるのですから当たり前ですね。)
Excel 2007以降では,開発タブのマクロのセキュリティメニューを選択するとセキュリティ センターウィンドウの当該ページが開くので,チェックボックスをチェックします。
Excel 2003では,ツール(T)→マクロ(M)→セキュリティ(S)でセキュリティダイアログボックスを開き,「信頼できる発行元」タブを選択します。そして,「Visual Basicプロジェクトへのアクセスを信頼する」をチェックします。
VBEオブジェクトの構造
VBEオブジェクトは,VBAの開発環境に対応するオブジェクトです。VBEオブジェクトはVBProjectsコレクションプロパティを持ち,その各VBProjectオブジェクトがオープン中の各VBAプロジェクトに対応するVBProjectオブジェクトを管理します。そして,VBProjectオブジェクトのVBComponentsコレクションが各種モジュールに対応するVBComponentオブジェクトを管理します。VBComponentオブジェクトは1つのCodeModuleオブジェクトを持ち,これがモジュールのVBコードに対応します。したがって,個々のVBProjectオブジェクトにアクセスするにはApplication.VBE.VBProjects(1)などと記述することになります。しかし,VBAプロジェクトはワークブックと1対1対応するため,WorkbookオブジェクトのVBProjectプロパティを使用して,Workbooks("Book1.xls").VBProjectのようにする場合がほとんどです。
モジュールの追加
VBComponentオブジェクトは,プロジェクト(=ワークブック)に含まれる個別オブジェクトモジュールに対応します。Typeプロパティはvbext_ComponentType列挙型の値を取り,モジュールの種別を表します。vbext_ComponentType | 値 | モジュール種別 |
vbext_ct_StdModule | 1 | 標準モジュール |
vbext_ct_ClassModule | 2 | クラスモジュール |
vbext_ct_MSForm | 3 | ユーザーフォーム |
vbext_ct_ActiveXDesigner | 11 | ActiveXデザイナ |
vbext_ct_Document | 100 | Excelオブジェクト |
新規モジュールを追加するには,VBComponentsコレクションのAddメソッドを使います。引数として上記vbext_ComponentType型の値を渡すことで,追加するモジュールの種別を指定します。あるいは,事前にエクスポートしておいたテキストファイルをImportメソッドで読み込むことで完成されたモジュールを追加することもできます。ただし,追加できるのは標準モジュール,クラスモジュールとユーザーフォームのみです。
Addメソッド
VBComponentsコレクションに新たなVBComponentオブジェクトを追加します。
構文
VBComponentObject = object.Add(type)
指定項目 | 内容 |
object | VBComponentsコレクションオブジェクトを指定します。 |
type | 追加するVBComponentオブジェクトの種別をvbext_ComponentType型で指定します。vbext_ct_StdModule,vbext_ct_ClassModule,vbext_ct_MSFormが指定可能です。 |
Importメソッド
ファイルから読み込んだ新たなVBComponentオブジェクトをVBComponentsコレクションに追加します。
構文
VBComponentObject = object.Import(filename)
指定項目 | 内容 |
object | VBComponentsコレクションオブジェクトを指定します。 |
filename | VBComponentsコレクションに追加するオブジェクトモジュールを定義するテキストファイルのパスを指定します。 |
追加したモジュールの名前を設定するにはVBComponentオブジェクトのNameプロパティを使用します。
Nameプロパティ
VBComponentオブジェクトの名前を取得または設定します。
構文
object.Name = NewName
指定項目 | 内容 |
object | VBComponentsコレクションオブジェクトを指定します。 |
NewName | VBComponentオブジェクトの新しい名前を指定します。 |
コードの付加
追加したモジュールにコードを追加するには,VBComponentオブジェクトが持つCodeModuleオブジェクトを使用します。CodeModuleオブジェクトには様々なプロパティやメソッドが用意されており,たとえばProcBodyLineプロパティは指定したプロシージャやプロパティの先頭行を取得することができます。既存のコードを細かく修正する場合にはこれらの機能が役に立ちますが,新規モジュールにコードを追加するのであれば,基本的にはInsertLinesメソッドさえあれば十分です。InsertLinesメソッド
モジュールの指定した行にコードを追加します。
構文
object.CodeModule.InsertLines(LineNo, CodeText)
指定項目 | 内容 |
object | VBComponentオブジェクトを指定します。 |
LineNo | コードを挿入する行番号を指定します。最初の行が1行目となります。 |
CodeText | 追加するコードを文字列で指定します。 |
新規モジュールにInsertLinesメソッドによりコードを追加する場合,必ずしもLineNoに1を指定すればよいとは限らないことに注意が必要です。なぜなら,オプションダイアログボックスにおいて「変数の宣言を強制する」オプションが指定されていると,コードの1行目には常にOption Explicitというステートメントが自動的に挿入されるからです。そして,Option Explicitはどのプロシージャよりも前に記述されないとエラーとなってしまいます。そこで,InsertLinesメソッドの実行前にCountOfLinesプロパティでモジュールに含まれる行数を取得し,既存コードの次にコードを挿入するようにします。
以下のプロシージャは,新規ワークブックを作成して,そこにVBAコードを付加し,直後にそのコードを実行します。
|
Public Sub TestAddCode() Dim bk As Workbook Set bk = Workbooks.Add ' Adding code to a new Standard module. With bk.VBProject.VBComponents.Add(vbext_ComponentType.vbext_ct_StdModule) .CodeModule.InsertLines _ (.CodeModule.CountOfLines + 1) _ , "Public Sub ProcInStdModule()" & vbCrLf & _ " Msgbox ""Executing ProcInStdModule()""" & vbCrLf & _ "End Sub" End With ' Adding code to ThisWorkbook object module. With bk.VBProject.VBComponents("ThisWorkbook") .CodeModule.InsertLines _ (.CodeModule.CountOfLines + 1) _ , "Public Sub ProcInThisWorkbook()" & vbCrLf & _ " Msgbox ""Executing ProcInThisWorkbook()""" & vbCrLf & _ "End Sub" End With ' Calling procedure in Standard module Application.Run bk.Name & "!ProcInStdModule" ' Calling procedure of ThisWorkbook module. bk.ProcInThisWorkbook End Sub |
||
24行目と26行目で2つのモジュールに追加したプロシージャを呼び出しますが,標準モジュールのプロシージャを呼び出すのとExcelオブジェクト(ThisWorkbook)モジュールに追加したプロシージャを呼び出すのとでは方法が異なります。ThisWorkbookオブジェクトのプロシージャの呼び出しは,通常のオブジェクトメソッド呼び出しと同じですが,外部プロジェクトの標準モジュールのプロシージャ呼び出しにはApplication.Runメソッドを使用します。Runメソッドの文法は以下の通りで,ワークブック名とプロシージャ名との連結には,Excelの数式内で外部ワークブックを参照するときと同じ"!"を用います。
Application.Runメソッド
指定したマクロを呼び出します。
構文
RetValue = Application.Run(macro, arg1, arg2, ... , arg30)
指定項目 | 内容 |
macro | 実行するマクロを以下のフォーマットの文字列として指定します。 "(ワークブック名)!(マクロ名)" |
arg1 ~ arg30 | マクロに引き渡す最大30個の引数 |
この例では,別のプロジェクト(ワークブック)にコードを追加しましたが,プログラムを実行しているプロジェクト自身のコードを変更することも可能です。ただし,そのような処理はエラーを引き起こしたり,Excel自身の動作を不安定にしたりする場合もありますので,あまり安易に使用しない方が無難です。