vba - 用 VBA for Word 查找和替换会覆盖以前的样式
问题描述
我正在编写一个 VBA 脚本来从已经定义的模板生成 word 文档。在其中,我需要能够编写标题以及每个标题的正文。作为一个小例子,我有一个只包含<PLACEHOLDER>
. 对于我需要编写的每个标题和正文,我使用 VBA 中的查找<PLACEHOLDER>
和替换功能来查找并将其替换为标题名称、换行符,然后<PLACEHOLDER>
再次替换。重复此过程,直到写入每个标题名称和正文,然后将<PLACEHOLDER>
结尾替换为换行符。
文本替换工作正常,但我指定的样式会被下一次替换调用覆盖。这导致我刚刚替换的所有内容都具有我上次调用替换函数的样式。
VBA 代码(运行main
)
Option Explicit
Sub replace_stuff(search_string As String, replace_string As String, style As Integer)
With ActiveDocument.Range.Find
.Text = search_string
.Replacement.Text = replace_string
.Replacement.style = style
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchWholeWord = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Execute Replace:=wdReplaceAll
End With
End Sub
Sub main()
Dim section_names(2) As String
section_names(0) = "Introduction"
section_names(1) = "Background"
section_names(2) = "Conclusion"
Dim section_bodies(2) As String
section_bodies(0) = "This is the body text for the introduction! Fetched from some file."
section_bodies(1) = "And Background... I have no issue fetching data from the files."
section_bodies(2) = "And for the conclusion... But I want the styles to 'stick'!"
Dim i As Integer
For i = 0 To 2
' Writes each section name as wsStyleHeading2, and then the section body as wdStyleNormal
Call replace_stuff("<PLACEHOLDER>", section_names(i) & Chr(11) & "<PLACEHOLDER>", wdStyleHeading2)
Call replace_stuff("<PLACEHOLDER>", section_bodies(i) & Chr(11) & "<PLACEHOLDER>", wdStyleNormal)
Next i
Call replace_stuff("<PLACEHOLDER>", Chr(11), wdStyleNormal)
End Sub
输入文档:一个word文档,里面只有一个<PLACEHOLDER>
。
<PLACEHOLDER>
预期输出: 我希望每个标题都以我指定的样式显示,并且可以从导航窗格中查看,如下所示:
实际输出:但是我实际得到的是这样的wdStyleNormal
风格:
我认为可以通过在每个样式转换之间插入一个段落分隔符来解决问题,但是当我尝试使用vbCrLF
orChr(10) & Chr(13)
或vbNewLine
代替chr(11)
我现在使用的时,每一行都以这样的盒装问号开头:
解决方案
在另一个答案的评论中更新讨论。下面描述的问题适用于 Word 2016 及更早版本。从Office 365(可能还有 Word 2019,但尚未确认)开始,Replace
行为已更改为将 ANSI 13“转换”为“真实”段落标记,因此不会出现问题中的问题。
回答
奇怪的格式化行为的原因是使用Chr(11)
,它插入一个新行(Shift + Enter)而不是一个新段落。因此,应用于此文本任何部分的段落样式以相同的样式格式化整个文本。
在这种特殊情况下(使用Replace
),vbCr
或等效的Chr(13)
也不起作用,因为这些不是真正的 Word 原生段落。段落不仅仅是 ANSI 代码 13 - 它包含段落格式信息。因此,在代码运行时,Word 并没有真正将它们识别为真正的段落标记,并且段落样式分配被应用于“所有内容”。
起作用的是使用 string ^p
,它在 Word 的 Find/Replace 中是完整段落标记的“别名”。因此,例如:
replace_stuff "<PLACEHOLDER>", section_names(i) & "^p" & "<PLACEHOLDER>", wdStyleHeading2
replace_stuff "<PLACEHOLDER>", section_bodies(i) & "^p" & "<PLACEHOLDER>", wdStyleNormal
但是,与为每个新项目插入占位符并使用查找/替换将占位符替换为文档内容相比,有一种更有效的方法来构建文档。更传统的方法是使用一个Range
对象(把它想象成一个不可见的选择)......
将内容分配给Range
、格式化、折叠(如按右箭头进行选择)并重复。这是一个示例,它返回与问题中的(更正的)代码相同的结果:
Sub main()
Dim rng As Range
Set rng = ActiveDocument.content
Dim section_names(2) As String
section_names(0) = "Introduction"
section_names(1) = "Background"
section_names(2) = "Conclusion"
Dim section_bodies(2) As String
section_bodies(0) = "This is the body text for the introduction! Fetched from some file."
section_bodies(1) = "And Background... I have no issue fetching data from the files."
section_bodies(2) = "And for the conclusion... But I want the styles to 'stick'!"
Dim i As Integer
For i = 0 To 2
BuildParagraph section_names(i), wdStyleHeading2, rng
BuildParagraph section_bodies(i), wdStyleNormal, rng
Next i
End Sub
Sub BuildParagraph(para_text As String, para_style As Long, rng As Range)
rng.Text = para_text
rng.style = para_style
rng.InsertParagraphAfter
rng.Collapse wdCollapseEnd
End Sub
推荐阅读
- oracle - .Net Core 的 OracleCoherence 库是什么?
- python - Python Datetime 与格式字符串不匹配
- jquery - Jquery - 下一个 IP 地址
- matplotlib - 在 matplotlib 图中更改 y 轴上的数字格式
- c++ - 发件人循环冗余校验码 - 为什么我的代码不起作用?
- java - Spring Scheduler 任务运行多个时区 dateTime
- javascript - 通过 AJAX 将 JSON 对象发布到 ASP.NET Core Web API
- python - 如何发布用 Python 创建的报告
- flutter - Flutter 本地通知引发错误
- python - 有没有办法在 Windows 中引用“ipconfig”文件