Word VBA未正确运行脚本

时间:2017-08-04 17:22:37

标签: word-vba

如果我从VBA编辑器中启动脚本,我遇到了运行正常的脚本问题,但是当我直接从Word启动它时却没有。作为解释,脚本定义Word文档中的首字母缩写词。在Word文件出现之前,它会进行第一级编辑,编辑器会在其中突出显示他/她已验证的术语。因为我的脚本也使用突出显示,所以我用彩色文本替换现有的突出显示。

'Turn track changes off, replace yellow highlighting from FLEs with colored text to avoid confusion between
'FLE highlighting and acronym defininer highlighting
ActiveDocument.TrackRevisions = False
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting

With Selection.Find

    .Highlight = True

    With .Replacement

        .Highlight = False
        .Font.Color = RGB(155, 187, 89)

    End With

    .Execute Replace:=wdReplaceAll, Wrap:=wdFindStop

End With

Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting

当我直接从Word运行脚本时,它会跳过整个代码块。其他所有工作都应该如此,但第一级编辑的重点仍然存在。当我直接从VBA编辑器运行时,一切都按预期工作。当我进行其他更改时(例如,我刚刚更新了宏调用的一个表单以添加绿色文本的解释),无论我从哪里开始编写脚本,它们都会通过。任何想法为什么这部分代码可能会被跳过?以下是整个脚本。

Option Explicit
Public Definitions(5) As String

Sub Acronym_Definer()
'Defines Workbook and Worksheet, Opens Excel
Dim xlApp As Excel.Application
Dim xlWbk As Workbook
Dim FN As String: FN = "C:\Users\" & Environ$("Username") & "\AppData\Roaming\Gartner\AcronymDefiner\AcronymDefiner.xlsx"

Dim Current_Row As Long: Current_Row = 2

Set xlApp = New Excel.Application
xlApp.Visible = False
Set xlWbk = xlApp.Workbooks.Open(FN)

'Determines whether Track Changes is on or off so it can be returned to original state at end of macro
Dim Track_Changes As Boolean
If ActiveDocument.TrackRevisions = False Then

    Track_Changes = False

End If

'Changes to Simple View in Track Changes to keep deleted text from coming up in searches throughout the macro
With ActiveWindow.View.RevisionsFilter
    .Markup = wdRevisionsMarkupSimple
    .View = wdRevisionsViewFinal
End With

'Turn track changes off, replace yellow highlighting from FLEs with colored text to avoid confusion between
'FLE highlighting and acronym defininer highlighting
ActiveDocument.TrackRevisions = False
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting

With Selection.Find

    .Highlight = True

    With .Replacement

        .Highlight = False
        .Font.Color = RGB(155, 187, 89)

    End With

    .Execute Replace:=wdReplaceAll, Wrap:=wdFindStop

End With

Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting

'Begins acronym definition loop
Do While Current_Row <= xlWbk.ActiveSheet.UsedRange.Rows.Count

    'Use to decide which column to check for NNTD status
    Dim NNTD_Column As Integer
    Dim NNTD As Boolean: NNTD = False

    Dim Chosen_Definition As String
    Dim Current_Acronym As String: Current_Acronym = xlWbk.ActiveSheet.Cells(Current_Row, 1)
    Dim User_Skip As Boolean

    Selection.HomeKey unit:=wdStory

    With Selection.Find

        .ClearFormatting
        '.Font.Color = wdColorAutomatic
        .Text = Current_Acronym
        .MatchCase = True
        .MatchWholeWord = True
        .Wrap = wdFindStop

    End With

    'Check for presence of acronym
    If Selection.Find.Execute Then

        'How many definitions does this acronym have?
        Dim Number_Definitions As Integer: Number_Definitions = xlWbk.ActiveSheet.Cells(Current_Row, 2)

        'There's only one definition; the definition is in column 3 and the NNTD status is in column 4
        If Number_Definitions = 1 Then

            Chosen_Definition = xlWbk.ActiveSheet.Cells(Current_Row, 3)
            NNTD_Column = 4
            NNTD = xlWbk.ActiveSheet.Cells(Current_Row, NNTD_Column)
            User_Skip = False

        'There's more than one definition; put definitions into array and get definition from user form
        Else

            'Ensures Array is empty at start of each loop
            Erase Definitions

            'Adds the definitions to Definitions array
            Dim i As Integer
            Dim Current_Column As Integer: Current_Column = 3

            For i = 1 To Number_Definitions

                Definitions(i - 1) = xlWbk.ActiveSheet.Cells(Current_Row, Current_Column)
                Current_Column = Current_Column + 2

            Next i

            'Opens userform to allow user to choose from the available definitions
            Load DefinitionList
            DefinitionList.lstAvailableDefinitions.List = Definitions
            DefinitionList.Show

            'Did the user select an option?
            If IsNull(DefinitionList.lstAvailableDefinitions.Value) Then

                User_Skip = True

            Else

                'Assigns user selection to Chosen_Definition variable
                Chosen_Definition = DefinitionList.lstAvailableDefinitions.Value

                User_Skip = False

                'Determines NNTD column
                Dim j As Integer
                For j = LBound(Definitions) To UBound(Definitions)

                    If Definitions(j) = Chosen_Definition Then
                    NNTD_Column = (2 * j) + 4
                    Exit For
                    End If

                Next j

                Unload DefinitionList

            NNTD = xlWbk.ActiveSheet.Cells(Current_Row, NNTD_Column)

            End If

        End If

        'Acronym is NNTD
        If NNTD = True Then

            'Highlights NNTD acronyms in yellow.
            Options.DefaultHighlightColorIndex = wdYellow
            Selection.HomeKey unit:=wdStory

            With Selection.Find

                '.Font.Color = wdColorAutomatic
                .Text = Current_Acronym
                .MatchCase = True
                .MatchWholeWord = True

                With .Replacement

                    .Highlight = True
                    .Text = ""

                End With

                .Execute Replace:=wdReplaceAll, Wrap:=wdFindStop

            End With

        'User chose to skip or clicked OK without selecting an option; highlight all instances of acronym in red
        ElseIf User_Skip = True Then

            Unload DefinitionList

            Options.DefaultHighlightColorIndex = wdRed
            Selection.HomeKey unit:=wdStory

            With Selection.Find

                '.Font.Color = wdColorAutomatic
                .Text = Current_Acronym
                .MatchCase = True
                .MatchWholeWord = True

                With .Replacement

                    .Highlight = True
                    .Text = ""

                End With

                .Execute Replace:=wdReplaceAll, Wrap:=wdFindStop

            End With

        'Acronym needs to be defined
        Else

            'Selects first instance of acronym. Get start position of first instance of acronym.
            Selection.HomeKey unit:=wdStory
            Selection.Find.Execute Current_Acronym
            Dim AcronymStart As Long: AcronymStart = Selection.Start

            'Determines whether definition occurs in document
            Selection.HomeKey unit:=wdStory
            With Selection.Find

                '.Font.Color = wdColorAutomatic
                .Text = Chosen_Definition
                .MatchCase = False
                .Execute Wrap:=wdFindStop

            End With

            'Definition doesn't occur; insert definition before first definition of acronym and add
            'parentheses around acronym
            If Selection.Find.Found = False Then

                Selection.HomeKey unit:=wdStory

                With Selection.Find

                    '.Font.Color = wdColorAutomatic
                    .Text = Current_Acronym
                    .MatchCase = True
                    .Execute

                End With

                With Selection

                    .InsertBefore Chosen_Definition & " ("
                    .InsertAfter ")"

                End With

            'Definition occurs in document; get end position of definition and compare to start position of acronym
            '(should be two lower than acronym)
            Else

                Selection.HomeKey unit:=wdStory
                Selection.Find.Execute Chosen_Definition
                Dim DefinitionEnd As Long: DefinitionEnd = Selection.End

                'Acronym is correctly defined; no further action is needed to define the acronym
                If DefinitionEnd = AcronymStart - 2 Then

                'Definition occurs after acronym; insert definition before first instance of acronym
                ElseIf DefinitionEnd > AcronymStart Then

                    'Moves to first instance of acronym
                    Selection.HomeKey unit:=wdStory

                    'Adds definition and places parentheses around acronym
                    With Selection.Find

                        '.Font.Color = wdColorAutomatic
                        .Text = Current_Acronym
                        .MatchCase = True
                        .Execute

                    End With

                    With Selection

                        .InsertBefore Chosen_Definition & " ("
                        .InsertAfter ")"

                    End With

                'Definition occurs before (but not immediately prior to) acronym
                Else

                    Selection.HomeKey unit:=wdStory
                    Selection.Find.Execute Chosen_Definition

                    'Inserts acronym (surrounded by parentheses) after definition
                    With Selection

                        .InsertAfter " (" & Current_Acronym & ")"

                    End With

                End If

            End If

            'Replace subsequent instances of acronym *and* definition with just acronym
            Dim Defined_Acronym As String: Defined_Acronym = Chosen_Definition & " (" & Current_Acronym & ")"

            'Moves cursor to follow first instance of Defined_Acronym
            Selection.HomeKey unit:=wdStory

            With Selection.Find

                '.Font.Color = wdColorAutomatic
                .Text = Defined_Acronym
                .MatchCase = False
                .Execute

            End With

            'Performs actual replacement of all but first instance of Defined_Acronym with acronym.
            Selection.HomeKey unit:=wdStory

            With Selection.Find

                '.Font.Color = wdColorAutomatic
                .Text = Defined_Acronym
                .MatchCase = False
                .Execute

            End With

            Selection.EndOf unit:=wdWord, Extend:=wdMove

            With Selection.Find

                '.Font.Color = wdColorAutomatic
                .Text = Defined_Acronym
                .MatchCase = False

                With .Replacement

                    .Highlight = False
                    .Text = Current_Acronym

                End With

                .Execute Wrap:=wdFindStop, Replace:=wdReplaceAll

            End With


            'Replace subsequent instances of definition (by itself) with acronym
            'Moves cursor to follow first instance of Defined_Acronym
            Selection.HomeKey unit:=wdStory

            With Selection.Find

                '.Font.Color = wdColorAutomatic
                .Text = Defined_Acronym
                .MatchCase = False
                .Execute

            End With

            Selection.EndOf unit:=wdWord, Extend:=wdMove

            With Selection.Find

                '.Font.Color = wdColorAutomatic
                .Text = Chosen_Definition
                .MatchCase = False


                With .Replacement

                    .ClearFormatting
                    .Text = Current_Acronym

                End With

                .Execute Replace:=wdReplaceAll, Wrap:=wdFindStop

            End With

            'Set highlight color to teal for non-NNTD acronyms, highlight all instances of Current_Acronym
            Options.DefaultHighlightColorIndex = wdTeal
            Selection.HomeKey unit:=wdStory

            With Selection.Find

                .ClearFormatting
                '.Font.Color = wdColorAutomatic
                .Text = Current_Acronym
                .MatchCase = True
                .MatchWholeWord = True

                With .Replacement

                    .Highlight = True
                    .Text = ""

                End With

                .Execute Replace:=wdReplaceAll, Wrap:=wdFindStop

            End With

        End If

    End If

    'Ends acronym definition loop
    Current_Row = Current_Row + 1

Loop

'Returns track changes to same status it was in when script began
If Track_Changes = False Then

    ActiveDocument.TrackRevisions = False

End If

'Returns view to show all track changes
With ActiveWindow.View.RevisionsFilter
    .Markup = wdRevisionsMarkupAll
    .View = wdRevisionsViewFinal
End With

Load Instructions
Instructions.Show

Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting

'Closes Excel
xlWbk.Close SaveChanges:=False
xlApp.Quit

End Sub

Function Define_Acronym()

End Function

1 个答案:

答案 0 :(得分:1)

根据您调用宏的方式,一开始可能不存在选择。请记住Selection.Find本质上意味着&#34;在当前选择&#34;指定的范围内找到[无论如何]。看到您使用Selection.Homekey Unit:=WdStory将所选内容折叠为空,我试图弄清楚为什么代码可以正常工作并失败。出于某种原因,单独使用Word似乎同意在选择为0(或1)时搜索整个文档。但零和Nothing一样。

更好的方法是指定要搜索的范围或选择。无论哪种方式,如果您希望搜索文档的整个正文,它应该是ActiveDocument.Content。虽然您的代码基于使用Selection对象,但您必须进行此类选择,例如ActiveDocument.Content.Select

@Slai我建议不要使用Selection对象。请改用Range对象。阅读差异at MSDN