2008-09-08 5 views
14

Ist es möglich, den gesamten VBA-Code aus einem Word 2007 "Docm" -Dokument mithilfe der API zu extrahieren?Makrocode (VBA) programmatisch aus Word 2007-Dokumenten extrahieren

Ich habe gefunden, wie Sie VBA-Code zur Laufzeit einfügen, und wie Sie alle VBA-Code löschen, aber nicht den tatsächlichen Code in einen Stream oder String, die ich speichern (und zukünftig in andere Dokumente einfügen).

Alle Tipps oder Ressourcen würden geschätzt.

Bearbeiten: danke an alle, Aardvark 's Antwort war genau das, was ich gesucht habe. Ich habe seinen Code in C# konvertiert, und konnte es von einer Klassenbibliothek nennen Visual Studio 2008.

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; 
} 
+1

den Stringbuilder Nutzen Sie die Speichernutzung zu optimieren: String sb = new Stringbuilder(); für .... sb.AppendLine ("Ihre Codezeile"); ... macros.Add (sb.ToString()); – Skuami

Antwort

9

Sie werden für Applikationen Extensibility 5.3 einen Verweis auf Microsoft Visual Basic hinzufügen müssen (oder was auch immer Version du hast). Ich habe das VBA-SDK und so auf meiner Box - so kann das nicht genau sein, womit das Büro ausgeliefert wird.

Außerdem müssen Sie den Zugriff auf das VBA-Objektmodell speziell aktivieren - siehe "Trust Center" in den Word-Optionen. Dies ist zusätzlich zu allen anderen Makrosicherheitseinstellungen, die Office bereitstellt.

Dieses Beispiel wird Code aus dem aktuellen Dokument, in dem es sich befindet, extrahieren - es selbst ist ein VBA-Makro (und wird sich selbst und anderen Code auch anzeigen). Es gibt auch eine Application.vbe.VBProjects-Sammlung, um auf andere Dokumente zuzugreifen. Obwohl ich es noch nie gemacht habe, nehme ich an, dass eine externe Anwendung Dateien mit dieser VBProjects-Sammlung öffnen könnte. Sicherheit ist lustig mit diesem Zeug, also kann es schwierig sein.

Ich frage mich auch, was das Docm-Dateiformat jetzt ist - XML ​​wie das docx? Wäre das ein besserer Ansatz?

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 
+1

Das ist großartig, danke! Ich habe Ihren Code in C# konvertiert und kann ihn von einer WPF-Anwendung aus aufrufen und den Makrocode in einer Listbox ausdrucken. Ich werde die C# -Version des Codes in meiner bearbeiteten Antwort veröffentlichen. –

+1

Wenn Sie Formulare in Ihrem Projekt haben, ist dies nicht ideal. Der Steuerdefinitionsteil des Formulars wird nicht exportiert. – MarkJ

+0

Bestätigung der '.xlsb' Dateien sind Zip-Dateien (wie erwartet), aber das vbaProject ist immer noch in einer' .bin' Datei gespeichert, die eindeutig ein zusammengesetztes Dokument ist (eine der ersten lesbaren Zeichenfolgen ist 'Root Entry'). –

25

Sie könnten den Code-Dateien exportieren und sie dann in zurücklesen.

Ich habe den Code benutze ich unten zu helfen, unter Quellcodeverwaltung einige Excel-Makros zu halten (mit Subversion & TortoiseSVN). Es exportiert im Grunde den gesamten Code in Textdateien, wenn ich bei geöffnetem VBA-Editor speichere. Ich stelle die Textdateien in Subversion, damit ich Diffs machen kann. Sie sollten in der Lage sein, etwas davon anzupassen/zu stehlen, um in Word zu arbeiten.

Die Registrierungsprüfung in CanAccessVBOM() entspricht dem "Zugriff auf Visual Basic-Projekt vertrauen" in der Sicherheitseinstellung.

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 
+1

Das ist schön, da Sie Formulare und solche intakt bekommen. +1 – Aardvark

Verwandte Themen