如何编程合并竖版与横版SSRS报表为单个可下载PDF?
实现SSRS纵向+横向报表合并为单一PDF的方案
嗨,这个需求完全可以搞定!你拆分出纵向、横向两个独立报表的思路是对的——毕竟SSRS单报表里确实没法直接混合不同页面方向,但我们可以通过编程手段把这两个报表生成的PDF合并成一个文件,给用户提供单一的下载入口。下面给你几种亲测有效的实现方案:
方案一:SSRS Web服务 + PDF合并库(最常用的编程方式)
这个方法的核心是先调用SSRS的官方Web服务,分别渲染两个报表为PDF字节流,再用PDF处理库把两个字节流合并成一个完整的PDF。推荐用C#结合iTextSharp(或iText 7)来实现,步骤如下:
- 引用必要的库:添加
Microsoft.Reporting.WebForms(用于SSRS服务调用)和iTextSharp(用于PDF合并)的NuGet包。 - 编写报表渲染方法:调用SSRS的
ReportExecutionService接口,获取两个报表的PDF字节数组。 - 合并PDF字节流:用iTextSharp读取两个PDF的页面,按顺序合并到一个新的PDF中,最后输出为下载文件。
这里给你一个简化的代码示例:
// 先封装一个渲染报表为PDF字节的辅助方法 private byte[] RenderSsrsReport(string reportPath, Dictionary<string, string> parameters = null) { var rs = new ReportExecutionService(); rs.Credentials = System.Net.CredentialCache.DefaultCredentials; rs.Url = "http://你的SSRS服务器地址/ReportServer/ReportExecution2005.asmx"; var execHeader = new ExecutionHeader(); rs.ExecutionHeaderValue = execHeader; var execInfo = rs.LoadReport(reportPath, null); // 设置报表参数(如果有的话) if (parameters != null && parameters.Count > 0) { var paramList = parameters.Select(p => new ParameterValue { Name = p.Key, Value = p.Value }).ToArray(); rs.SetExecutionParameters(paramList, "zh-CN"); } // 渲染为PDF格式 string extension, encoding, mimeType; Warning[] warnings; string[] streamIds; return rs.Render("PDF", null, out extension, out encoding, out mimeType, out warnings, out streamIds); } // 合并两个PDF并输出下载 public void DownloadCombinedReport() { // 获取纵向、横向报表的PDF字节 var portraitPdf = RenderSsrsReport("/Reports/你的纵向报表"); var landscapePdf = RenderSsrsReport("/Reports/你的横向报表"); using (var combinedStream = new MemoryStream()) { var document = new iTextSharp.text.Document(); var pdfCopy = new PdfCopy(document, combinedStream); document.Open(); // 添加纵向报表的所有页面 var portraitReader = new PdfReader(portraitPdf); for (int i = 1; i <= portraitReader.NumberOfPages; i++) { pdfCopy.AddPage(pdfCopy.GetImportedPage(portraitReader, i)); } portraitReader.Close(); // 添加横向报表的所有页面 var landscapeReader = new PdfReader(landscapePdf); for (int i = 1; i <= landscapeReader.NumberOfPages; i++) { pdfCopy.AddPage(pdfCopy.GetImportedPage(landscapeReader, i)); } landscapeReader.Close(); document.Close(); // 输出给用户下载 HttpContext.Current.Response.ContentType = "application/pdf"; HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=Combined_Report.pdf"); HttpContext.Current.Response.BinaryWrite(combinedStream.ToArray()); HttpContext.Current.Response.End(); } }
方案二:子报表+分页控制(无需额外合并代码)
如果你不想单独生成两个报表,也可以做一个主报表,通过子报表嵌套的方式实现:
- 主报表中先插入纵向子报表,设置子报表的页面方向为纵向,并且在子报表的最后一个控件后添加分页符。
- 接着插入横向子报表,设置子报表的页面方向为横向,同时勾选“在新页上显示”选项。
不过这个方法有个小坑:SSRS的页面渲染有时候会忽略子报表的页面设置,导致横向页面还是纵向显示,所以需要在子报表的“页面设置”里单独指定纸张大小和方向,并且主报表的页面设置尽量和第一个子报表保持一致。如果遇到渲染异常,还是方案一更稳定。
方案三:命令行工具合并(适合自动化场景)
如果你的部署环境允许使用命令行工具,可以先通过SSRS的rs.exe工具生成两个独立的PDF文件,再用pdftk或Ghostscript这类命令行PDF工具合并:
- 用
rs.exe生成纵向报表PDF:rs -i RenderReport.rss -s http://你的SSRS服务器地址/ReportServer -v ReportPath="/Reports/纵向报表" -v OutputFile="Portrait.pdf" - 同理生成横向报表PDF,然后用pdftk合并:
pdftk Portrait.pdf Landscape.pdf cat output CombinedReport.pdf
注意事项
- 确保两个报表使用相同的参数,避免数据不一致。
- 如果使用iTextSharp,注意版本兼容性:iText 7采用AGPL协议,商用场景需要确认版权;如果是旧项目,iTextSharp 5.x是MIT协议,更灵活。
- 合并PDF时要注意页面顺序,确保纵向页面在前,横向页面在后。
内容的提问来源于stack exchange,提问作者Sohel Pathan
相关产品推荐
相关产品推荐

