如何在ASP.NET中用Crystal Reports导出多页不同内容的PDF?
使用Crystal Reports在ASP.NET Web Forms导出多页PDF(每页格式一致内容不同)
问题说明
目前通过ASP.NET Web Forms给Crystal Reports传递参数导出PDF时,仅能生成单页PDF,但实际DataTable包含多条数据,需要实现每页格式完全一致,每条数据单独占一页的多页PDF导出。
解决方案
方式一:利用Crystal Reports原生数据源绑定+分页(推荐)
这是最高效的实现方式,利用Crystal Reports的报表节分页功能自动生成多页:
修改报表设计
- 为报表创建匹配DataTable结构的数据集(Dataset),将其设置为报表的数据源。
- 把报表中原本用参数(P_DUMMY1、P_DUMMY2等)显示的内容,替换为绑定到数据集对应字段的控件,保留原格式布局不变。
- 设置详细资料节分页:右键点击报表的「详细资料」节空白处,选择「节专家」,在弹出窗口中勾选「在后面新建页」,确保每条记录渲染后自动分页。
修改后台代码
不再单独取单条记录设置参数,直接将整个DataTable绑定到报表:
ReportDocument reportDocument = new ReportDocument(); reportDocument.Load(Server.MapPath(@"Report\MyReportFile.rpt")); // 获取包含多条数据的DataTable DataTable dt = new DummyDL().PROCEDURE_GET_DUMMY_DATA(DUMMY_NO); // 将完整DataTable绑定为报表数据源 reportDocument.SetDataSource(dt); // 若需全局参数(如P_DUMMY),仍可正常设置 reportDocument.SetParameterValue("P_DUMMY", DUMMY); // PDF导出配置 ExportOptions exportOpts = new ExportOptions(); PdfFormatOptions pdfOpts = ExportOptions.CreatePdfFormatOptions(); exportOpts.ExportFormatType = ExportFormatType.PortableDocFormat; exportOpts.ExportFormatOptions = pdfOpts; // 导出到响应流 reportDocument.ExportToHttpResponse(exportOpts, Response, false, "多页报表"); // 报表Viewer绑定逻辑 if (!IsPostBack) CrystalReportViewer1.Error += new ErrorEventHandler(CrystalReportViewer1_Error); CrystalReportViewer1.ReportSource = reportDocument; CrystalReportViewer1.DataBind();
方式二:循环生成单页报表并合并PDF(特殊场景用)
如果因特殊限制无法修改报表数据源,可循环生成单页报表,导出为内存流后合并成多页PDF(需引入iTextSharp等PDF处理库):
using iTextSharp.text; using iTextSharp.text.pdf; using System.IO; // 创建内存流存储合并后的PDF MemoryStream mergedStream = new MemoryStream(); Document document = new Document(); PdfCopy copy = new PdfCopy(document, mergedStream); document.Open(); DataTable dt = new DummyDL().PROCEDURE_GET_DUMMY_DATA(DUMMY_NO); foreach (DataRow row in dt.Rows) { ReportDocument report = new ReportDocument(); report.Load(Server.MapPath(@"Report\MyReportFile.rpt")); // 为当前行设置参数 report.SetParameterValue("P_DUMMY", DUMMY); report.SetParameterValue("P_DUMMY1", Convert.ToString(row["DUMMY1"])); report.SetParameterValue("P_DUMMY2", Convert.ToString(row["DUMMY2"])); report.SetParameterValue("P_DUMMY3", Convert.ToString(row["DUMMY3"])); // 导出单页PDF到内存流 MemoryStream singlePageStream = new MemoryStream(); report.ExportToStream(ExportFormatType.PortableDocFormat).CopyTo(singlePageStream); singlePageStream.Position = 0; // 将单页PDF加入合并文档 PdfReader reader = new PdfReader(singlePageStream); copy.AddDocument(reader); reader.Close(); report.Close(); } document.Close(); // 将合并后的PDF输出到响应 Response.ContentType = "application/pdf"; Response.AddHeader("Content-Disposition", "attachment;filename=多页报表.pdf"); Response.BinaryWrite(mergedStream.ToArray()); Response.End();
注意事项
- 方式一性能更优,是Crystal Reports的标准用法,优先推荐。
- 方式二需额外引入PDF处理库,且循环加载报表会增加服务器资源消耗,仅用于无法修改报表设计的场景。
内容的提问来源于stack exchange,提问作者Emre Kayacık
相关产品推荐
相关产品推荐

