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

如何使用iTextSharp实现DataTable每行数据生成PDF单独一页

问题原因

你的代码存在3个核心问题导致只能输出单页PDF:

  • 你在获取到DataTable后就立刻执行了dt0.Dispose()、ds.Dispose(),后续循环访问dt0.Rows实际是操作已释放的资源,属于隐形逻辑错误
  • 你将PDF文档创建、响应输出的逻辑全部放在了For循环内部,第一次循环执行到Response.End()就会直接终止整个请求处理,后续循环完全不会运行
  • 每次循环都新建独立的Document对象,本质是每次生成一个全新的单页PDF,自然无法合并为多页文件,同时你还做了多余的字节数组转Base64再转字节数组的冗余操作
修复后的代码
Private Sub MySub(Param As String)
    Try
        Dim obj As New ReportObjects
        Dim dt0 As DataTable
        Dim ds As DataSet = obj.MyStoredProcedure(Param)
        obj.Dispose()
        dt0 = ds.Tables(0)

        ' 把PDF对象创建移到循环外部
        Using memoryStream As System.IO.MemoryStream = New System.IO.MemoryStream()
            Dim document As Document = New Document(PageSize.A4, 1.0F, 1.0F, 1.0F, 1.0F)
            Dim writer As PdfWriter = PdfWriter.GetInstance(document, memoryStream)
            document.Open()

            ' 循环生成每页优惠券
            For i As Integer = 0 To dt0.Rows.Count - 1
                Dim qrGenerator As QRCodeGenerator = New QRCodeGenerator()
                Dim qrCode As QRCodeGenerator.QRCode = qrGenerator.CreateQrCode(dt0.Rows(i).Item("VoucherNo"), QRCodeGenerator.ECCLevel.Q)
                Dim byteImage As Byte()
                Using bitMap As Bitmap = qrCode.GetGraphic(20)
                    Using ms As MemoryStream = New MemoryStream()
                        bitMap.Save(ms, System.Drawing.Imaging.ImageFormat.Png)
                        byteImage = ms.ToArray()
                    End Using
                End Using

                ' 去掉冗余的Base64转码步骤
                Dim image As iTextSharp.text.Image = iTextSharp.text.Image.GetInstance(byteImage)
                ' 非第一页调用NewPage添加新页
                If i > 0 Then document.NewPage()
                document.Add(image)
                document.Add(New Phrase("Valid From : " & dt0.Rows(i).Item("StartDT").ToString() & " To " & dt0.Rows(i).Item("EndDT").ToString()))
            Next

            ' 所有页生成完成后再关闭文档、输出
            document.Close()
            Dim bytes As Byte() = memoryStream.ToArray()

            ' 释放DataTable相关资源,移到使用完之后
            dt0.Dispose()
            ds.Dispose()

            Response.Clear()
            Response.ContentType = "application/pdf"
            Response.AddHeader("Content-Disposition", "attachment; filename=Vouchers.pdf")
            Response.Buffer = True
            Response.Cache.SetCacheability(HttpCacheability.NoCache)
            Response.BinaryWrite(bytes)
            Response.End()
        End Using

    Catch ex As Exception
        Throw New Exception(ex.Message)
    End Try
End Sub
核心修改说明
  • 调整了资源释放顺序,DataTable、DataSet在所有循环逻辑执行完成后才释放,避免访问已释放对象
  • PDF文档实例、输出流的创建移到循环外部,循环内仅处理当前优惠券的二维码生成和内容添加,每处理完一张调用NewPage()新建下一页
  • 所有优惠券页全部生成完成后,再统一将完整的PDF字节流输出到Response,仅调用一次Response.End()
  • 删除了无意义的字节数组转Base64再转回字节数组的冗余步骤,减少性能损耗

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 22:18:02