如何获取 Word 邮件合并文档中包含的记录列表?



我有一个通过VBA控制的邮件合并文档。用户选择要打印的记录后,我希望这些记录在数据库中设置打印日期。为此,我需要邮件合并中包含的记录列表。

我尝试使用 .包括属性,设置ThisDocument.MailMerge.DataSource.ActiveRecord = wdFirstRecord(我后来删除了wdFirstRecord,有利于1,因为它给我带来了麻烦( 然后检查ThisDocument.MailMerge.DataSource.Included是否为 true,但收到 5852 运行时错误"对象不可用"。编辑:我使用以下代码循环访问记录。当我删除任何一个评论时.包含语句,我得到说错误。(执行不再像昨天那样慢,尽管不是特别快。

Function outputRecords(Optional limitRecords = -1)
With ThisDocument.MailMerge.DataSource
Dim str
For currentFieldNameIndex = 1 To .FieldNames.Count
str = str & .FieldNames(currentFieldNameIndex) & vbTab
Next
Debug.Print str
For currentRecordIndex = 1 To .RecordCount
If currentRecordIndex <= limitRecords Or limitRecords < 0 Then
.ActiveRecord = currentRecordIndex
str = ""
For currentDataFieldIndex = 1 To .DataFields.Count
str = str & .DataFields(currentDataFieldIndex) & vbTab
Next
'Debug.Print str
End If
'.Included = True
'Debug.Print .Included
Next
End With
End Function

是否有解决方案可以知道用户选择了哪些记录?

关于我的文档:经过一些常规计算后,数据源链接到文档

Dim sql As String
sql = "SELECT * FROM `Sheet0$` "
sql = sql & "WHERE ((`" & photoPathHeader & "` > '') AND (`" & photoLastEditHeader & "` >= #" & Format(printFromDate, "yyyy-mm-dd") & "#)) "
sql = sql & "ORDER BY `klasse#name` ASC"
ThisDocument.MailMerge.OpenDataSource _
name:=ThisDocument.Path & "" & ThisDocument.Variables("masterDataFileName"), _
SQLStatement1:=sql, _
ReadOnly:=True, LinkToSource:=True

将显示一个对话框,用户可以在其中选择要打印的单个记录。我为此使用了这段代码:

Application.Dialogs(wdDialogMailMergeRecipients).Display

最后,邮件合并是使用

ThisDocument.MailMerge.Execute

提前非常感谢!

这个答案是基于到目前为止的评论。

  1. 我没有遇到问题。除非此文档是错误的文档,否则包含在此处。但是,由于您的循环代码在访问ThisDocument.MailMerge.DataSource的其他成员时似乎不会引发错误,因此问题所在并不明显。但是,我认为您不需要使用.包括。
  2. 一旦我尝试访问任何.数据源.数据字段项。我不知道为什么会这样。每次访问都有延迟,而不仅仅是每条记录的第一次访问。我的一个想法是,一旦您更改活动记录,Word 就会刷新主文档中合并字段的值,这可能会导致问题,尤其是在 Word 由于某种原因需要访问打印机驱动程序的情况下。但是我尝试过的任何内容(例如将视图更改为草稿(都不会改变这一点。
  3. 你真的不需要.之所以包含,是因为您可以像这样迭代记录:

    With ActiveDocument.MailMerge.DataSource
    previousRecord = 0
    .ActiveRecord = wdFirstRecord
    While .ActiveRecord <> previousRecord
    previousRecord = .ActiveRecord
    Debug.Print .ActiveRecord ' (just lists the record number)
    previousRecord = .ActiveRecord
    .ActiveRecord = wdNextRecord
    DoEvents ' advisable if you need to stop the code
    Wend
    

    如果需要迭代所有记录,则需要改用 wdFirstDataSourceRecord 和 wdNextDataSourceRecord。

  4. 我能够加快对数据的访问的唯一方法是修改文档以包含我要列出的所有字段,然后从文档中而不是从 中获取值。我个人认为修改邮件合并主文档并不理想 - 特别是,某些东西可能会阻止您在开始时插入材料,就像我所做的那样。但是我的测试代码(需要更多的错误捕获等(是这样的(:

    Sub checkincluded()
    Dim b As Word.Bookmark
    Dim bVMMFC As Boolean
    Dim bSFC As Boolean
    Dim i As Integer
    Dim previousRecord As Long
    Dim p As Word.Paragraph
    Dim r As Word.Range
    With ActiveWindow.View
    bSFC = .ShowFieldCodes
    .ShowFieldCodes = False
    End With
    With ActiveDocument.MailMerge
    bVMMFC = .ViewMailMergeFieldCodes
    .ViewMailMergeFieldCodes = False
    With .DataSource
    Set r = ActiveDocument.Range(0, 0)
    Set p = ActiveDocument.Range(0, 0).Paragraphs.Add
    
    For i = 1 To .FieldNames.Count
    If i > 1 Then
    r.Text = vbTab
    r.Start = p.Range.End - 1
    r.End = p.Range.End - 1
    End If
    r.Fields.Add r, WdFieldType.wdFieldMergeField, .FieldNames(i), False
    r.Start = p.Range.End - 1
    r.End = p.Range.End - 1
    Next
    r.Start = 0
    r.End = p.Range.End - 1
    Set b = r.Bookmarks.Add("recorddata")
    Set r = Nothing
    previousRecord = 0
    .ActiveRecord = wdFirstRecord
    While .ActiveRecord <> previousRecord
    previousRecord = .ActiveRecord
    Debug.Print .ActiveRecord, b.Range.Text
    previousRecord = .ActiveRecord
    .ActiveRecord = wdNextRecord
    DoEvents
    Wend
    b.Delete
    Set b = Nothing
    p.Range.Text = ""
    Set p = Nothing
    End With
    .ViewMailMergeFieldCodes = bVMMFC
    End With
    ActiveWindow.View.ShowFieldCodes = bSFC
    End Sub
    
  5. 最后,可能值得指出的是,还有其他方法可以排除记录,例如使用 NEXT、NEXTIF、SKIP 和 SKIPIF 字段。但这也许是另一个问题。

多亏了@yokki的回答,我能够将其与我所知道的结合起来,最终得出以下结果

Sub listIncluded()
Dim LastRecord As Long
With ActiveDocument.MailMerge.DataSource
' Storing the index of the last record for later use
.ActiveRecord = wdLastRecord
LastRecord = .ActiveRecord
.ActiveRecord = wdFirstRecord
Do
Debug.Print .ActiveRecord
DoEvents
If .ActiveRecord = LastRecord Then Exit Do
.ActiveRecord = wdNextRecord
Loop Until .ActiveRecord > LastRecord ' Note this will never be satisfied and the loop will always be exited via the Exit Do statement
End With
End Sub

我发现WdMailMergeActiveRecord枚举有点令人困惑,但这有效。

如果已经达到最后包含的记录并且不等于最后一条记录(即不包括最后一条记录(,则原始答案会在wdNextRecord上抛出5853 Invalid parameter错误。我通过将最后一条记录的索引存储到局部变量中并使用它来检查是否到达了最后包含的记录来规避此问题。

非常感谢所有帮助过的人!

正如评论中简要指出的那样,我已经有所有 数据源中的数据作为数组,因为我在其他部分中也使用它 的脚本。我为此使用了以下语句

numRows = wks.Range("A1").CurrentRegion.Rows.Count
masterData = wks.Range("A1").CurrentRegion.Offset(RowOffset:=1).Resize(RowSize:=numRows).Value

wks是指 Excel 工作表对象。

最新更新