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

VB.NET PrintDocument多页打印异常:设置e.HasMorePages=True后无法分页

VB.NET PrintDocument 分页失效问题排查与修复

核心问题分析

你的代码无法触发新页打印,主要是以下几个关键问题导致:

  1. 分页状态无法跨页保留
    你在PrintPage事件内部声明了ii、grand_total等变量,每次触发新页打印时,这些变量都会被重置为初始值,导致系统无法记住上一页打印到哪一行,每次都从头开始打印数据。

  2. 分页标记被强制覆盖
    循环中设置e.HasMorePages = True后,代码最后又执行了e.HasMorePages = False,直接覆盖了分页指令,系统不会触发下一页打印流程。

  3. 分页触发逻辑不合理
    你的分页条件If page_number > 10 And page_number < 12限制太死,只有打印到第11行时才会尝试分页,而且没有判断是否还有未打印的剩余数据,无法适配多行数据的连续分页需求。

  4. GDI+资源未释放
    代码中创建的Pen、Font等GDI+对象没有手动释放,长期运行可能导致内存泄漏,影响打印稳定性。


修复后的完整代码

首先,在窗体类的类级别声明需要跨页保留的变量(放在事件方法外面):

' 类级变量,用于跨页保存打印状态
Private ii As Integer = 0
Private grand_total As Double = 0
Private cgst As Double = 0
Private sgst As Double = 0
Private igst As Double = 0

然后修改PrintPage事件处理代码:

Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
    Dim l, t, right, b As Integer
    Dim companyName As String = "G.M.Agencies"
    l = e.MarginBounds.Left
    t = e.MarginBounds.Top
    right = e.MarginBounds.Right
    b = e.MarginBounds.Bottom
    Dim StringAlignment As New StringFormat()
    StringAlignment.Alignment = Drawing.StringAlignment.Far
    Dim formatednumber As String

    ' 使用Using语句自动释放GDI+资源
    Using bor As New Pen(Color.Black, 2)
        Using nameFont As New Font("Arial", 24, FontStyle.Bold)
            Using nameFont2 As New Font("Arial", 12, FontStyle.Bold)
                Dim r As New Rectangle(l - 50, t - 50, right - 10, b - 10)
                e.Graphics.DrawRectangle(bor, r)

                ' 绘制卖家名称下方的横线
                e.Graphics.DrawLine(bor, l - 50, t + 100, right + 40, t + 100)

                ' 绘制买卖双方分隔竖线
                e.Graphics.DrawLine(bor, right - 350, t - 50, (right - 350), t + 100)

                ' 绘制商品描述和表头下方的横线
                e.Graphics.DrawLine(bor, l - 50, t + 150, right + 40, t + 150)
                e.Graphics.DrawLine(bor, l - 50, b - 150, right + 40, b - 150)
                e.Graphics.DrawLine(bor, l - 50, b - 250, right + 40, b - 250)

                ' 绘制商品详情表格的竖线
                e.Graphics.DrawLine(bor, l + 10, t + 100, l + 10, b - 250)
                e.Graphics.DrawLine(bor, right - 370, t + 100, right - 370, b - 150)
                e.Graphics.DrawLine(bor, right - 273, t + 100, right - 273, b - 250)
                e.Graphics.DrawLine(bor, right - 205, t + 100, right - 205, b - 250)
                e.Graphics.DrawLine(bor, right - 125, t + 100, right - 125, b - 250)
                e.Graphics.DrawLine(bor, right - 70, t + 100, right - 70, b - 150)

                ' 打印公司和发票基本信息
                e.Graphics.DrawString(companyName, nameFont, Brushes.Black, l - 40, t - 40)
                e.Graphics.DrawString("Dharapuram", nameFont2, Brushes.Black, l - 40, t)
                e.Graphics.DrawString("Invoice No", nameFont2, Brushes.Black, l - 40, t + 20)
                e.Graphics.DrawString("Date", nameFont2, Brushes.Black, l - 40, t + 40)

                ' 打印表头文本
                e.Graphics.DrawString("S.No", nameFont2, Brushes.Black, l - 40, t + 120)
                e.Graphics.DrawString("Description", nameFont2, Brushes.Black, l + 40, t + 120)
                e.Graphics.DrawString("HSN Code", nameFont2, Brushes.Black, right - 360, t + 120)
                e.Graphics.DrawString("GST %", nameFont2, Brushes.Black, right - 270, t + 120)
                e.Graphics.DrawString("Rate", nameFont2, Brushes.Black, right - 200, t + 120)
                e.Graphics.DrawString("Qty", nameFont2, Brushes.Black, right - 120, t + 120)
                e.Graphics.DrawString("Total", nameFont2, Brushes.Black, right - 60, t + 120)

                ' 打印总计项标签
                e.Graphics.DrawString("Grand Total", nameFont2, Brushes.Black, right - 170, b - 180, StringAlignment)
                e.Graphics.DrawString("Total CGST", nameFont2, Brushes.Black, right - 170, b - 200, StringAlignment)
                e.Graphics.DrawString("Total SGST", nameFont2, Brushes.Black, right - 170, b - 220, StringAlignment)
                e.Graphics.DrawString("Total  IGST", nameFont2, Brushes.Black, right - 170, b - 240, StringAlignment)
            End Using
        End Using
    End Using

    ' 打印商品详情
    Dim dataGridViewRows As DataGridViewRowCollection = dg_sales_entry.Rows
    Dim numRows As Integer = dataGridViewRows.Count
    Dim startY As Integer = t + 170
    Dim currentY As Integer = startY
    Dim page_number As Integer = 0

    e.HasMorePages = False ' 默认无更多页

    For i = ii To numRows - 1
        ' 跳过DataGridView的空行
        If dataGridViewRows(i).IsNewRow Then Continue For

        ' 累计计算总计和税费
        grand_total += CDbl(dataGridViewRows(i).Cells(10).Value)
        cgst += CDbl(dataGridViewRows(i).Cells(15).Value)
        sgst += CDbl(dataGridViewRows(i).Cells(17).Value)
        igst += CDbl(dataGridViewRows(i).Cells(13).Value)

        Dim formated_number As String = CDbl(dataGridViewRows(i).Cells(10).Value).ToString("F2")
        Dim formatednuber2 As String = formated_number.PadLeft(25 - formated_number.Length)
        Dim rate As String = CDbl(dataGridViewRows(i).Cells(7).Value).ToString("F2")
        Dim rate2 As String = rate.PadLeft(10 - rate.Length)

        e.Graphics.DrawString((i + 1).ToString(), dg_sales_entry.Font, Brushes.Black, l - 40, currentY)
        e.Graphics.DrawString(dataGridViewRows(i).Cells(4).Value.ToString(), dg_sales_entry.Font, Brushes.Black, l + 40, currentY)
        e.Graphics.DrawString(dataGridViewRows(i).Cells(5).Value.ToString(), dg_sales_entry.Font, Brushes.Black, right - 360, currentY)
        e.Graphics.DrawString(dataGridViewRows(i).Cells(12).Value.ToString(), dg_sales_entry.Font, Brushes.Black, right - 270, currentY)
        e.Graphics.DrawString(rate2, dg_sales_entry.Font, Brushes.Black, right - 200, currentY)
        e.Graphics.DrawString(dataGridViewRows(i).Cells(6).Value.ToString(), dg_sales_entry.Font, Brushes.Black, right - 120, currentY)
        e.Graphics.DrawString(formatednuber2, dg_sales_entry.Font, Brushes.Black, right - 60, currentY)

        currentY += dg_sales_entry.Rows(i).Height
        page_number += 1
        ii += 1

        ' 打印满10行且还有剩余数据时,触发分页
        If page_number >= 10 And ii < numRows - 1 Then
            e.HasMorePages = True
            Exit For
        End If
    Next

    ' 只有最后一页打印总计和税费
    If Not e.HasMorePages Then
        e.Graphics.DrawString(grand_total.ToString("F2"), dg_sales_entry.Font, Brushes.Red, right - 60, b - 180)
        e.Graphics.DrawString(sgst.ToString("F2"), dg_sales_entry.Font, Brushes.Black, right - 60, b - 220)
        e.Graphics.DrawString(cgst.ToString("F2"), dg_sales_entry.Font, Brushes.Black, right - 60, b - 200)
        e.Graphics.DrawString(igst.ToString("F2"), dg_sales_entry.Font, Brushes.Black, right - 60, b - 240)
        
        ' 重置状态变量,为下一次打印做准备
        ii = 0
        grand_total = 0
        cgst = 0
        sgst = 0
        igst = 0
    End If
End Sub

关键修改说明

  1. 类级变量保存状态:将ii、grand_total等变量移到类级别,确保分页时能延续上一页的打印位置和累计计算值。
  2. 修正分页标记逻辑:移除末尾强制设置e.HasMorePages = False的代码,改为根据剩余数据动态设置,且只有打印满10行且还有数据时才触发分页。
  3. 资源自动释放:使用Using语句包裹GDI+对象,避免内存泄漏。
  4. 总计打印优化:仅在最后一页打印累计的总计和税费,避免每页重复打印。
  5. 空行处理:跳过DataGridView的默认空行,防止打印无效数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 12:59:56