<p>Is it possible to extract all of the VBA code from a Word 2007 "docm" document using the API?</p>

<p>I have found how to insert VBA code at runtime, and how to delete all VBA code, but not pull the actual code out into a stream or string that I can store (and insert into other documents in the future).</p>

<p>Any tips or resources would be appreciated.</p>

<p><strong>Edit</strong>: thanks to everyone, <a href="https://stackoverflow.com/users/3655/aardvark">Aardvark</a>'s answer was exactly what I was looking for.  I have converted his code to C#, and was able to call it from a class library using Visual Studio 2008.</p>

<pre><code>using Microsoft.Office.Interop.Word;
using Microsoft.Vbe.Interop;

...

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

    List&lt;string&gt; macros = new List&lt;string&gt;();

    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 &lt; 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;
}
</code></pre>

[{'answer_id': 49773, 'author': 'Aardvark', 'author_id': 3655, 'author_profile': 'https://Stackoverflow.com/users/3655', 'pm_score': 5, 'selected': True, 'text': '<p>You\'ll have to add a reference to Microsoft Visual Basic for Applications Extensibility 5.3 (or whatever version you have). I have the VBA SDK and such on my box - so this may not be exactly what office ships with.</p>\n\n<p>Also you have to enable access to the VBA Object Model specifically - see the "Trust Center" in Word options. This is in addition to all the other Macro security settings Office provides.</p>\n\n<p>This example will extract code from the current document it lives in - it itself is a VBA macro (and will display itself and any other code as well). There is also a Application.vbe.VBProjects collection to access other documents. While I\'ve never done it, I assume an external application could get to open files using this VBProjects collection as well. Security is funny with this stuff so it may be tricky.</p>\n\n<p>I also wonder what the docm file format is now - XML like the docx? Would that be a better approach? </p>\n\n<pre><code>Sub GetCode()\n\n    Dim prj As VBProject\n    Dim comp As VBComponent\n    Dim code As CodeModule\n    Dim composedFile As String\n    Dim i As Integer\n\n    Set prj = ThisDocument.VBProject\n        For Each comp In prj.VBComponents\n            Set code = comp.CodeModule\n\n            composedFile = comp.Name &amp; vbNewLine\n\n            For i = 1 To code.CountOfLines\n                composedFile = composedFile &amp; code.Lines(i, 1) &amp; vbNewLine\n            Next\n\n            MsgBox composedFile\n        Next\n\nEnd Sub\n</code></pre>\n'}, {'answer_id': 49796, 'author': 'Jim Harte', 'author_id': 4544, 'author_profile': 'https://Stackoverflow.com/users/4544', 'pm_score': 5, 'selected': False, 'text': '<p>You could export the code to files and then read them back in.</p>\n\n<p>I\'ve been using the code below to help me keep some Excel macros under source control (using Subversion &amp; TortoiseSVN).  It basically exports all the code to text files any time I save with the VBA editor open.  I put the text files in subversion so that I can do diffs.  You should be able to adapt/steal some of this to work in Word.</p>\n\n<p>The registry check in CanAccessVBOM() corresponds to the "Trust access to Visual Basic Project" in the security setting.</p>\n\n<pre class="lang-vb prettyprint-override"><code>Sub ExportCode()\n\n    If Not CanAccessVBOM Then Exit Sub \' Exit if access to VB object model is not allowed\n    If (ThisWorkbook.VBProject.VBE.ActiveWindow Is Nothing) Then\n        Exit Sub \' Exit if VBA window is not open\n    End If\n    Dim comp As VBComponent\n    Dim codeFolder As String\n\n    codeFolder = CombinePaths(GetWorkbookPath, "Code")\n    On Error Resume Next\n    MkDir codeFolder\n    On Error GoTo 0\n    Dim FileName As String\n\n    For Each comp In ThisWorkbook.VBProject.VBComponents\n        Select Case comp.Type\n            Case vbext_ct_ClassModule\n                FileName = CombinePaths(codeFolder, comp.Name &amp; ".cls")\n                DeleteFile FileName\n                comp.Export FileName\n            Case vbext_ct_StdModule\n                FileName = CombinePaths(codeFolder, comp.Name &amp; ".bas")\n                DeleteFile FileName\n                comp.Export FileName\n            Case vbext_ct_MSForm\n                FileName = CombinePaths(codeFolder, comp.Name &amp; ".frm")\n                DeleteFile FileName\n                comp.Export FileName\n            Case vbext_ct_Document\n                FileName = CombinePaths(codeFolder, comp.Name &amp; ".cls")\n                DeleteFile FileName\n                comp.Export FileName\n        End Select\n    Next\n\nEnd Sub\nFunction CanAccessVBOM() As Boolean\n    \' Check resgistry to see if we can access the VB object model\n    Dim wsh As Object\n    Dim str1 As String\n    Dim AccessVBOM As Long\n\n    Set wsh = CreateObject("WScript.Shell")\n    str1 = "HKEY_CURRENT_USER\\Software\\Microsoft\\Office\\" &amp; _\n        Application.Version &amp; "\\Excel\\Security\\AccessVBOM"\n    On Error Resume Next\n    AccessVBOM = wsh.RegRead(str1)\n    Set wsh = Nothing\n    CanAccessVBOM = (AccessVBOM = 1)\nEnd Function\n\n\nSub DeleteFile(FileName As String)\n    On Error Resume Next\n    Kill FileName\nEnd Sub\n\nFunction GetWorkbookPath() As String\n    Dim fullName As String\n    Dim wrkbookName As String\n    Dim pos As Long\n\n    wrkbookName = ThisWorkbook.Name\n    fullName = ThisWorkbook.fullName\n\n    pos = InStr(1, fullName, wrkbookName, vbTextCompare)\n\n    GetWorkbookPath = Left$(fullName, pos - 1)\nEnd Function\n\nFunction CombinePaths(ByVal Path1 As String, ByVal Path2 As String) As String\n    If Not EndsWith(Path1, "\\") Then\n        Path1 = Path1 &amp; "\\"\n    End If\n    CombinePaths = Path1 &amp; Path2\nEnd Function\n\nFunction EndsWith(ByVal InString As String, ByVal TestString As String) As Boolean\n    EndsWith = (Right$(InString, Len(TestString)) = TestString)\nEnd Function\n</code></pre>\n'}]
['https://Stackoverflow.com/questions/49724', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/2194/']