POS系统使用Report Viewer打印收据始终输出首单而非当前订单问题
问题修复方案
核心问题原因
- 你使用了全局静态的
FrmReceipt窗体实例,第一次调用ShowDialog()后窗体没有释放,后续调用时复用了旧实例的ReportViewer缓存数据,导致始终显示第一笔订单信息 - 部分场景下
PrintPreview方法内部没有做数据源清空、重新绑定的逻辑,哪怕传入了新的查询语句也没有加载新数据 - 额外SQL隐患:查询、更新语句中无通配符的
LIKE可以替换为=,避免不必要的匹配错误
修复步骤
1. 修改Savepayment中收据调用逻辑
每次打印都创建新的收据窗体实例,避免复用旧实例缓存,把原有代码段:
With FrmReceipt .PrintPreview("Select c.id, p.Description, c.price, c.qty, c.total From tblcart as c inner join tblproduct as p on c.pid=p.id where c.status like 'Completed' and TransNo like '" & FrmPos.LblTransNo.Text & "'") .ShowDialog() End With
替换为:
' 新建独立收据窗体实例 Dim receiptForm As New FrmReceipt() With receiptForm ' 替换LIKE为=提升查询准确性 .PrintPreview("Select c.id, p.Description, c.price, c.qty, c.total From tblcart as c inner join tblproduct as p on c.pid=p.id where c.status = 'Completed' and TransNo = '" & FrmPos.LblTransNo.Text & "'") .ShowDialog() End With ' 用完释放资源 receiptForm.Dispose()
2. 校验FrmReceipt的PrintPreview方法逻辑
确保该方法每次调用都会清空旧数据源、重新加载新数据、刷新报表,参考正确逻辑如下:
Sub PrintPreview(sqlQuery As String) ' 清空原有报表数据源 ReportViewer1.LocalReport.DataSources.Clear() ' 加载新的订单数据 Dim orderDt As New DataTable() Using conn As New SqlConnection("你的数据库连接字符串") conn.Open() Dim cmd As New SqlCommand(sqlQuery, conn) Dim adapter As New SqlDataAdapter(cmd) adapter.Fill(orderDt) End Using ' 绑定新数据源并刷新报表 ReportViewer1.LocalReport.DataSources.Add(New ReportDataSource("你报表配置的数据源名称", orderDt)) ReportViewer1.RefreshReport() End Sub
额外优化建议
- 将SQL语句中的字符串拼接替换为参数化查询,避免SQL注入风险,同时避免订单号含特殊字符导致的查询错误
- 不要复用全局的数据库连接对象
cn,每次数据库操作新建连接、用完自动释放,避免连接泄漏
内容的提问来源于stack exchange,提问作者Chaker
相关产品推荐
相关产品推荐

