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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 14:13:26