vba - проверять документы на наличие макросов и заменять текст макросов? - PullRequest
3 голосов
/ 16 ноября 2009

Мне преподносят головоломку. Там, где я работаю, есть огромное количество шаблонов Word, каждый из которых содержит автономный дескриптор события, который содержит некоторые ошибки. И эта ошибка лежит во всех шаблонах. И мне было интересно, может ли быть способ сканирования каталога на наличие шаблонов, содержащих этот макрос, и незначительное изменение кода макроса?

Может ли это быть возможно?

1 Ответ

8 голосов
/ 16 ноября 2009

Да, вы можете сделать это. Вы можете получить доступ к проекту VBA любого документа, используя:

Application.VBE.ActiveVBProject.VBComponents

Ваш проект должен иметь ссылку на «Microsoft Visual Basic для расширяемости приложений».

Чтобы запустить код, вы должны включить опцию «Доверительный доступ к проекту Visual Basic» в Word, используя

Инструменты-> Макрос-> Безопасность (Доверенные Вкладка "Издатели")

Коллекция VBComponents содержит все стандартные модули, модули классов, формы и модули «документ», содержащиеся в проекте. Если вы зайдете в Google, вы найдете множество справок о том, как получить к ним доступ или изменить их.

РЕДАКТИРОВАТЬ : ОК, более подробно. Этот метод будет искать во всем 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

Обратите внимание, что это будет работать только с методами Sub и Function, а не со свойством Get/Set/Let, потому что я использую vbext_pk_Proc. Это PITA, что вы должны быть откровенными об этом. Честно говоря, весь API для компонента CodeModule, похоже, почти расстроен. Например, хотя объект VbComponent имеет метод Find (который, как вы думаете, был бы удобным способом поиска искомого текста), он фактически возвращает True или False (!). Полезно, я не думаю!

У разработчиков этого API должно было быть очень плохое похмелье, когда они это делали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...