【问题标题】:Automating Mail Merge自动化邮件合并
【发布时间】:2015-11-06 17:55:13
【问题描述】:

我需要使用 Access 数据库表中的文本动态生成 W​​ord 文档。这里需要注意的是,来自数据库的一些文本需要修改为 MergeFields。我目前正在使用 Interop.Word(VBA 宏)和 VB.NET 来生成文档。

到目前为止,我的步骤如下所示:

  1. 拉取标准 .docx 模板
  2. 使用表格中预定义的填充文本填充模板
  3. 通过将填充文本替换为实际的合并字段来添加合并字段
  4. 附加数据源并执行邮件合并

经过测试,我注意到我不能简单地将 MergeFields 作为字符串存储到 access 数据库中,它们不会馈送到实际文档中。然后我在想的是创建一个已知字符串的表,应该通过编码替换为 MergeFields。

例如:

第 2 步将插入“在@INACTIVE_DATE@ 之后,您的帐户将不再有效。”这将在数​​据库文本中。

第 3 步将使用 MergeField «INACTIVE_DATE» 查找/替换 @INACTIVE_DATE@。我正在使用 Word Interop 来执行此操作,因此理论上我可以循环浏览文档。

我无法从文本到 MergeField 执行“查找和替换”,那么我应该如何实现呢?

另外标记 VBA,因为我正在寻找“VBA”风格的答案(Word Interop)。

【问题讨论】:

    标签: vb.net vba ms-word office-interop


    【解决方案1】:

    你遗漏了很多细节,所以我将用一些笼统的术语来回答这个问题。

    你想做的事情肯定是可以实现的。立即想到两种可能的解决方案:

    1. 使用Find 替换范围
    2. 使用TypeText 插入令牌

    使用Find 替换范围

    假设文本已被插入,您可以在文档中搜索给定的模式并将其替换为合并字段。例如:

    Sub FindInsertMerge()
        Dim rng As Range
        Set rng = ActiveDocument.Range
    
        With rng.Find
            .Text = "(\@*\@)"
            .MatchWildcards = True
            .Execute
    
            If .Found Then
                ActiveDocument.MailMerge.Fields.Add rng, Mid(rng.Text, 2, Len(rng.Text) - 2)
            End If
        End With
    End Sub
    

    将查找第一个以@ 开头的文本,匹配任何字符串并以@ 结尾。然后,找到的范围的内容将被合并字段替换。上面的代码可以很容易地扩展到循环所有字段。

    使用TypeText 插入令牌

    虽然我通常建议不要使用 Selection 插入数据,但这个解决方案让事情变得简单。假设您有一个目标范围rng,您对要插入的数据库文本进行标记,选择范围,开始输入,每当找到指定的邮件合并字段时,插入一个字段而不是文本。

    例如:

    Private Sub InsertMergeText(rng As Range, txt As String)
        Dim i As Integer
        Dim t As String
        Dim tokens() As String
    
        tokens = Split(txt, " ")
        rng.Select
    
        For i = 0 To UBound(tokens)
            t = tokens(i)
    
            If Left(t, 1) = "@" And Right(t, 1) = "@" Then
                'Insert field if it's a mail merge label.
                ActiveDocument.MailMerge.Fields.Add Selection.Range, Mid(t, 2, Len(t) - 2)
            Else
                'Simply insert text.
                Selection.TypeText t
            End If
    
            'Insert the whitespace we replaced earlier.
            If i < UBound(tokens) Then Selection.TypeText " "
        Next
    End Sub
    

    调用示例:

    InsertMergeText Selection.Range, "After @INACTIVE_DATE@ your account will no longer be active which will be in the database text."
    

    【讨论】:

    • 很抱歉缺少细节,但您完美地回答了这个问题。在我目前的状态下,我正在考虑使用 TypeText 插入整个字符串,然后传递单词并进行替换。如您所显示的那样更换它似乎是一个更好的选择。为什么不建议使用 Selection 插入数据?
    • 我发现在某些情况下更改Selection 是不可靠的,而且我通常不喜欢弄乱用户的会话。对于数据插入,书签或内容控件是最佳选择,但这会使代码更加复杂。不过,我不认为在这种情况下使用 Selection 有什么问题。
    • 好的,我明白了。我正在使用书签来标记内容的去向。这对用户应该是透明的。感谢您的帮助,我会确保进行大量测试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-05
    • 2015-04-19
    • 1970-01-01
    • 2019-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多