无法获取递归范围。在 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

第一个问题是,我不知道如何保持。发现在正确的范围内执行。这就是文档和输出的样子(后面有空格{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的Find行为非常奇怪。

在其他特性中,如果您的搜索文本与Range的文本完全匹配,则会忽略"换行"选项,并根据本文重新定义搜索范围:

当查找对象。执行方法确定要查找的东西与搜索范围完全匹配,搜索范围被动态重新定义。新的搜索范围从旧搜索范围的末尾开始,到文档(或目标故事范围)的末尾结束。在重新定义的范围内继续处理。

这就是{fizzbuzz}(带尾部空格)工作的原因-它不是完全匹配。

你需要调整你的代码来处理:

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

您可以通过在每次Execute调用前后以及每次Text分配前后添加Range.Select语句来查看Range在操作中的更改

最新更新