Excel 2007では、いくつかのプロパティやメソッドが追加されています。
WorkbookオブジェクトのHasVBProjectプロパティも新しいプロパティです。
HasVBProjectプロパティは、ブックにマクロが含まれているかどうかを返します。
Sub Sample1()
MsgBox Workbooks(2).HasVBProject
End Sub
Sub ○○〜End Subというプロシージャが存在すれば、もちろんマクロが含まれていると認識されますし、標準モジュールやUserFormが追加されていても、マクロが含まれていることになります。
非常に便利なHasVBProjectプロパティですが、残念ながらExcel 2007でしか使えません。
では、Excel 2003以前のVBAで、任意のブックにマクロが含まれているかどうかを判定することはできないのでしょうか。
もちろん可能です。
ここでは、2つのブックを開き、2番目のブックにマクロが含まれているかどうかを調べてみましょう。
2番目のブックは、新規作成したままの状態で「名前を付けて保存」してください。
ファイル名や保存するフォルダは、ご自由にどうぞ。
なお、これ以降のマクロはVBEにアクセスします。マクロでVBEにアクセスするには、Excelの[ツール]-[マクロ]-[セキュリティ]で[セキュリティ]ダイアログボックスを開き、[信頼のおける発行元]タブにある[Visual Basicプロジェクトへのアクセスを信頼する]チェックボックスをオンにしてください。
そのほか、特別な参照設定などは必要ありません。
VBEのモジュールにアクセスするには、まずVBEオブジェクトを利用します。
VBEオブジェクトはVBE全体を表すオブジェクトです。
Excel上で開いているブックは、VBEで見ると「VBAProject」と表示されます。
このVBProjectもオブジェクトとして操作可能です。
次のコードは、VBEで現在開いているVBProjectをイミディエイトウィンドウに出力します。
Sub Sample2()
Dim i As Long
Debug.Print Application.VBE.VBProjects.Count & "個のVBProject"
For i = 1 To Application.VBE.VBProjects.Count
Debug.Print Application.VBE.VBProjects(i).Filename
Next i
End Sub
ブックには「Sheet1」や「ThisWorkbook」などのDocumentモジュールがあります。
また、標準モジュールやUserFormを挿入することもできます。
そうした、プロシージャの記述場所である"モジュール"は、VBComponentオブジェクトとして表されます。
次のコードは、2番目のブックに存在するすべてのモジュールを調べます。
Sub Sample3()
Dim vbc As Object
For Each vbc In Workbooks(2).VBProject.VBComponents
Debug.Print vbc.Name & vbTab & vbc.Type
Next vbc
End Sub
VBComponentオブジェクトのTypeプロパティは、次の値を返します。
「ActiveX デザイナ」は特別な開発環境でしか使用しませんので、解説を割愛します。
ブックが標準で持っている「Sheet1」「ThisWorkbook」などのDocumentモジュールはTypeプロパティが100を返します。
したがって、Typeプロパティが「100でない」VBComponentオブジェクトが存在したら、それはマクロが存在すると判断してもいいでしょう。
Sub Sample4()
Dim vbc As Object, flag As Boolean
For Each vbc In Workbooks(2).VBProject.VBComponents
If vbc.Type <> 100 Then
flag = True
End If
Next vbc
If flag Then
MsgBox "マクロが存在します"
Else
MsgBox "マクロは存在しません"
End If
End Sub
これで、標準モジュールやUserFormの存在を判定できます。
しかし、ブックの「Sheet1」や「ThisWorkbook」にもプロシージャは記述できます。
Documentモジュールにプロシージャが記述されているかどうかは、次のようにして調べられます。
プロシージャを記述するコードウィンドウはCodeModuleオブジェクトとして操作できます。
CodeModuleオブジェクトにはコードウィンドウ内の全行数を返すCountOfLinesプロパティと任意の行が、どのプロシージャに属するかを返すProcOfLineプロパティがあります。
これらを組み合わせて、コードウィンドウ内に1つ以上のプロシージャが存在するかどうかを判定します。
Sub Sample5()
Dim vbc As Object, flag As Boolean, I As Long, buf As String
For Each vbc In Workbooks(2).VBProject.VBComponents
If vbc.Type <> 100 Then
flag = True
Else
For I = 1 To vbc.CodeModule.CountOfLines
buf = vbc.CodeModule.ProcOfLine(I, 0)
Next I
End If
Next vbc
If flag Or buf <> "" Then
MsgBox "マクロが存在します"
Else
MsgBox "マクロは存在しません"
End If
End Sub
とりあえず、これでマクロが存在するかどうかは判定できました。
上記のSample5は省略した部分も多く、決して洗練されたコードではありませんが、VBAからVBEを操作するマクロは奥が深いので、本稿ではここまでとします。