我有一个通过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
提前非常感谢!
这个答案是基于到目前为止的评论。
- 我没有遇到问题。除非此文档是错误的文档,否则包含在此处。但是,由于您的循环代码在访问ThisDocument.MailMerge.DataSource的其他成员时似乎不会引发错误,因此问题所在并不明显。但是,我认为您不需要使用.包括。
- 一旦我尝试访问任何.数据源.数据字段项。我不知道为什么会这样。每次访问都有延迟,而不仅仅是每条记录的第一次访问。我的一个想法是,一旦您更改活动记录,Word 就会刷新主文档中合并字段的值,这可能会导致问题,尤其是在 Word 由于某种原因需要访问打印机驱动程序的情况下。但是我尝试过的任何内容(例如将视图更改为草稿(都不会改变这一点。
-
你真的不需要.之所以包含,是因为您可以像这样迭代记录:
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。
-
我能够加快对数据的访问的唯一方法是修改文档以包含我要列出的所有字段,然后从文档中而不是从 中获取值。我个人认为修改邮件合并主文档并不理想 - 特别是,某些东西可能会阻止您在开始时插入材料,就像我所做的那样。但是我的测试代码(需要更多的错误捕获等(是这样的(:
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
-
最后,可能值得指出的是,还有其他方法可以排除记录,例如使用 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 工作表对象。