vba - 扫描宏的文档并替换宏文本?

时间:2009-11-16 12:56:46

标签: c# vb.net vba

我遇到了一个谜题。在我工作的地方有大量的Word模板,它们都包含一个包含一些错误的autonew事件句柄。而且这个错误存在于所有模板中。我想知道是否有办法扫描包含此宏的模板的目录并稍微更改宏代码?

这可能吗?

1 个答案:

答案 0 :(得分:8)

是的,你可以这样做。您可以使用以下方式访问任何文档的VBA项目:

Application.VBE.ActiveVBProject.VBComponents

您的项目必须引用“Microsoft Visual Basic for Applications Extensibility”。

要运行代码,必须使用

启用Word中的“Trust Access to Visual Basic Project”选项
  

工具 - >宏 - >安全(可信   发布商标签)

VBComponents集合包含项目包含的所有标准模块,类模块,表单和“文档”模块。如果你谷歌它,你会找到很多关于如何访问/修改它们的帮助。

编辑:好的,还有一些细节。此方法将搜索文档的所有VbComponents,以查找具有指定名称的方法,并在找到的第一个文档中执行搜索/替换。

Public Sub ReplaceInProject(ByVal oDocument As Document, ByVal strMethodName As String, ByVal strFindText As String, ByVal strReplaceWithText As String)

    ' For each module (of any type - could use oVbComponent.Type to restrict
    ' this to certain types of module)

    Dim oVbComponent As VBComponent
    For Each oVbComponent In oDocument.VBProject.VBComponents

        Dim oCodeModule As CodeModule
        Set oCodeModule = oVbComponent.CodeModule

        ' See if we can find the method in this module

        Dim ixStartLine As Long
        ixStartLine = FindMethodStartLine(oCodeModule, strMethodName)

        If ixStartLine > 0 Then

            ' Get all the text of the method

            Dim numLines As Long
            numLines = oCodeModule.ProcCountLines(strMethodName, vbext_pk_Proc)

            Dim strLines As String
            strLines = oCodeModule.Lines(ixStartLine, numLines)

            ' Do the find/replace

            strLines = Replace(strLines, strFindText, strReplaceWithText)

            ' Replace the method text.

            oCodeModule.DeleteLines ixStartLine, numLines

            oCodeModule.InsertLines ixStartLine, strLines

        End If

    Next oVbComponent

End Sub

Private Function FindMethodStartLine(ByVal oCodeModule As CodeModule, ByVal strMethodName As String) As Long

    FindMethodStartLine = 0

    ' ProcStartLine will raise an error if the method is not found;
    ' we'll just ignore the error and return -1

    On Error Resume Next
    FindMethodStartLine = oCodeModule.ProcStartLine(strMethodName, vbext_pk_Proc)

End Function

请注意,这仅适用于SubFunction方法,而不适用于属性Get/Set/Let,因为我正在使用vbext_pk_Proc。这是一个PITA,你需要明确这一点。坦率地说,CodeModule组件的整个API似乎几乎被设计为令人沮丧。例如,虽然VbComponent对象具有Find方法(您认为这是查找正在查找的文本的便捷方式),但它实际上会返回True或{ {1}(!)。有用,我不认为!

这个API的设计者在这样做时必须有一个非常糟糕的宿醉。