15

APIを使用してWord2007の「docm」ドキュメントからすべてのVBAコードを抽出することは可能ですか?

実行時にVBAコードを挿入する方法と、すべてのVBAコードを削除する方法を見つけましたが、実際のコードを、保存できる(そして将来的に他のドキュメントに挿入する)ストリームまたは文字列に引き出すことはできません。

ヒントやリソースをいただければ幸いです。

編集:みんなのおかげで、Aardvarkの答えはまさに私が探していたものでした。彼のコードをC#に変換し、VisualStudio2008を使用してクラスライブラリから呼び出すことができました。

using Microsoft.Office.Interop.Word;
using Microsoft.Vbe.Interop;

...

public List<string> GetMacrosFromDoc()
{
    Document doc = GetWordDoc(@"C:\Temp\test.docm");

    List<string> macros = new List<string>();

    VBProject prj;
    CodeModule code;
    string composedFile;

    prj = doc.VBProject;
    foreach (VBComponent comp in prj.VBComponents)
    {
        code = comp.CodeModule;

        // Put the name of the code module at the top
        composedFile = comp.Name + Environment.NewLine;

        // Loop through the (1-indexed) lines
        for (int i = 0; i < code.CountOfLines; i++)
        {
            composedFile += code.get_Lines(i + 1, 1) + Environment.NewLine;
        }

        // Add the macro to the list
        macros.Add(composedFile);
    }

    CloseDoc(doc);

    return macros;
}
4

2 に答える 2

29

コードをファイルにエクスポートしてから、に読み戻すことができます。

以下のコードを使用して、いくつかのExcelマクロをソース管理下に置いています(SubversionとTortoiseSVNを使用)。基本的に、VBAエディターを開いた状態で保存すると、すべてのコードがテキストファイルにエクスポートされます。差分を実行できるように、テキストファイルをsubversionに入れました。これの一部をWordで機能するように適応/盗むことができるはずです。

CanAccessVBOM()のレジストリチェックは、セキュリティ設定の「VisualBasicプロジェクトへのアクセスを信頼する」に対応しています。

Sub ExportCode()

    If Not CanAccessVBOM Then Exit Sub ' Exit if access to VB object model is not allowed
    If (ThisWorkbook.VBProject.VBE.ActiveWindow Is Nothing) Then
        Exit Sub ' Exit if VBA window is not open
    End If
    Dim comp As VBComponent
    Dim codeFolder As String

    codeFolder = CombinePaths(GetWorkbookPath, "Code")
    On Error Resume Next
    MkDir codeFolder
    On Error GoTo 0
    Dim FileName As String

    For Each comp In ThisWorkbook.VBProject.VBComponents
        Select Case comp.Type
            Case vbext_ct_ClassModule
                FileName = CombinePaths(codeFolder, comp.Name & ".cls")
                DeleteFile FileName
                comp.Export FileName
            Case vbext_ct_StdModule
                FileName = CombinePaths(codeFolder, comp.Name & ".bas")
                DeleteFile FileName
                comp.Export FileName
            Case vbext_ct_MSForm
                FileName = CombinePaths(codeFolder, comp.Name & ".frm")
                DeleteFile FileName
                comp.Export FileName
            Case vbext_ct_Document
                FileName = CombinePaths(codeFolder, comp.Name & ".cls")
                DeleteFile FileName
                comp.Export FileName
        End Select
    Next

End Sub
Function CanAccessVBOM() As Boolean
    ' Check resgistry to see if we can access the VB object model
    Dim wsh As Object
    Dim str1 As String
    Dim AccessVBOM As Long

    Set wsh = CreateObject("WScript.Shell")
    str1 = "HKEY_CURRENT_USER\Software\Microsoft\Office\" & _
        Application.Version & "\Excel\Security\AccessVBOM"
    On Error Resume Next
    AccessVBOM = wsh.RegRead(str1)
    Set wsh = Nothing
    CanAccessVBOM = (AccessVBOM = 1)
End Function


Sub DeleteFile(FileName As String)
    On Error Resume Next
    Kill FileName
End Sub

Function GetWorkbookPath() As String
    Dim fullName As String
    Dim wrkbookName As String
    Dim pos As Long

    wrkbookName = ThisWorkbook.Name
    fullName = ThisWorkbook.fullName

    pos = InStr(1, fullName, wrkbookName, vbTextCompare)

    GetWorkbookPath = Left$(fullName, pos - 1)
End Function

Function CombinePaths(ByVal Path1 As String, ByVal Path2 As String) As String
    If Not EndsWith(Path1, "\") Then
        Path1 = Path1 & "\"
    End If
    CombinePaths = Path1 & Path2
End Function

Function EndsWith(ByVal InString As String, ByVal TestString As String) As Boolean
    EndsWith = (Right$(InString, Len(TestString)) = TestString)
End Function
于 2008-09-08T14:21:27.320 に答える
11

Microsoft Visual Basic for Applications Extensibility 5.3(または使用しているバージョン)への参照を追加する必要があります。ボックスにVBASDKなどが入っているので、これはOfficeに付属しているものとは異なる場合があります。

また、VBAオブジェクトモデルへのアクセスを具体的に有効にする必要があります。Wordオプションの「セキュリティセンター」を参照してください。これは、Officeが提供する他のすべてのマクロセキュリティ設定に追加されます。

この例では、現在のドキュメントからコードを抽出します。これは、それ自体がVBAマクロです(また、それ自体と他のコードも表示します)。他のドキュメントにアクセスするためのApplication.vbe.VBProjectsコレクションもあります。私はこれを行ったことがありませんが、外部アプリケーションがこのVBProjectsコレクションを使用してファイルを開くこともできると思います。このようなものではセキュリティがおかしいので、注意が必要かもしれません。

また、docmファイル形式が現在何であるか疑問に思います-docxのようなXML?それはより良いアプローチでしょうか?

Sub GetCode()

    Dim prj As VBProject
    Dim comp As VBComponent
    Dim code As CodeModule
    Dim composedFile As String
    Dim i As Integer

    Set prj = ThisDocument.VBProject
        For Each comp In prj.VBComponents
            Set code = comp.CodeModule

            composedFile = comp.Name & vbNewLine

            For i = 1 To code.CountOfLines
                composedFile = composedFile & code.Lines(i, 1) & vbNewLine
            Next

            MsgBox composedFile
        Next

End Sub
于 2008-09-08T14:08:09.270 に答える