You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Access VBA中Do Until EOF循环遗漏最后一条记录的问题

解决Access VBA报表最后一条记录无法打印的问题

问题原因

核心矛盾是打开报表后立即执行ToPrint字段重置操作,此时报表可能尚未完成所有记录的数据读取流程,最后一条记录的ToPrint字段被快速改为False,导致报表未捕获到该记录的打印标记。


方法1:用对话框模式打开报表,等待关闭后再重置

将报表以acDialog模式打开,代码会暂停执行直到用户关闭报表预览窗口,确保报表完全读取数据后再重置字段。修改后的完整代码:

Sub PrintReports()
    Dim rst As Recordset
    Dim startDate As Date
    Dim endDate As Date
 
    ' 提示用户输入开始日期
    startDate = InputBox("Enter start date (mm/dd/yyyy):")

    ' 提示用户输入结束日期
    endDate = InputBox("Enter end date (mm/dd/yyyy):")

    Set rst = CurrentDb.OpenRecordset("SELECT * FROM CustomerT WHERE ExpiryDate >= #" & startDate & "# AND ExpiryDate <= #" & endDate & "#")

    ' 标记需要打印的记录
    Do Until rst.EOF
        rst.Edit
        rst("ToPrint") = True
        rst.Update
        rst.MoveNext
    Loop

    ' 对话框模式打开报表,代码暂停到报表关闭
    DoCmd.OpenReport "2DateReports", acViewPreview, , , acDialog

    ' 重置所有标记为False
    rst.MoveFirst
    Do Until rst.EOF
        rst.Edit
        rst("ToPrint") = False
        rst.Update
        rst.MoveNext
    Loop

    ' 释放资源
    rst.Close
    Set rst = Nothing
End Sub

方法2:在报表关闭事件中触发重置

通过报表的OnClose事件执行重置操作,无需阻塞主流程,更符合Access事件驱动的设计逻辑:

  1. 声明全局变量存储日期范围,用于传递给报表事件:
Public g_startDate As Date
Public g_endDate As Date
  1. 修改主打印过程,去掉末尾的重置循环:
Sub PrintReports()
    Dim rst As Recordset
 
    ' 获取用户输入的日期
    g_startDate = InputBox("Enter start date (mm/dd/yyyy):")
    g_endDate = InputBox("Enter end date (mm/dd/yyyy):")

    Set rst = CurrentDb.OpenRecordset("SELECT * FROM CustomerT WHERE ExpiryDate >= #" & g_startDate & "# AND ExpiryDate <= #" & g_endDate & "#")

    ' 标记需要打印的记录
    Do Until rst.EOF
        rst.Edit
        rst("ToPrint") = True
        rst.Update
        rst.MoveNext
    Loop

    ' 正常打开报表
    DoCmd.OpenReport "2DateReports", acViewPreview, , , acNormal

    ' 释放资源
    rst.Close
    Set rst = Nothing
End Sub
  1. 打开报表设计视图,添加OnClose事件代码:
Private Sub Report_Close()
    Dim rst As Recordset
    Set rst = CurrentDb.OpenRecordset("SELECT * FROM CustomerT WHERE ExpiryDate >= #" & g_startDate & "# AND ExpiryDate <= #" & g_endDate & "#")
    
    ' 重置打印标记
    Do Until rst.EOF
        rst.Edit
        rst("ToPrint") = False
        rst.Update
        rst.MoveNext
    Loop

    rst.Close
    Set rst = Nothing
End Sub

额外优化建议

  • 避免直接拼接SQL日期字符串,改用参数查询防止格式错误:
Dim qdf As QueryDef
Set qdf = CurrentDb.CreateQueryDef("", "SELECT * FROM CustomerT WHERE ExpiryDate >= [StartDate] AND ExpiryDate <= [EndDate]")
qdf.Parameters("[StartDate]") = startDate
qdf.Parameters("[EndDate]") = endDate
Set rst = qdf.OpenRecordset()
  • 原循环中的Do Until rst.EOF Or rst.BOF冗余,MoveFirst后BOF始终为False,直接用Do Until rst.EOF即可。

内容的提问来源于stack exchange,提问作者diamanthian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 03:05:31