简体   繁体   English

截断Microsoft Word中的合并域以进行邮件合并

[英]Truncating a mergefield in Microsoft Word for mailmerge

I'm looking to create a formula and apply to a mergefield in Word 2013. I have no access to the db and only given merge fields. 我正在寻找创建一个公式并将其应用于Word 2013中的mergefield。我无权访问db,而只能使用给定的merge字段。 My goal is truncate/shorten certain mergefields. 我的目标是截断/缩短某些合并域。 Eg Full Name to just initial, Age [27 years] to short age [27]. 例如,全名只是最初的名字,年龄[27岁]至短年龄[27]。

Access and excel have the formula 'left' which i've tried to use with no success. Access和excel具有我尝试使用但未成功使用的公式“ left”。 There seems to be a low more options available for numbers. 似乎数字可用的选项较少。

{=left({ MERGEFIELD First_Name },1)}

However this gives a syntax error. 但是,这会产生语法错误。 Is there a list of formulas that work for mergefield? 是否有适用于mergefield的公式列表?

Outcome 结果

'Steven' -> 'S' '史蒂文'->'S'

'27 Years' -> '27' '27年'->'27'

The short answer to your question is that there is nothing in the Word field language that can reliably do string manipulation such as left(), mid() and so on. 这个问题的简短答案是,Word字段语言中没有任何东西可以可靠地进行字符串操作,例如left(),mid()等。 The {=} field only has numeric functions such as SUM, ABS, PRODUCT and so on. {=}字段仅具有数字功能,例如SUM,ABS,PRODUCT等。 There are unreliable approaches, and in some cases they may be reliable enough for your requirement, but that really depends on how sure you can be that the data source will always contain values formatted as you expect. 存在不可靠的方法,在某些情况下它们可能足以满足您的要求,但这实际上取决于您如何确定数据源将始终包含期望格式的值。

As a simple example, let's take the "27 years" thing. 举一个简单的例子,让我们来谈谈“ 27年”。

If every value in the relevant data source column is in the same general format, which I will describe as "something that Word recognises as an individual number, followed by an alpha string", then you can in fact use 如果相关数据源列中的每个值都具有相同的常规格式(我将其描述为“ Word识别为单个数字,后跟一个字母字符串)”,那么实际上您可以使用

{ SET dat { MERGEFIELD age } }{ =dat }

Notice that in that case, if you are merging to a new document, { =dat } fields will remain in the output, and updating those fields will cause errors. 请注意,在这种情况下,如果要合并到新文档,则{ =dat }字段将保留在输出中,而更新这些字段将导致错误。 You can avoid that by nesting either the { =dat } field or the all the fields in a QUOTE field: 您可以通过嵌套{ =dat }字段或QUOTE字段中的所有字段来避免这种情况:

{ QUOTE "{ SET dat { MERGEFIELD age } }{ =dat }" }

{ SET dat { MERGEFIELD age } }{ QUOTE { =dat } }

However , if your data source field could contain a value such as 但是 ,如果您的数据源字段可能包含一个值,例如

4 years 2 months

then this will not work because in that case { =dat } will evaluate to 6, not 2. Word will also evaluate anything that looks like an { = } field expression, eg if your data source contains 那么这将不起作用,因为在这种情况下, { =dat }计算结果为6,而不是2。Word还将计算任何看起来像{ = }字段表达式的内容,例如,如果您的数据源包含

SUM(23,25)

then { =dat } will evaluate to 48. There are further oddities that I will not describe now. 那么{ =dat }将为48。我现在不再赘述。

The simplest unreliable approach to extracting the first letter from a field is to use a large number of IF fields to test for every possible initial letter, eg 从字段中提取第一个字母的最简单, 不可靠的方法是使用大量的IF字段来测试每个可能的首字母,例如

{ IF "{ MERGEFIELD First_Name }" = "A*" "A" }{ IF "{ MERGEFIELD First_Name }" = "B*" "B" } etc.

If you don't need to distinguish between lower and upper case you can use 如果您不需要区分大小写,可以使用

{ IF "{ MERGEFIELD First_Name \*Upper }" = "A*" "A" } etc.

That's OK if you know (for example) that the names can only start with AZ,az (and you could obviously test for 0-9 etc. as well. But what if it could start with any Unicode letter? Not sure that inserting thousands of IF fields is a reliable approach. 如果您知道(例如)名称只能以AZ,az开头(并且显然也可以测试0-9等),那没关系,但是如果它可以以任何Unicode字母开头怎么办?不确定是否插入数千IF字段是一种可靠的方法。

There is a similarly "unreliable" - and resource-consuming - way to use functions such as left, mid etc., as long as you are using recent versions of Windows Word (not Mac Word). 只要您使用的是Windows Word的最新版本(非Mac Word),就有类似的“不可靠”且消耗资源的方式来使用诸如left,mid等功能。

What you can do is create a completely empty Access/Jet database .mdb (let's say it is at c:\\i\\i.mdb , then insert a DATABASE field nested in a QUOTE field like this 您可以做的是创建一个完全空的Access / Jet数据库.mdb(假设它位于c:\\i\\i.mdb ,然后在嵌套在QUOTE字段中的DATABASE字段中插入这样的内容

{ QUOTE { DATABASE \d "c:\\i\\i.mdb" \s "SELECT left('{ MERGEFIELD First_Name }',1)" } }

Normally, a DATABASE field inserts a Word table (unless the data source has more columns than a Word table can contain), but when you only insert a single value with no headings, Word does not put the value in a cell. 通常, DATABASE字段会插入Word表(除非数据源的列数超出Word表可以包含的列数),但是当您仅插入不带标题的单个值时,Word不会将该值放在单元格中。 Unfortunately, these days Word does add a paragraph mark, but nesting the DATABASE field inside a QUOTE field appears to remove that again. 不幸的是,这些天来Word确实添加了一个段落标记,但是将DATABASE字段嵌套在QUOTE字段中似乎又将其删除了。

So why is that "unreliable"? 那么为什么那是“不可靠的”呢? Well, the main reason is if the First_Name field contains any quotation marks (certainly single-quotation marks, and OTTOMH I think double quotation marks) then the query that Word sends to Jet will look like this like this 好吧,主要原因是,如果First_Name字段包含任何引号(肯定是单引号和OTTOMH,我认为是双引号),那么Word发送给Jet的查询将像这样

SELECT left('a name containing a ' mark'),1)

and Jet will return a syntax error. 并且Jet将返回语法错误。

There are other problems with the DATABASE field approach, including DATABASE字段方法还有其他问题,包括

  • Word restricts the SELECT statement to 255 characters (I think). Word将SELECT语句限制为255个字符(我认为)。 If your data source filed causes the SLEECT statement length to exceed that, Jet will return an error. 如果您的数据源字段导致SLEECT语句长度超过该长度,Jet将返回错误。
  • You have to put the database somewhere. 您必须将数据库放在某个地方。 If you are just using this merge yourself, that may not be a problem, but if you have to distribute the Word document etc. for others to use, you also have to ensure they have the .mdb and that it's at the specified location. 如果您只是自己使用此合并,那可能不是问题,但是如果您必须分发Word文档等供其他人使用,则还必须确保它们具有.mdb并且位于指定位置。
  • Word sometimes gets confused between a Mail Merge data source and a data source introduced via a DATABASE field. Word有时会在邮件合并数据源和通过DATABASE字段引入的数据源之间造成混淆。
  • Even one DATABASE field will execute a query for every record in the data source. 甚至一个DATABASE字段也将对数据源中的每个记录执行查询。 If you use this technique in several places, a very large number of queries will be issued. 如果您在多个地方使用此技术,将发出大量查询。 That could cause problems. 那可能会引起问题。

As far as "single letter extraction" is concerned, there is another approach, rather similar to the DATABASE one, that uses an external .XML file and a set of INCLUDETEXT fields to specify a node in the file and return its content. 至于“单字母提取”,还有另一种方法,与DATABASE相似,它使用外部.XML文件和一组INCLUDETEXT字段来指定文件中的节点并返回其内容。 But there are also similar difficulties. 但是也有类似的困难。 I may modify this Answer to describe that approach at some point, but as far as I know it has never been used in a real-world scenario. 我可能会在某个时候修改此答案以描述该方法,但据我所知,它从未在实际场景中使用过。

So what if you need something more reliable? 那么,如果您需要更可靠的产品怎么办? Well, there are several approaches, but all of them suffer from shortcomings of one kind or another. 嗯,有几种方法,但是所有方法都存在一种或另一种缺点。 The main approaches I know are: 我知道的主要方法是:

  1. use Word VBA and the OpenDataSource method to open the data source. 使用Word VBA和OpenDataSource方法打开数据源。 That allows you to specify a query in the SQL dialect understood by the data source. 这样,您就可以使用数据源可以理解的SQL方言来指定查询。
  2. use a Query/View defined in an intermediate database to extract the data items you need, and use that Query/View as your data source 使用在中间数据库中定义的查询/视图提取所需的数据项,并将查询/视图用作数据源
  3. Use Word VBA's MailMerge Events to manipulate the data for each record in the data source as Word processes the mailmerge 当Word处理邮件合并时,使用Word VBA的MailMerge事件来处理数据源中每个记录的数据
  4. use a manual intermediate step 使用手动中间步骤
  5. (more drastic) ditch Word MailMerge and find another approach altogether, eg create a .docx using .NET, the relevant database provider, and the Office Open XML SDK (更加激烈)放弃Word MailMerge并找到另一种方法,例如,使用.NET,相关的数据库提供程序和Office Open XML SDK创建.docx

If you are creating this merge for use by other people, two side-effects of all those approaches is that the overall process becomes more complicated or unfamiliar for the user, and in particular, they may not be able to use Word's facilities for data source record filtering and so on. 如果创建此合并供其他人使用,则所有这些方法的两个副作用是,整个过程对于用户而言变得更加复杂或不熟悉,尤其是,他们可能无法使用Word的功能来获取数据源记录过滤等。 Another issue that some people encounter is that if your database contains long text fields/memo fields longer than 255 characters, they have a tendency to be truncated by Jet whenever you do something much more complicated than the default "SELECT * FROM TABLE" 某些人遇到的另一个问题是,如果您的数据库包含长于255个字符的长文本字段/备注字段,则当您执行比默认的“ SELECT * FROM TABLE”复杂得多的操作时,它们有被Jet截断的趋势。

(1) requires that you can write a suitable query to get the columns you need from your data source. (1)要求您可以编写一个合适的查询来从数据源中获取所需的列。 Because the query is executed using OLE DB you don't actually need to create any permanent objects in your database. 因为查询是使用OLE DB执行的,所以您实际上不需要在数据库中创建任何永久对象。 So it may be a viable approach as long as the backend database allows you to execute external queries. 因此,只要后端数据库允许您执行外部查询,这可能是一种可行的方法。 But Word also imposes a 255 or 511 character limit on the query, so if you have to manipulate a lot of fields or the functions you need are complicated, you may find that you exceed the character limit quite quickly. 但是Word还对查询强加了255个或511个字符的限制,因此,如果您必须操纵很多字段或所需的功能很复杂,则可能会很快超过字符限制。

(2) is rather similar to (1) but may allow you to specify a much more complex query. (2)与(1)相当相似,但可以允许您指定更为复杂的查询。 For example, if your data source is a Jet .accdb, you may be able to create your own .accdb and define a query in that that accesses the tables in the .accdb that you are not allowed to modify. 例如,如果您的数据源是Jet .accdb,则您可以创建自己的.accdb并定义一个查询,该查询访问不允许修改的.accdb中的表。 You might either used "linked tables" to achieve that, or in certain cases you can specify the locations of the underlying tables/queries in the SQL. 您可能使用“链接表”来实现该目的,或者在某些情况下,您可以在SQL中指定基础表/查询的位置。

(3) means that you use VBA to intercept Word as it processes each data source record. (3)表示您在处理每个数据源记录时使用VBA拦截Word。 I leave you to research that. 我留给你研究。 You have to control the process from VBA to ensure that the MailMerge events are invoked. 您必须从VBA控制该过程,以确保调用MailMerge事件。 There have been reports of various unreliabilities. 已有各种不可靠性的报道。 VBA can only access the first 255 characters of any memo fields. VBA只能访问任何备注字段的前255个字符。

(4), eg you create an Excel workbook and use it to query the database. (4),例如,创建一个Excel工作簿并使用它来查询数据库。 In that case you may be able to issue a much longer SQL query than you can in Word, and you may be able to create new Excel columns that manipulate the data using excel formulas. 在这种情况下,您可以发出比在Word中更长的SQL查询, 并且可以创建新的Excel列以使用excel公式来操纵数据。 (I have never tried that, though). (不过,我从未尝试过)。 Then use that as your data source. 然后将其用作您的数据源。

Finally, a web search should reveal a list of functions recognised by Word's "=" field, but recent Microsoft documentation tends to omit the IF() function. 最后,网络搜索应显示Word的“ =”字段可识别的功能列表,但最近的Microsoft文档倾向于忽略IF()函数。 The ISO29500 documents on the .docx standard omit it as well, but I think that was not the intention and may be fixed in a future version of the standard. .docx标准上的ISO29500文档也将其省略,但是我认为这不是故意的,可能会在该标准的将来版本中进行修复。 The functions are: 这些功能是:

ABS, AND, AVERAGE, COUNT, DEFINED, FALSE, IF, INT, MIN, MAX, MOD, NOT, OR, PRODUCT, ROUND, SUM, TRUE. ABS,与,平均,计数,定义,伪,IF,INT,MIN,MIN,MOD,NOT或OR,乘积,ROUND,SUM,TRUE。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM