VB.NET PrintDocument多页打印失效问题:代码存在哪些错误?
问题分析与修复
你的代码存在几个核心问题导致无法正常分页:
- 缺少全局状态记录:每次触发
PrintPage事件时,所有变量都会重新初始化,没有记录已经打印到哪一行,导致每次都从头打印,且后续页面无法正确接续。 - 无效循环干扰变量值:空的
For List = 0 To ListView1.Items.Count - 1循环会把List变量直接设为ListView1.Items.Count - 1,破坏了后续的位置计算逻辑。 - 分页逻辑完全错误:提前判断
List > 1000设置e.HasMorePages = True,但随后又打印所有行,最后强制设置e.HasMorePages = False,直接覆盖了分页标记,导致不会触发后续页面打印。 - 未利用页面边界计算:固定用1000作为分页阈值,没有结合打印页面的实际可用高度(
e.MarginBounds),分页位置不准确。
修复后的代码
首先在窗体类中声明模块级变量,记录当前打印的项索引:
Private currentPrintIndex As Integer = 0
然后修改PrintDocument1_PrintPage事件处理代码:
Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage Dim yPos As Integer = e.MarginBounds.Top ' 从页面边距顶部开始打印 Dim rowHeight As Integer = 50 ' 每行的高度,可根据字体调整 Dim headerFont As New Drawing.Font("Times New Roman", 20) Dim rowFont As New Drawing.Font("Times New Roman", 10) ' 打印标题 e.Graphics.DrawString("Pocket book collection", headerFont, Brushes.Black, e.MarginBounds.Left + 200, yPos) yPos += headerFont.Height + 10 ' 标题下方留间距 ' 打印表头 e.Graphics.DrawString("Pocket Serie Name", rowFont, Brushes.Black, e.MarginBounds.Left, yPos) e.Graphics.DrawString("Single/Double", rowFont, Brushes.Black, e.MarginBounds.Left + 50, yPos) e.Graphics.DrawString("Pocket Nr", rowFont, Brushes.Black, e.MarginBounds.Left + 150, yPos) e.Graphics.DrawString("Year", rowFont, Brushes.Black, e.MarginBounds.Left + 250, yPos) e.Graphics.DrawString("Bought Date", rowFont, Brushes.Black, e.MarginBounds.Left + 400, yPos) e.Graphics.DrawString("Cost", rowFont, Brushes.Black, e.MarginBounds.Left + 500, yPos) yPos += rowFont.Height + 10 ' 表头下方留间距 ' 打印数据行,从当前索引开始 While currentPrintIndex < ListView1.Items.Count Dim item As ListViewItem = ListView1.Items(currentPrintIndex) ' 检查当前行是否超出页面底部边距 If yPos + rowHeight > e.MarginBounds.Bottom Then e.HasMorePages = True ' 还有未打印内容,触发下一页 Exit While End If ' 打印当前行的各个子项 e.Graphics.DrawString(item.Text, rowFont, Brushes.Black, e.MarginBounds.Left, yPos) e.Graphics.DrawString(item.SubItems(1).Text, rowFont, Brushes.Black, e.MarginBounds.Left + 50, yPos) e.Graphics.DrawString(item.SubItems(2).Text, rowFont, Brushes.Black, e.MarginBounds.Left + 150, yPos) e.Graphics.DrawString(item.SubItems(3).Text, rowFont, Brushes.Black, e.MarginBounds.Left + 250, yPos) e.Graphics.DrawString(item.SubItems(4).Text, rowFont, Brushes.Black, e.MarginBounds.Left + 400, yPos) e.Graphics.DrawString(item.SubItems(5).Text, rowFont, Brushes.Black, e.MarginBounds.Left + 500, yPos) yPos += rowHeight currentPrintIndex += 1 End While ' 如果所有项都打印完成,重置索引并标记无更多页面 If currentPrintIndex >= ListView1.Items.Count Then e.HasMorePages = False currentPrintIndex = 0 ' 重置索引,方便下次打印 End If ' 释放字体资源 headerFont.Dispose() rowFont.Dispose() End Sub
关键修复点说明
- 模块级索引变量:
currentPrintIndex记录当前打印到哪一项,确保每次触发PrintPage时从上次结束的位置继续打印。 - 基于页面边界分页:使用
e.MarginBounds.Bottom判断当前行是否超出页面,分页更准确,适配不同纸张大小。 - 正确设置
HasMorePages:只有当还有未打印的项且当前页面已满时,才标记需要下一页,打印完成后重置索引。 - 释放资源:手动释放创建的
Font对象,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Joachim
相关产品推荐
相关产品推荐

