无法获得递归Range.Find在Word VBA中工作

我一直在为此喋喋不休,似乎无法想出一个解决方案.我必须通过通配符搜索自定义标记从头到尾搜索文档.为了这个问题,我们会说{something}当我找到一个特定的匹配时,它会被另一个字符串的内容替换,该字符串也可能包含标记.标记必须按照它在最终文档中出现的顺序进行替换.我必须知道每次替换所做的递归级别.

这基本上就是我提出的.请注意,ProcessReplacement函数是为示例设计的 – 文本被外部程序替换:

 

Option Explicit
Private replaced As Integer
Public Sub Demo()
    Dim pos As Range
    Set pos = ActiveDocument.Content
    replaced = 0
    pos.Text = "{fizz}{fizz}{more}{buzz}{buzz}"
    Expand pos
End Sub
Private Sub Expand(incoming As Range, Optional depth = 1)
    Dim sub_range As Range
    Dim end_pos As Long
    end_pos = incoming.End
    With incoming.Find
        .ClearFormatting
        .MatchWildcards = True
        .Forward = True
        .Wrap = wdFindStop
    End With
    Do While incoming.Find.Execute("\{*\}")
        If incoming.Start < incoming.End Then
            Debug.Print "Replaced " & incoming.Text & " at " & depth
            end_pos = end_pos + ProcessReplacement(incoming)
            Set sub_range = incoming.Duplicate
            Expand sub_range, depth + 1
            incoming.End = end_pos
            incoming.Start = sub_range.End - 1
        End If
    Loop
End Sub
Private Function ProcessReplacement(replacing As Range) As Long
    Dim len_cache As Long
    len_cache = Len(replacing.Text)
    If replacing.Text = "{more}" Then
        replacing.Text = "{foo}{evenmore}{bar}"
    ElseIf replacing.Text = "{evenmore}" Then
        'This kind of works.
        replacing.Text = "{fizzbuzz} "
        'This doesn't work at all.
'        replacing.Text = "{fizzbuzz}"
    Else
        replaced = replaced + 1
        replacing.Text = "<" & replaced & ">"
    End If
    ProcessReplacement = Len(replacing.Text) - len_cache
End Function

第一个问题是我无法想象如何将.Find.Execute限制在正确的范围内.这就是文档和输出的样子({fizzbuzz}之后的空格 – 后面会有更多内容):

 

Document text: <1><2><3><4> <5><6><7>
Output:
Replaced {fizz} at 1
Replaced {fizz} at 1
Replaced {more} at 1
Replaced {foo} at 2
Replaced {evenmore} at 2
Replaced {fizzbuzz} at 3
Replaced {bar} at 2
Replaced {buzz} at 2    <---This was outside of the range at that depth.
Replaced {buzz} at 1

如果我在{fizzbuzz}之后取出空间,它甚至不会匹配,即使我在监视窗口中确认它基本上是该函数在替换后递归时的范围内容.没有空格的输出:

 

Document text: <1><2><3>{fizzbuzz}<4><5><6>
Output:
Replaced {fizz} at 1
Replaced {fizz} at 1
Replaced {more} at 1
Replaced {foo} at 2
Replaced {evenmore} at 2
Replaced {bar} at 3  <---No clue how this happens - wdFindStop is ignored.
Replaced {buzz} at 3
Replaced {buzz} at 3

预期输出(有或没有空格):

 

Document text: <1><2><3><4><5><6><7>
Output:
Replaced {fizz} at 1
Replaced {fizz} at 1
Replaced {more} at 1
Replaced {foo} at 2
Replaced {evenmore} at 2
Replaced {fizzbuzz} at 3
Replaced {bar} at 2
Replaced {buzz} at 1
Replaced {buzz} at 1

有人看到我遗失的任何东西吗?

最佳答案 Word的查找行为非常奇怪.

除了其他特性之外,如果您的搜索文本与Range的文本完全匹配,则忽略Wrap选项,并根据此article重新定义搜索范围:

 

When the Find object .Execute method determines that the thing to find exactly matches the search range, the search range is dynamically redefined. The new search range starts at the end of the old search range and ends at the end of the document (or targeted storyRange). Processing continues in the redefined range.

这就是{fizzbuzz}(带尾随空格)的原因 – 它不是完全匹配的原因.

您需要调整代码来处理:

> Range.Text是通配符搜索的完全匹配,和/或:
>调用Execute后,检查Range的开始是否在预期结束之前.

通过在每个Execute调用之前和之后以及每个Text分配之前和之后添加Range.Select语句,可以看到Range更改的操作

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章