我一直在为此喋喋不休,似乎无法想出一个解决方案.我必须通过通配符搜索自定义标记从头到尾搜索文档.为了这个问题,我们会说{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更改的操作