是否可以使用API从Word 2007“docm”文档中提取所有VBA代码?
我已经找到了如何在运行时插入VBA代码,以及如何删除所有VBA代码,但是没有将实际代码拉出到我可以存储的流或字符串中(以及将来插入到其他文档中)。 / p>
任何提示或资源都将受到赞赏。
修改:感谢所有人,Aardvark的答案正是我所寻找的。我已将其代码转换为C#,并且能够使用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;
}
答案 0 :(得分:27)
您可以将代码导出到文件中,然后再将其读回。
我一直在使用下面的代码来帮助我在源代码控制下保留一些Excel宏(使用Subversion&amp; TortoiseSVN)。它基本上在我打开VBA编辑器时保存所有代码到文本文件。我把文本文件放在subversion中,这样我就可以做差异了。你应该能够适应/窃取其中一些在Word中工作。
CanAccessVBOM()中的注册表检查对应于安全设置中的“对Visual Basic项目的信任访问”。
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 :(得分:9)
您必须添加对Microsoft Visual Basic for Applications Extensibility 5.3(或您拥有的任何版本)的引用。我的盒子上有VBA SDK等 - 所以这可能不是办公室随附的。
此外,您还必须专门启用对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