【问题标题】:Why is range.find searching like this?为什么 range.find 搜索是这样的?
【发布时间】:2018-08-20 17:55:42
【问题描述】:

我正在尝试在 Word 文档中搜索特定字符串的出现。 代码应该只在目录之后搜索。 我完成的代码如下:

Private Sub cmdFindNextAbbr_Click()

    Dim myRange As range

    'CREATING DICTONARY for Selected Items
    If firstClickAbr = True Then

        txtNew = ""

        abSelIndex = 0
        Set abSel = CreateObject("scripting.dictionary")
        Set abSelFirstStart = CreateObject("scripting.dictionary")

        firstClickAbr = False
        iAbbr = 0
        For x = 0 To lstAbbreviations.ListCount - 1
            If lstAbbreviations.Selected(x) = True Then
                If Not abSel.Exists(lstAbbreviations.List(x, 1)) Then
                    abSel.Add lstAbbreviations.List(x, 0), lstAbbreviations.List(x, 1)
                    abSelFirstStart.Add lstAbbreviations.List(x, 0), lstAbbreviations.List(x, 5)
                End If
            End If
        Next x
    End If

    Dim Word, findText As String
    Dim chkAbbrLast, fsCountExt, firstOccEnd As Integer

    Do While abSelIndex < abSel.count
        chkAbbrLast = 0

        Set myRange = ActiveDocument.Content

        If txtNew <> abSel.keys()(abSelIndex) Then
            fnCountAbr = 0
            locInteger = abbrTableEnd
        End If

        firstOccEnd = abSelFirstStart.items()(abSelIndex) + Len(abSel.items()(abSelIndex) & " (" & abSel.keys()(abSelIndex) & ")")
        fnCountAbr = fnCountAbr + 1
        Word = abSel.keys()(abSelIndex)

        'initially search for full text
        findText = abSel.items()(abSelIndex)

        myRange.Start = locInteger
        myRange.Find.ClearFormatting
        Do While myRange.Find.Execute( _
                    findText:=findText, _
                    MatchCase:=False, _
                    MatchWholeWord:=True, _
                    Wrap:=wdFindStop, _
                    Forward:=True _
                    )

            If Left(myRange.Style, 7) <> "Heading" Then
                If abSelFirstStart.items()(abSelIndex) <> myRange.Start Then 'ignore the first occurrence

                    locInteger = myRange.End
                    tCount = tCount + 1

                    'check for full term and abbreviation
                    fsCountExt = Len(abSel.items()(abSelIndex) & "s (" & abSel.keys()(abSelIndex) & "s)")
                    myRange.End = myRange.Start + fsCountExt

                    If InStr(UCase(myRange.Text), UCase(abSel.items()(abSelIndex) & "s (" & abSel.keys()(abSelIndex) & "s)")) > 0 Then
                        txtNew = abSel.keys()(abSelIndex) & "s"
                        myRange.Select
                        Exit Sub
                    Else
                        fsCountExt = Len(abSel.items()(abSelIndex) & " (" & abSel.keys()(abSelIndex) & ")")
                        myRange.End = myRange.Start + fsCountExt
                    End If

                    If InStr(UCase(myRange.Text), UCase(abSel.items()(abSelIndex) & " (" & abSel.keys()(abSelIndex) & ")")) > 0 Then
                        txtNew = abSel.keys()(abSelIndex)
                        myRange.Select
                        Exit Sub
                    End If

                    'check for full term only
                    fsCountExt = Len(abSel.items()(abSelIndex) & "s (" & abSel.keys()(abSelIndex) & "s)")
                    myRange.End = myRange.Start + fsCountExt

                    If InStr(UCase(myRange.Text), UCase(abSel.items()(abSelIndex) & "s")) > 0 Then
                        txtNew = abSel.keys()(abSelIndex) & "s"
                        myRange.Select
                        Exit Sub
                    Else
                        fsCountExt = Len(abSel.items()(abSelIndex))
                        myRange.End = myRange.Start + fsCountExt
                    End If

                    If InStr(UCase(myRange.Text), UCase(abSel.items()(abSelIndex))) > 0 Then
                        txtNew = abSel.keys()(abSelIndex)
                        myRange.Select
                        Exit Sub
                    End If
                End If
            End If
                chkAbbrLast = chkAbbrLast + 1     ' check to prevent infinite loop
            myRange.End = ActiveDocument.Content.End
            If chkAbbrLast > 2 Then
                Exit Do
            End If
        Loop

        'now search for abbreviation
        findText = abSel.keys()(abSelIndex)
        chkAbbrLast = 0
        myRange.Start = locInteger
        myRange.Find.ClearFormatting
        Do While myRange.Find.Execute( _
                    findText:=findText, _
                    MatchCase:=True, _
                    MatchWholeWord:=True _
                    )

            If Left(myRange.Style, 7) <> "Heading" And myRange.Start > firstOccEnd Then

                If abbIgnoreList.contains(myRange.Start) Then ' skip if match is in ignore list
                    If abSelIndex = abSel.count - 1 Then
                        chkAbbrLast = chkAbbrLast + 1   ' check to prevent infinite loop
                    End If
                    locInteger = myRange.End
                Else
                    locInteger = myRange.End
                    tCount = tCount + 1

                    fsCountExt = Len(abSel.keys()(abSelIndex) & "s")
                    myRange.End = myRange.Start + fsCountExt

                    If InStr(UCase(myRange.Text), UCase(abSel.keys()(abSelIndex) & "s")) > 0 Then
                        txtNew = abSel.keys()(abSelIndex) & "s"
                        myRange.Select
                        Exit Sub
                    Else
                        fsCountExt = Len(abSel.keys()(abSelIndex))
                        myRange.End = myRange.Start + fsCountExt
                    End If

                    If InStr(UCase(myRange.Text), UCase(abSel.keys()(abSelIndex))) > 0 Then
                        txtNew = abSel.keys()(abSelIndex)
                        myRange.Select
                        Exit Sub
                    End If
                End If

            End If
                chkAbbrLast = chkAbbrLast + 1     ' check to prevent infinite loop
            If chkAbbrLast > 2 Then
                Exit Do
            End If
            myRange.End = ActiveDocument.Content.End

        Loop

        'loop to next/first item
        If abSelIndex <= abSel.count - 1 Then
            abSelIndex = abSelIndex + 1
        Else
            abSelIndex = 0 ' start again at beginning
        End If
    Loop

    MsgBox "No further occurrences found"
End Sub

ToCEnd 是 4085。

我能够找到第一个结果。当我单击调用相同方法的查找下一个按钮时,我有以下值:

myRange.Start : 18046
myRange.End : 21467

但是,在.Find.Execute 之后,我有以下值:

myRange.Start : 18022
myRange.End : 18046 

为什么找到的文本会在我之前定义的起点处结束? StartEnd 的区别在于我的字符串长度,24

编辑: 我已经添加了完整的代码。

我在代码中所做的是查找用户可以替换的文本。 替换是从另一个按钮触发的。

Find Next 按钮事件中,我验证了一个结果,将范围的结尾存储到一个变量并退出子。 下次单击时,我会尝试从存储的位置开始搜索。

我更新了我的代码,使其与this link 的代码相同,但我的行为仍然相同。

【问题讨论】:

  • 向我们展示与 Find 相关的整个代码 - 一个 [mvce]。我们无法对所提供的内容进行任何分析。另外,包括ToCEnd 是什么。
  • 如果你在哪里执行全部替换,那么你就不会使用 Do While。你说你按下了一个下一步按钮......如果它执行你在这里暗示的相同代码,那么根据你替换的确切内容,例程只会找到它在之前的查找/替换中部分替换的内容。如果您确实需要遍历文档,那么这与必须手动单击下一步是不一致的。 @CindyMeister 是正确的,您需要通过提供完整代码来正确完成您的问题,我会添加......对您尝试做的事情的更全面的解释。
  • 从您的第二个问题开始:请编辑 this 问题,并提供有关问题的信息,即“查找”出现在表格中时。那是一个特例。完成后请“ping”。
  • @CindyMeister 我目前已经对我的 UI 和代码进行了相当多的修改,并使用了 Selection.Find,即“查找”出现在表格中。
  • 问题是,Selection.Find 通常不是一个好主意; Range.Find 通常更可取。无论如何,不​​要依赖开始和结束数字 - 这些是可以改变的。如果您想回到某个位置,请在该位置设置一个(临时)书签。

标签: vba ms-word


【解决方案1】:

您显然想遍历找到的实例。为此,您可以使用如下代码:

Sub Demo()
Application.ScreenUpdating = False
Dim i As Long
With ActiveDocument.Range
  With .Find
    .ClearFormatting
    .Replacement.ClearFormatting
    .Text = InputBox("What is the Text to Find")
    .Replacement.Text = ""
    .Forward = True
    .Wrap = wdFindStop
    .Format = False
    .MatchCase = False
    .MatchWholeWord = False
    .MatchWildcards = False
    .MatchSoundsLike = False
    .MatchAllWordForms = False
    .Execute
  End With
  Do While .Find.Found
    i = i + 1
    'insert code to do something with whatever's been found here
    .Collapse wdCollapseEnd
    .Find.Execute
  Loop
End With
Application.ScreenUpdating = True
MsgBox i & " instances found."
End Sub

【讨论】:

  • 我想查找下一个出现的缩写或其对应的完整术语。循环遍历找到的实例对我不起作用
  • 相反,遍历找到的实例确实会返回下一个出现的缩写词或其对应的完整术语,具体取决于您要搜索的是哪一个。事实上,它会在遇到每个“下一个”实例时找到并重置范围。
猜你喜欢
  • 2011-12-14
  • 2023-03-18
  • 2013-04-11
  • 2011-09-25
  • 1970-01-01
  • 2020-10-23
  • 1970-01-01
相关资源
最近更新 更多