截断 Microsoft Word 中的合并字段以进行邮件合并
Truncating a mergefield in Microsoft Word for mailmerge
我想创建一个公式并应用于 Word 2013 中的合并字段。我无权访问数据库,只能提供合并字段。我的目标是 truncate/shorten 某些合并字段。例如。全名到首字母,年龄 [27 岁] 到短年龄 [27]。
Access 和 excel 的公式 'left' 我曾尝试使用但没有成功。数字可用的选项似乎很少。
{=left({ MERGEFIELD First_Name },1)}
然而,这给出了一个语法错误。是否有适用于 mergefield 的公式列表?
结果
'Steven' -> 'S'
'27 岁' -> '27'
对您的问题的简短回答是,Word 字段语言中没有任何东西可以可靠地 进行字符串操作,例如 left()、mid() 等。 {=} 字段只有 SUM、ABS、PRODUCT 等数值函数。有 不可靠的 方法,在某些情况下它们可能足以满足您的要求,但这实际上取决于您对数据源始终包含按您期望的格式设置的值的确定程度.
举个简单的例子,就拿“27岁”这件事来说吧。
如果相关数据源列中的每个值都采用相同的通用格式,我将其描述为"something that Word recognises as an individual number, followed by an alpha string",那么您实际上可以使用
{ 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.
如果您知道(例如)名称只能以 A-Z、a-z 开头(您显然也可以测试 0-9 等),那没关系。但是如果它可以以任何 Unicode 字母开头?不确定插入数千个 IF 字段是否可靠。
有一种类似 "unreliable" - 和 resource-consuming - 的方法来使用左、中等函数,只要你使用的是最新版本的 Windows Word (不是 Mac 字)。
你可以做的是创建一个完全空的 Access/Jet 数据库 .mdb(假设它位于 c:\i\i.mdb
,然后插入嵌套在 [=20= 中的 DATABASE
字段] 这样的字段
{ QUOTE { DATABASE \d "c:\i\i.mdb" \s "SELECT left('{ MERGEFIELD First_Name }',1)" } }
通常,DATABASE
字段插入一个 Word table(除非数据源的列数超过 Word table 可以包含的列数),但是当您只插入一个值时没有标题,Word 不会将值放在单元格中。不幸的是,现在 Word 确实添加了段落标记,但是将 DATABASE
字段嵌套在 QUOTE
字段中似乎又将其删除。
那为什么是 "unreliable"?好吧,主要原因是如果 First_Name 字段包含任何引号(肯定是 single-quotation 标记,而 OTTOMH 我认为是双引号)那么 Word 发送给 Jet 的查询将如下所示
SELECT left('a name containing a ' mark'),1)
Jet 将 return 语法错误。
DATABASE 字段方法还有其他问题,包括
- Word 将 SELECT 语句限制为 255 个字符(我认为)。如果
您提交的数据源导致 SLEECT 语句长度超过
那个,Jet 会 return 一个错误。
- 您必须将数据库放在某个地方。如果你只是使用这个
合并你自己,这可能不是问题,但如果你必须
分发Word文档等给别人使用,你也必须
确保他们拥有 .mdb 并且位于指定位置。
- Word 有时会混淆邮件合并数据源和
通过数据库字段引入的数据源。
- 即使是一个数据库字段也会对数据源中的每条记录执行查询。如果您在多个地方使用此技术,将会发出大量查询。这可能会导致问题。
就"single letter extraction"而言,还有另一种方法,与DATABASE 方法非常相似,它使用外部.XML 文件和一组INCLUDETEXT 字段来指定节点文件和 return 它的内容。但也有类似的困难。我可能会修改此答案以在某些时候描述该方法,但据我所知,它从未在 real-world 场景中使用过。
如果您需要更可靠的东西怎么办?好吧,有几种方法,但它们都存在一种或另一种缺点。我知道的主要方法是:
- 使用 Word VBA 和 OpenDataSource 方法打开数据源。
这允许您在 SQL 方言中指定查询
数据源。
- 使用在中间数据库中定义的 Query/View 来提取
您需要的数据项,并使用 那个 Query/View 作为您的数据源
- 使用 Word VBA 的 MailMerge 事件来处理每个
在 Word 处理邮件合并时记录在数据源中
- 使用一个每年的中间步骤
- (更激烈)抛弃 Word MailMerge 并寻找另一种方法
完全,例如使用 .NET 创建一个 .docx,相关数据库
提供商和 Office Open XML SDK
如果您创建此合并供其他人使用,所有这些方法中的两个 side-effects 是整个过程变得更加复杂或用户不熟悉,特别是,他们可能无法使用 Word 的工具进行数据源记录过滤等。一些人遇到的另一个问题是,如果您的数据库包含超过 255 个字符的长文本 fields/memo 字段,每当您执行比默认 "SELECT * FROM TABLE"[更复杂的操作时,它们往往会被 Jet 截断。 =30=]
(1) 要求您可以编写一个 suitable 查询以从您的数据源中获取您需要的列。因为查询是使用 OLE DB 执行的,所以您实际上不需要在数据库中创建任何永久 objects。因此,只要后端数据库允许您执行外部查询,这可能是一种可行的方法。但 Word 也对查询施加了 255 或 511 个字符的限制,因此如果您需要操作很多字段或需要的功能很复杂,您可能会很快发现超出字符限制。
(2) 与 (1) 非常相似,但可能允许您指定更复杂的查询。例如,如果您的数据源是 Jet .accdb,您 可能 能够创建自己的 .accdb 并定义一个查询,该查询访问 table 中的.accdb 不允许您修改。您可以使用 "linked tables" 来实现这一点,或者在某些情况下,您可以在 SQL.
中指定基础 tables/queries 的位置
(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。
我想创建一个公式并应用于 Word 2013 中的合并字段。我无权访问数据库,只能提供合并字段。我的目标是 truncate/shorten 某些合并字段。例如。全名到首字母,年龄 [27 岁] 到短年龄 [27]。
Access 和 excel 的公式 'left' 我曾尝试使用但没有成功。数字可用的选项似乎很少。
{=left({ MERGEFIELD First_Name },1)}
然而,这给出了一个语法错误。是否有适用于 mergefield 的公式列表?
结果
'Steven' -> 'S'
'27 岁' -> '27'
对您的问题的简短回答是,Word 字段语言中没有任何东西可以可靠地 进行字符串操作,例如 left()、mid() 等。 {=} 字段只有 SUM、ABS、PRODUCT 等数值函数。有 不可靠的 方法,在某些情况下它们可能足以满足您的要求,但这实际上取决于您对数据源始终包含按您期望的格式设置的值的确定程度.
举个简单的例子,就拿“27岁”这件事来说吧。
如果相关数据源列中的每个值都采用相同的通用格式,我将其描述为"something that Word recognises as an individual number, followed by an alpha string",那么您实际上可以使用
{ 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.
如果您知道(例如)名称只能以 A-Z、a-z 开头(您显然也可以测试 0-9 等),那没关系。但是如果它可以以任何 Unicode 字母开头?不确定插入数千个 IF 字段是否可靠。
有一种类似 "unreliable" - 和 resource-consuming - 的方法来使用左、中等函数,只要你使用的是最新版本的 Windows Word (不是 Mac 字)。
你可以做的是创建一个完全空的 Access/Jet 数据库 .mdb(假设它位于 c:\i\i.mdb
,然后插入嵌套在 [=20= 中的 DATABASE
字段] 这样的字段
{ QUOTE { DATABASE \d "c:\i\i.mdb" \s "SELECT left('{ MERGEFIELD First_Name }',1)" } }
通常,DATABASE
字段插入一个 Word table(除非数据源的列数超过 Word table 可以包含的列数),但是当您只插入一个值时没有标题,Word 不会将值放在单元格中。不幸的是,现在 Word 确实添加了段落标记,但是将 DATABASE
字段嵌套在 QUOTE
字段中似乎又将其删除。
那为什么是 "unreliable"?好吧,主要原因是如果 First_Name 字段包含任何引号(肯定是 single-quotation 标记,而 OTTOMH 我认为是双引号)那么 Word 发送给 Jet 的查询将如下所示
SELECT left('a name containing a ' mark'),1)
Jet 将 return 语法错误。
DATABASE 字段方法还有其他问题,包括
- Word 将 SELECT 语句限制为 255 个字符(我认为)。如果 您提交的数据源导致 SLEECT 语句长度超过 那个,Jet 会 return 一个错误。
- 您必须将数据库放在某个地方。如果你只是使用这个 合并你自己,这可能不是问题,但如果你必须 分发Word文档等给别人使用,你也必须 确保他们拥有 .mdb 并且位于指定位置。
- Word 有时会混淆邮件合并数据源和 通过数据库字段引入的数据源。
- 即使是一个数据库字段也会对数据源中的每条记录执行查询。如果您在多个地方使用此技术,将会发出大量查询。这可能会导致问题。
就"single letter extraction"而言,还有另一种方法,与DATABASE 方法非常相似,它使用外部.XML 文件和一组INCLUDETEXT 字段来指定节点文件和 return 它的内容。但也有类似的困难。我可能会修改此答案以在某些时候描述该方法,但据我所知,它从未在 real-world 场景中使用过。
如果您需要更可靠的东西怎么办?好吧,有几种方法,但它们都存在一种或另一种缺点。我知道的主要方法是:
- 使用 Word VBA 和 OpenDataSource 方法打开数据源。 这允许您在 SQL 方言中指定查询 数据源。
- 使用在中间数据库中定义的 Query/View 来提取 您需要的数据项,并使用 那个 Query/View 作为您的数据源
- 使用 Word VBA 的 MailMerge 事件来处理每个 在 Word 处理邮件合并时记录在数据源中
- 使用一个每年的中间步骤
- (更激烈)抛弃 Word MailMerge 并寻找另一种方法 完全,例如使用 .NET 创建一个 .docx,相关数据库 提供商和 Office Open XML SDK
如果您创建此合并供其他人使用,所有这些方法中的两个 side-effects 是整个过程变得更加复杂或用户不熟悉,特别是,他们可能无法使用 Word 的工具进行数据源记录过滤等。一些人遇到的另一个问题是,如果您的数据库包含超过 255 个字符的长文本 fields/memo 字段,每当您执行比默认 "SELECT * FROM TABLE"[更复杂的操作时,它们往往会被 Jet 截断。 =30=]
(1) 要求您可以编写一个 suitable 查询以从您的数据源中获取您需要的列。因为查询是使用 OLE DB 执行的,所以您实际上不需要在数据库中创建任何永久 objects。因此,只要后端数据库允许您执行外部查询,这可能是一种可行的方法。但 Word 也对查询施加了 255 或 511 个字符的限制,因此如果您需要操作很多字段或需要的功能很复杂,您可能会很快发现超出字符限制。
(2) 与 (1) 非常相似,但可能允许您指定更复杂的查询。例如,如果您的数据源是 Jet .accdb,您 可能 能够创建自己的 .accdb 并定义一个查询,该查询访问 table 中的.accdb 不允许您修改。您可以使用 "linked tables" 来实现这一点,或者在某些情况下,您可以在 SQL.
中指定基础 tables/queries 的位置(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。