Question

Est-il possible d'extraire tout le code VBA d'un document « docm » Word 2007 à l'aide de l'API ?

J'ai trouvé comment insérer du code VBA au moment de l'exécution et comment supprimer tout le code VBA, sans extraire le code réel dans un flux ou une chaîne que je peux stocker (et insérer dans d'autres documents à l'avenir).

Tous les conseils ou ressources seraient appréciés.

Modifier:Merci à tout le monde, AardvarkLa réponse de était exactement ce que je cherchais.J'ai converti son code en C# et j'ai pu l'appeler à partir d'une bibliothèque de classes à l'aide de 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;
}
Était-ce utile?

La solution

Vous devrez ajouter une référence à Microsoft Visual Basic pour Applications Extensibility 5.3 (ou quelle que soit la version dont vous disposez).J'ai le SDK VBA et autres sur ma boîte - donc ce n'est peut-être pas exactement ce qu'Office est livré.

Vous devez également activer spécifiquement l'accès au modèle objet VBA - voir le "Centre de confiance" dans les options de Word.Ceci s’ajoute à tous les autres paramètres de sécurité des macros fournis par Office.

Cet exemple extraira le code du document actuel dans lequel il réside - il s'agit lui-même d'une macro VBA (et s'affichera ainsi que tout autre code).Il existe également une collection Application.vbe.VBProjects pour accéder à d'autres documents.Bien que je ne l'ai jamais fait, je suppose qu'une application externe pourrait également ouvrir des fichiers à l'aide de cette collection VBProjects.La sécurité est amusante avec ce genre de choses, donc cela peut être délicat.

Je me demande aussi quel est le format de fichier docm maintenant - XML ​​comme le docx ?Serait-ce une meilleure approche ?

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

Autres conseils

Vous pouvez exporter le code vers des fichiers, puis le relire.

J'utilise le code ci-dessous pour m'aider à conserver certaines macros Excel sous contrôle de code source (en utilisant Subversion et TortoiseSVN).En gros, il exporte tout le code vers des fichiers texte chaque fois que j'enregistre avec l'éditeur VBA ouvert.J'ai mis les fichiers texte dans Subversion pour pouvoir faire des différences.Vous devriez pouvoir en adapter/voler une partie pour fonctionner dans Word.

La vérification du registre dans CanAccessVBOM() correspond à « Accès approuvé au projet Visual Basic » dans le paramètre de sécurité.

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top