对您的问题的简短回答是 Word 字段语言中没有任何内容可以可靠地进行字符串操作,例如 left()、mid() 等。{=} 字段只有 SUM、ABS、PRODUCT 等数值函数。有一些不可靠的方法,在某些情况下,它们可能对您的要求足够可靠,但这实际上取决于您对数据源将始终包含按您预期格式化的值的把握程度。
作为一个简单的例子,让我们以“27年”的事情为例。
如果相关数据源列中的每个值都采用相同的通用格式,我将其描述为“Word 将其识别为单个数字,后跟一个字母字符串”,那么您实际上可以使用
{ SET dat { MERGEFIELD age } }{ =dat }
请注意,在这种情况下,如果您要合并到新文档,{ =dat }
则字段将保留在输出中,更新这些字段将导致错误。您可以通过嵌套{ =dat }
字段或字段中的所有字段来避免这种情况QUOTE
:
{ QUOTE "{ SET dat { MERGEFIELD age } }{ =dat }" }
{ SET dat { MERGEFIELD age } }{ QUOTE { =dat } }
但是,如果您的数据源字段可能包含一个值,例如
4 years 2 months
那么这将不起作用,因为在这种情况下{ =dat }
将评估为 6,而不是 2。Word 还将评估任何看起来像{ = }
字段表达式的内容,例如,如果您的数据源包含
SUM(23,25)
然后{ =dat }
将评估为 48。还有一些我现在不会描述的奇怪之处。
从字段中提取首字母最简单的不可靠方法是使用大量 IF 字段来测试每个可能的首字母,例如
{ IF "{ MERGEFIELD First_Name }" = "A*" "A" }{ IF "{ MERGEFIELD First_Name }" = "B*" "B" } etc.
如果您不需要区分大小写,则可以使用
{ IF "{ MERGEFIELD First_Name \*Upper }" = "A*" "A" } etc.
如果您知道(例如)名称只能以 AZ、az 开头(显然您也可以测试 0-9 等),那没关系。但是如果它可以以任何 Unicode 字母开头怎么办?不确定插入数千IF 字段是一种可靠的方法。
只要您使用的是最新版本的 Windows Word(而不是 Mac Word),就有一种类似“不可靠”且耗费资源的方式来使用 left、mid 等功能。
您可以做的是创建一个完全空的 Access/Jet 数据库 .mdb (假设它位于c:\i\i.mdb
,然后插入一个DATABASE
嵌套在QUOTE
这样的字段中的字段
{ QUOTE { DATABASE \d "c:\\i\\i.mdb" \s "SELECT left('{ MERGEFIELD First_Name }',1)" } }
通常,DATABASE
字段会插入 Word 表格(除非数据源的列数超过 Word 表格可以包含的数量),但当您只插入一个没有标题的值时,Word 不会将该值放入单元格中。不幸的是,这些天 Word 确实添加了一个段落标记,但是将DATABASE
字段嵌套在一个QUOTE
字段中似乎又将其删除了。
那么为什么“不可靠”呢?好吧,主要原因是如果 First_Name 字段包含任何引号(当然是单引号,我认为是双引号),那么 Word 发送给 Jet 的查询将如下所示
SELECT left('a name containing a ' mark'),1)
并且 Jet 将返回一个语法错误。
DATABASE 字段方法还有其他问题,包括
- Word 将 SELECT 语句限制为 255 个字符(我认为)。如果您的数据源归档导致 SLEECT 语句长度超过该长度,Jet 将返回错误。
- 你必须把数据库放在某个地方。如果您只是自己使用此合并,那可能不是问题,但如果您必须分发 Word 文档等以供其他人使用,您还必须确保他们拥有 .mdb 并且它位于指定位置。
- Word 有时会混淆 Mail Merge 数据源和通过 DATABASE 字段引入的数据源。
- 甚至一个 DATABASE 字段也会对数据源中的每条记录执行查询。如果您在多个地方使用此技术,则会发出大量查询。这可能会导致问题。
就“单字母提取”而言,还有另一种方法,与 DATABASE 方法非常相似,它使用外部 .XML 文件和一组 INCLUDETEXT 字段来指定文件中的节点并返回其内容。但也有类似的困难。我可能会在某个时候修改此答案以描述该方法,但据我所知,它从未在实际场景中使用过。
那么,如果您需要更可靠的东西怎么办?好吧,有几种方法,但它们都存在一种或另一种缺点。我知道的主要方法是:
- 使用 Word VBA 和 OpenDataSource 方法打开数据源。这允许您以数据源理解的 SQL 方言指定查询。
- 使用在中间数据库中定义的查询/视图来提取您需要的数据项,并将该查询/视图用作您的数据源
- 在 Word 处理邮件合并时,使用 Word VBA 的 MailMerge 事件来处理数据源中每条记录的数据
- 使用手动中间步骤
- (更激烈)放弃 Word MailMerge 并完全找到另一种方法,例如使用 .NET、相关数据库提供程序和 Office Open XML SDK 创建一个 .docx
如果您正在创建此合并以供其他人使用,所有这些方法的两个副作用是整个过程对用户来说变得更加复杂或不熟悉,特别是他们可能无法使用 Word 的数据源设施记录过滤等。有些人遇到的另一个问题是,如果您的数据库包含超过 255 个字符的长文本字段/备注字段,那么每当您执行比默认的“SELECT * FROM TABLE”复杂得多的事情时,它们就会被 Jet 截断。
(1) 要求您可以编写合适的查询以从数据源中获取所需的列。因为查询是使用 OLE DB 执行的,所以您实际上不需要在数据库中创建任何永久对象。因此,只要后端数据库允许您执行外部查询,这可能是一种可行的方法。但是 Word 对查询也有 255 或 511 个字符的限制,所以如果你必须操作很多字段或者你需要的功能很复杂,你可能会发现你很快就超过了字符限制。
(2) 与 (1) 非常相似,但可能允许您指定更复杂的查询。例如,如果您的数据源是 Jet .accdb,则您可以创建自己的 .accdb 并定义一个查询,以访问 .accdb 中不允许修改的表。您可以使用“链接表”来实现这一点,或者在某些情况下,您可以指定 SQL 中基础表/查询的位置。
(3) 表示您使用 VBA 在处理每个数据源记录时拦截 Word。我让你去研究。您必须从 VBA 控制进程以确保调用 MailMerge 事件。有各种不可靠的报告。VBA 只能访问任何备注字段的前 255 个字符。
(4)、例如你创建一个Excel工作簿并用它来查询数据库。在这种情况下,您可以发出比在 Word 中更长的 SQL 查询,并且您可以创建新的 Excel 列来使用 Excel 公式处理数据。(不过,我从未尝试过)。然后将其用作您的数据源。
最后,网络搜索应显示 Word 的“=”字段识别的函数列表,但最近的 Microsoft 文档倾向于省略 IF() 函数。.docx 标准上的 ISO29500 文档也省略了它,但我认为这不是本意,可能会在标准的未来版本中得到修复。功能是:
ABS, AND, AVERAGE, COUNT, DEFINED, FALSE, IF, INT, MIN, MAX, MOD, NOT, OR, PRODUCT, ROUND, SUM, TRUE。