【问题标题】:Running a MS Word mail merge from excel从 excel 运行 MS Word 邮件合并
【发布时间】:2020-01-06 19:46:11
【问题描述】:

我知道之前有人问过这个问题,我尝试更新另一个线程但不被允许。

我有一个电子表格,其中包含用于 MS 邮件合并的数据。我有一个全部设置为运行的 Word 邮件合并文档。字段已经设置好了。当我打开 word doc 时,我收到一个提示,上面写着“打开此文档将运行以下 SQL 命令”等等。我想要做的是让 Excel 电子表格在我单击时在没有任何用户干预的情况下运行邮件合并按钮。我从这个论坛上的示例中汇总了以下代码,但无法正常工作。当运行 Word 打开时,我得到相同的提示。我如何让它发挥作用?

Public Sub RunMailMerge(MMFileName As String)

    Dim wdDoc As Object

'   open the mail merge layout file

    Set wdDoc = GetObject(MMFileName, "Word.document")
    wdDoc.Application.Visible = True

    With wdDoc.MailMerge
         .MainDocumentType = wdFormLetters
         .Destination = wdSendToPrinter
         .SuppressBlankLines = True
         .Execute Pause:=False
    End With

'   cleanup

    wdDoc.Close SaveChanges:=False
    Set wdDoc = Nothing

End Sub

我看到的所有示例都使用后期绑定。使用词对象的早期绑定不是更好吗?

谢谢 唐

【问题讨论】:

  • 视情况而定 - 如果您不确定用户拥有什么版本,或者您需要它与每个版本一起使用,后期绑定非常有用。
  • 后期绑定不能使用字常量。在对象浏览器中查找值并使用该值。或者在引用对话框中提前绑定到 Word。
  • 关于版本的好点。常量这个词正在起作用。更大的问题是如何让 MM 工作?它会启动,但随后会弹出一个对话框等待答案。我根本不想要用户交互。用户单击一个按钮并打印邮件合并文档。

标签: excel vba


【解决方案1】:

这个概念怎么样?

Sub PushToWord()

Dim objWord As New Word.Application
Dim doc As Word.Document
Dim bkmk As Word.Bookmark
sWdFileName = Application.GetOpenFilename(, , , , False)
Set doc = objWord.Documents.Open(sWdFileName)

objWord.activedocument.variables("FirstName").Value = Range("FirstName").Value
objWord.activedocument.variables("LastName").Value = Range("LastName").Value

ActiveDocument.Fields.Update

objWord.Visible = True

End Sub

将 DocVariables 添加到您的 Word 文档中,并适当地命名它们。从 Excel 运行代码。

【讨论】:

    【解决方案2】:

    https://support.microsoft.com/en-au/help/825765/you-receive-the-opening-this-will-run-the-following-sql-command-messag

    “症状”部分中描述的提示是设计使然。

    此提示存在于所有更高版本的 Microsoft Office 中,并且是 在 Office XP Service Pack 3 中引入。此提示已添加到 “适用于”部分中列出的产品以使邮件合并更多 安全的。如果在收到提示时单击“是”,则让代码运行 在你的电脑。恶意用户可能能够制作 SQL 查询 旨在窃取或破坏您有权访问的数据。 如果您在收到提示时单击“否”,则不要让代码 运行。

    注意通过 VBA 设置 DisplayAlerts=none 时会抑制提示 该文件是使用 VBA 打开的,但使用 NO 选项打开 文档并且没有数据附加到邮件合并主文档

    【讨论】:

    • 感谢您的解释。
    【解决方案3】:

    有两种基本方法可用于在不触发提示的情况下运行邮件合并。请注意,提示是一种安全措施,因为邮件合并运行的 SQL可能对系统造成损害。提示确保用户知道这一点,并且(假设)仅在文档来自“受信任的来源”时才运行邮件合并。

    1. 从主合并文档中删除数据源,然后在每次打开文档时使用 VBA 显式添加它

    这种方法的优点是它支持 Word 的安全设置。如果用户允许 VBA 运行,则认为整个项目都是可信的,因此允许使用代码附加数据源。

    可以通过选择在不允许邮件合并的情况下打开文档的选项从文档中删除数据源(我正在查看的 Word 版本中标记为“否”的按钮)。以该状态保存文档。在执行邮件合并之前,在您的代码中添加一行链接数据源。

    为了找出必要的语法,您可以在连接到数据源时录制宏(这是最确定和最快的),也可以在断开连接之前从文档中查询数据源。在 Word 中,在 VBA 编辑器的即时窗口 (Ctrl+G) 中输入 ? 行并逐个按 Enter:

    ?ActiveDocument.MailMerge.DataSource.Name
    C:\Users\Cindy Meister\Documents\Personal\klpFeb00.mdb
    ?Document.MailMerge.DataSource.QueryString
    SELECT * FROM `Q_MailMergeInvite`
    

    然后

    ?ActiveDocument.MailMerge.DataSource.ConnectString
    

    按 Enter 后,您应该会看到类似于

    的内容
    Provider=Microsoft.ACE.OLEDB.12.0;User ID=Admin;Data Source=C:\Users\[username]\Documents\Personal\Text.mdb;Mode=Read;Extended Properties="";Jet OLEDB:System database="";Jet OLEDB:Registry Path="";Jet OLEDB:Engine Type=5;Jet OLEDB:Database Locking Mode=0;Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password="";Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;Jet OLEDB:Don't Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;Jet OLEDB:SFP=False;Jet OLEDB:Support Complex Data=False;Jet OLEDB:Bypass UserInfo Validation=False
    

    这些用双引号括起来,分配给Document.MailMerge.OpenDataSourceNameSQLStatementConnection 参数。

    1. 更改注册表设置以禁用提示

    这在Knowledge Base article about the prompt 中有描述。

    确切的注册表项会有所不同,具体取决于 Word 的版本,但遵循模式

    HKEY_CURRENT_USER\Software\Microsoft\Office\15.0\Word\Options 
    

    以上适用于 Word 2013 版本 15。对于 Word 2010,将其更改为 14; 16 for Word 2016 等。

    需要在此位置创建DWord 类型的新注册表项,命名为SQLSecurityCheck。为其分配值00000000

    【讨论】:

    • 感谢 Cindy 的详细解释。
    • @Don 由于您对该网站比较陌生:“感谢”人们的贡献不是您问题的答案的公认方式是通过单击旁边的向上箭头进行投票的贡献。 Upvoting 是让人们知道这(在您看来)是对网站的有用/有益的贡献。问题和答案都是可能的。您应该能够在任何地方执行此操作(尽管在启用之前您可能需要更多的声誉)。稍后,您还可以对您认为质量差的内容投反对票。
    【解决方案4】:

    例如:

    Sub MergetoPrint()
    Dim wrdObj As Object, wrdDoc As Object, strFile As String
    strFile = ThisWorkbook.FullName
    Const wdFormLetters As Long = 0
    Const wdSendToNewDocument As Long = 0
    Const wdSendToPrinter = 1
    Const wdSendToEmail As Long = 2
    Const wdMergeSubTypeAccess As Long = 1
    Const wdMailFormatHTML As Long = 1
    Set wrdObj = CreateObject("Word.Application")
    With wrdObj
      .Visible = False
      .DisplayAlerts = False
      Set wrdDoc = .Documents.Open(ThisWorkbook.Path & "\MailMergeMainDocument.docx", False, True, False, , , , , , , , False)
      With wrdDoc
        With .MailMerge
          .MainDocumentType = wdFormLetters
          .Destination = wdSendToPrinter
          .SuppressBlankLines = True
          .OpenDataSource Name:=strFile, ReadOnly:=True, AddToRecentFiles:=False, LinkToSource:=False, _
            Connection:="Provider=Microsoft.ACE.OLEDB.12.0;User ID=Admin;Data Source=strFile;Mode=Read;" & _
            "Extended Properties=""HDR=YES;IMEX=1"";", SQLStatement:="SELECT * FROM [Sheet1$]", _
            SQLStatement1:="", SubType:=wdMergeSubTypeAccess
          .Execute
        End With
        .Close 0
      End With
    End With
    Set wrdDoc = Nothing: Set wrdObj = Nothing
    End Sub
    

    【讨论】:

    • 这行得通,有点。我单步执行了代码,当执行 .opendatasource 时,邮件合并运行并打印字母。 VBA 执行然后停止。没有错误。它不执行 .execute 语句或继续进行。
    • 这确实有效。当我在家用机器上进行测试时,它运行良好。在工作中测试时,它不起作用。我相信它不能在办公室工作,因为安装了不同版本的 Office。现在我需要让 IT 部门修复 Office。谢谢!
    • 该解决方案与 Office 版本无关 - 除非您使用的是 1980 年代的东西...更有可能与您的 IT 部门施加的限制有关。那么为什么要投反对票???
    • 我没有投反对票。如果我这样做是偶然的。我实际上将其作为解决方案进行了检查。在我的办公电脑上安装了多个最新版本的办公软件。某些内容未正确安装,因为当您单击电子表格时,2016 版会启动。单击 word doc 并启动 2013。我不认为我的问题是有多个版本。我认为问题在于安装不正确。
    • 有点晚了,但我想更新。 IT 卸载了 Office 并重新安装,它开始工作。这是某种版本不兼容的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多