如何从 Excel 运行 Word 邮件合并宏?

发布于 2025-01-14 13:56:18 字数 4882 浏览 7 评论 0原文

我的 Excel 工作簿中有一个宏,当前执行以下操作:

  1. 创建一个包含前两行数据的 data.csv 文件(用于邮件合并)
  2. 提取所选 Word 文档的模板并将 data.csv 文件作为源对于邮件合并
  3. 如果用户选择,它会完成文档的合并
  4. 如果用户选择,它会在宏完成时打开文档。如果他们不选择打开,Word 文档将全部关闭。

我遇到了几个主要问题:

  1. 只有在事先完全关闭 Word 的情况下,宏才能顺利运行。我当前的解决方法是,如果 Word 打开,则会弹出一条消息,告诉用户关闭 Word,但这并不理想,因为它会扰乱某些可能打开多个 Word 实例的用户的流程。
  2. 该宏运行缓慢,特别是对于某些在模板中预先输入了数千个合并字段的文档模板。有时需要超过一分钟,有时会完全冻结。

如果我让 Excel VBA 打开 Word 模板,并且在 Word VBA 中拥有用于设置和完成邮件合并的大部分代码,宏会运行得更顺畅吗?我对 Word VBA 不太熟悉 - 任何人都可以帮助我将代码转换为 Word(但仍然由 Excel 启动)吗?另外,如果您能弄清楚为什么当 Word 已经打开时宏会陷入困境,我将不胜感激。

出于专有原因,我没有包含完整的代码,但如果您还需要查看其他内容,请告诉我。

谢谢你!!

Sub Mail_Merge_Dynamic()
    Dim mergeFile, tempFilePath As String
    Dim WordDoc, WordApp As Object
    Dim tempPath, mergePath, finalPath, curDir As String
    Dim mergeFilePath, finalFilePath As String
    Dim dataPath, FileNameCell, PrincCertCell, MMPrefix As String
    Dim FileCount As Integer
    Dim Close_Choice, ActiveWindow As String
    Dim WarningMsg, WarningMsg2 As String
    Dim NotFound, Overwrite1, Overwrite2 As Boolean
    
Dim oBook As Workbook

'Update csv file for Data Merge
    narrative_merge
    Call WarpSpeed_On
    Sheets("Navigation").Select
    Range("Merge_File_1").Select
    
    Set WordApp = CreateObject("Word.Application")
    
'//////////////////////////////MAIL MERGE MACRO\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
'Set up Mail Merge Documents from Template Folder based on selections on Navigation tab
    For i = 1 To FileCount
        FileNameCell = "Merge_File_" & i
        If Range(FileNameCell) = "" Then
        Else
            mergeFile = Range(FileNameCell)
            
           
            tempFilePath = tempPath & mergeFile
    
            mergeFilePath = mergePath & "MM_" & mergeFile
            finalFilePath = finalPath & mergeFile
                
'Activate Mail Merge
            If Range("MM_Activate") = 0 Then
            Else
                Set WordDoc = WordApp.Documents.Open(tempFilePath)
                
                With WordDoc.MailMerge
                    .MainDocumentType = wdFormLetters
        
                'Set up the mail merge data source
                    dataPath = curDir & "\data.csv"
                    .OpenDataSource Name:=dataPath
                    
                'Show values in the mail merge fields
                    .ViewMailMergeFieldCodes = wdToggle
                End With
                
                'WordDoc.ShowFieldCodes = False
                'WordDoc.MailMerge.ViewMailMergeFieldCodes = False
                
                WordDoc.SaveAs FileName:=mergeFilePath
        
            End If
              
' Finish mail merge
            If Range("MM_Finish") = 0 Then
            Else
                With WordDoc.MailMerge
                    .Destination = wdSendToNewDocument
                    .SuppressBlankLines = True
                    .Execute Pause:=False
                End With
            
                WordDoc.Application.ActiveDocument.SaveAs finalFilePath
            End If
                
        End If
    Next i
       
Call CloseWordDocuments
    
'Make word visible if an Open command has been selected
If Range("MM_Open_Merge") = 1 Or Range("MM_Open_Doc") = 1 Then
    curDir = ThisWorkbook.Path
    Set WordApp = CreateObject("Word.Application")
    
    For i = 1 To FileCount
        FileNameCell = "Merge_File_" & i
        If Range(FileNameCell) = "" Then
        Else
        
        mergeFile = Range(FileNameCell)
          
        mergeFilePath = curDir & "\Merge-Active Forms\" & "MM_" & mergeFile
        finalFilePath = curDir & "\Merge-Complete Forms\" & mergeFile
            
            If Range("MM_Open_Merge") = 1 Then
                Set WordDoc = WordApp.Documents.Open(mergeFilePath)
            End If
            
            If Range("MM_Open_Doc") = 1 Then
                Set WordDoc = WordApp.Documents.Open(finalFilePath)
            End If
        End If
    Next i
    
    WordApp.Visible = True
    'Windows(mergeFile).Activate
    
End If

GoTo Reset
Reset:
Call WarpSpeed_Off
      

End Sub


Sub WarpSpeed_On_Calcs_Off()

'Optimize Macro Speed
  Application.ScreenUpdating = False
  Application.EnableEvents = False
  Application.Calculation = xlCalculationManual
  
' Turn off display alerts
  Application.DisplayAlerts = False
End Sub

Sub WarpSpeed_On()

'Optimize Macro Speed
  Application.ScreenUpdating = False
  Application.EnableEvents = False
  
' Turn off display alerts
    Application.DisplayAlerts = False

End Sub


Sub WarpSpeed_Off()

'Reset Macro Optimization Settings
   Application.EnableEvents = True
   Application.ScreenUpdating = True
   Application.DisplayAlerts = True
   Application.Calculation = xlCalculationAutomatic

End Sub

I have a macro in an Excel workbook that currently does the following:

  1. Create a data.csv file with data in the first two rows (for a mail merge)
  2. Pull a template of a selected Word document and make the data.csv file the source for the mail merge
  3. If the user chooses, it finishes the merge for the document
  4. If the user chooses, it opens the document when the macro is complete. If they don't choose to open, the word documents all close.

I've been running into a couple major issues:

  1. The macro only seems to run smoothly if Word is entirely closed beforehand. My current workaround is a popup message if Word is open, telling the user to close word, but this is not ideal because it disrupts flow for some users who may have several instances of Word open.
  2. The macro has been running slowly, especially for some of the document templates that have thousands of merge fields pre-entered in the template. It sometimes take longer than a minute, and sometimes completely freezes.

Would the macro would run more smoothly if I have the Excel VBA open the Word template and have most of the code for setting up and finishing the mail merge in Word VBA? I'm much less familiar with Word VBA - can anyone help me with bringing over my code to word (but still initiated by Excel)? Also, if you can figure out why the macro struggles when Word is already open, I'd greatly appreciate it.

I didn't include the entire code for proprietary reasons, but please let me know if there's something else you need to see.

Thank you!!

Sub Mail_Merge_Dynamic()
    Dim mergeFile, tempFilePath As String
    Dim WordDoc, WordApp As Object
    Dim tempPath, mergePath, finalPath, curDir As String
    Dim mergeFilePath, finalFilePath As String
    Dim dataPath, FileNameCell, PrincCertCell, MMPrefix As String
    Dim FileCount As Integer
    Dim Close_Choice, ActiveWindow As String
    Dim WarningMsg, WarningMsg2 As String
    Dim NotFound, Overwrite1, Overwrite2 As Boolean
    
Dim oBook As Workbook

'Update csv file for Data Merge
    narrative_merge
    Call WarpSpeed_On
    Sheets("Navigation").Select
    Range("Merge_File_1").Select
    
    Set WordApp = CreateObject("Word.Application")
    
'//////////////////////////////MAIL MERGE MACRO\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
'Set up Mail Merge Documents from Template Folder based on selections on Navigation tab
    For i = 1 To FileCount
        FileNameCell = "Merge_File_" & i
        If Range(FileNameCell) = "" Then
        Else
            mergeFile = Range(FileNameCell)
            
           
            tempFilePath = tempPath & mergeFile
    
            mergeFilePath = mergePath & "MM_" & mergeFile
            finalFilePath = finalPath & mergeFile
                
'Activate Mail Merge
            If Range("MM_Activate") = 0 Then
            Else
                Set WordDoc = WordApp.Documents.Open(tempFilePath)
                
                With WordDoc.MailMerge
                    .MainDocumentType = wdFormLetters
        
                'Set up the mail merge data source
                    dataPath = curDir & "\data.csv"
                    .OpenDataSource Name:=dataPath
                    
                'Show values in the mail merge fields
                    .ViewMailMergeFieldCodes = wdToggle
                End With
                
                'WordDoc.ShowFieldCodes = False
                'WordDoc.MailMerge.ViewMailMergeFieldCodes = False
                
                WordDoc.SaveAs FileName:=mergeFilePath
        
            End If
              
' Finish mail merge
            If Range("MM_Finish") = 0 Then
            Else
                With WordDoc.MailMerge
                    .Destination = wdSendToNewDocument
                    .SuppressBlankLines = True
                    .Execute Pause:=False
                End With
            
                WordDoc.Application.ActiveDocument.SaveAs finalFilePath
            End If
                
        End If
    Next i
       
Call CloseWordDocuments
    
'Make word visible if an Open command has been selected
If Range("MM_Open_Merge") = 1 Or Range("MM_Open_Doc") = 1 Then
    curDir = ThisWorkbook.Path
    Set WordApp = CreateObject("Word.Application")
    
    For i = 1 To FileCount
        FileNameCell = "Merge_File_" & i
        If Range(FileNameCell) = "" Then
        Else
        
        mergeFile = Range(FileNameCell)
          
        mergeFilePath = curDir & "\Merge-Active Forms\" & "MM_" & mergeFile
        finalFilePath = curDir & "\Merge-Complete Forms\" & mergeFile
            
            If Range("MM_Open_Merge") = 1 Then
                Set WordDoc = WordApp.Documents.Open(mergeFilePath)
            End If
            
            If Range("MM_Open_Doc") = 1 Then
                Set WordDoc = WordApp.Documents.Open(finalFilePath)
            End If
        End If
    Next i
    
    WordApp.Visible = True
    'Windows(mergeFile).Activate
    
End If

GoTo Reset
Reset:
Call WarpSpeed_Off
      

End Sub


Sub WarpSpeed_On_Calcs_Off()

'Optimize Macro Speed
  Application.ScreenUpdating = False
  Application.EnableEvents = False
  Application.Calculation = xlCalculationManual
  
' Turn off display alerts
  Application.DisplayAlerts = False
End Sub

Sub WarpSpeed_On()

'Optimize Macro Speed
  Application.ScreenUpdating = False
  Application.EnableEvents = False
  
' Turn off display alerts
    Application.DisplayAlerts = False

End Sub


Sub WarpSpeed_Off()

'Reset Macro Optimization Settings
   Application.EnableEvents = True
   Application.ScreenUpdating = True
   Application.DisplayAlerts = True
   Application.Calculation = xlCalculationAutomatic

End Sub

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

困倦 2025-01-21 13:56:18

而不是:

Set WordApp = CreateObject("Word.Application")

这将打开 Word(如果尚未打开):

Set WordApp = GetObject(, "Word.Application")

Edit#1

在 VBA 中,您可以执行以下操作:

  On Error GoTo CreateObj
  ' Is Word application already running ?
  Set WordApp = GetObject(, "Word.Application")
  GoTo gotApp
CreateObj:
  ' Not running, create first instance:
  Set WordApp = CreateObject("Word.Application")
gotApp:
  On Error GoTo 0 ' disable error handling
  ' continue
  ....
  ....

Instead of:

Set WordApp = CreateObject("Word.Application")

this will open Word if it is not already open:

Set WordApp = GetObject(, "Word.Application")

Edit#1

In VBA you may do something like:

  On Error GoTo CreateObj
  ' Is Word application already running ?
  Set WordApp = GetObject(, "Word.Application")
  GoTo gotApp
CreateObj:
  ' Not running, create first instance:
  Set WordApp = CreateObject("Word.Application")
gotApp:
  On Error GoTo 0 ' disable error handling
  ' continue
  ....
  ....
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文