为什么.Font.Reset在查找/替换VBA宏中不起作用?

时间:2018-08-16 19:11:16

标签: vba replace ms-word word-vba

我的文档中有一个特定的单词,该单词具有以前作者的各种内联格式。我想找到该单词并删除其内联格式。如果使用键盘,则一次选择一项,对每项应用CTRL +空格键。相反,我写了一个宏。 总体上,我不想假设内联格式的本质;我不想担心它是粗体还是斜体。我只想执行一个通用的CTRL + Spacebar,将其转换为VBA中的.Font.Reset。但是,这不起作用。这是我的代码,可以工作,但是请参阅我添加的注释,这些注释共同询问为什么.Font.Reset不起作用:

Sub Inline_Formatting_Replacement()
Dim MyDocRange As Range
Set MyDocRange = ActiveDocument.Range

With MyDocRange.Find
    .ClearFormatting
    .Text = "word_with_inline_formatting"
    With .Replacement
        .ClearFormatting
        .Text = "word_with_inline_formatting"
        .Font.Bold = False 'I shouldn't have to use this.
        .Font.Italic = False 'I shouldn't have to use this.
        .Font.Reset 'This should work instead of using .Bold and .Italic, _
                     'but this line does nothing. Why?
    End With
    .Forward = True
    .Wrap = wdFindStop
    .Execute Replace:=wdReplaceAll
End With
End Sub

2 个答案:

答案 0 :(得分:3)

As Cindy Meister pointed outFont.Reset方法,而不是属性

您正在配置Range.Find.Replacement.Font,告诉对象模型您要替换的对象以及应该如何格式化。当您调用读/写 properties 时,此方法有效,因为读/写属性存储了 state 。在该状态上的方法 act

当您了解属性的工作原理时,这更有意义-这是一个示例:

Option Explicit
Private internalState As Boolean

Public Property Get State() As Boolean
'invoked when .State is on the right-hand side of an expression, e.g. foo = obj.State
    State = internalState
End Property

Public Property Let State(ByVal value As Boolean)
'invoked when .State is on the left-hand side of an expression, e.g. obj.State = foo
'the "value" parameter is the result of the right-hand side expression.
    internalState = value
End Property

想象一下,internalState包含有关字体是否应该粗体的信息:Font返回的对象的Replacement属性是{ {1}}对象,即Font类的 instance 。因此,当您执行Font时,您就是在那个.Bold = False对象的内部状态内将该值封装

现在说您在这个虚构的类模块中还有一个方法

Font

现在我不知道Public Sub Reset() internalState = False End Sub 真的的作用-人们将不得不窥视该源代码……或查看文档中是否有任何有用的东西:

  

删除手动字符格式(不使用样式应用的格式)。例如,如果您手动将单词的格式设置为粗体,并且基础样式为纯文本(而非粗体),则 Reset 方法将删除粗体格式。
   https://msdn.microsoft.com/en-us/vba/word-vba/articles/font-reset-method-word

那么为什么不重置 Reset对象的Font?实际上,这是一个很好的问题:人们可以合理预期在Replacement上调用Reset可以有效地“重置”该字体。

我对对象模型不是很熟悉(尽管Cindy是专家!),但是为了让Replacement.Font可以替代,我相信{{1} }类需要执行以下操作:

.Reset

然后在实际执行替换时,Word可以检查Font并在受影响的Option Explicit Private doReset As Boolean Public Property Get ShouldReset() As Boolean ShouldReset = doReset End Property Public Sub Reset() 'does whatever it does '... doReset = True End Sub ShouldReset实例上调用方法-是一个与Font对象上的Range实例不同的实例。

Font进行上述操作没有任何意义,因为当然,如果您调用Replacement,则应该重置-所缺少的是像Font类之类的东西可以合理地保存该状态/信息...而它不存在。

如果VBA具有一等公民的功能,那么您也许可以执行以下类似的杂乱无味的伪代码:

Reset

然后,当您使用ReplacementFont时,假设的Set .ReplacementAction = New Function(ByVal r As Range) r.ClearFormatting r.Text = "word_with_inline_formatting" r.Font.Reset End Function 函数会将实际的Find.Execute作为参数传递给此... 委派的动作 ,并且ReplacementAction在目标Range 被调用时将针对目标.Reset进行操作,而不是在Range.Font 设置时对其进行操作

A,VBA无法做Replacement.Font的事情……or can it?

答案 1 :(得分:0)

我敢肯定,调用Find.Replacement.Font.Reset只会清除所有替换字体信息,因此当您进行替换时,字体不会更改。

我正在遇到类似的效果,我想使用查找/替换从全局文本中删除字符样式,但我没有找到任何方法来实现。

Replacement.Font.Style等似乎无法将它们设置为“清除任何特定的字体/样式/等”。唯一的选择是什么都不做或设置特定的值。

作为我的结果,我将不得不编写一个循环,该循环单独查找每个搜索命中,并在结果范围内等效于ctrl-space。不幸的是,这将比全局替换慢得多。