VB.NET下ReportViewer打印SSRS报表仅出第一页的完整解决方案请求
SSRS报表打印仅输出第一页的完整解决方案(VB.NET/C#)
问题场景
在Windows窗体中使用ReportViewer组件,通过VB.NET代码直接打印SSRS报表时,仅能打印第一页,现有代码片段如下:
现有VB.NET代码片段
Try doc = New Printing.PrintDocument() AddHandler doc.PrintPage, AddressOf PrintPageHandler doc.DefaultPageSettings.Landscape = False Dim deviceInfo As String = "<DeviceInfo>" & "<OutputFormat>emf</OutputFormat>" & " <PageWidth>8.3in</PageWidth>" & " <PageHeight>11.7in</PageHeight>" & " <MarginTop>0.14in</MarginTop>" & " <MarginLeft>0.22in</MarginLeft>" & " <MarginRight>0.22in</MarginRight>" & " <MarginBottom>0.14in</MarginBottom>" & " <StartPage>0</StartPage>" & " <EndPage>10</EndPage>" & "</DeviceInfo>" Dim warnings() As Microsoft.Reporting.WinForms.Warning Dim streamids() As String Dim mimeType As String, encoding As String, filenameExtension As String mimeType = "" : encoding = "" : filenameExtension = "" Dim data() As Byte data = ReportViewer1.ServerReport.Render("Image", deviceInfo, mimeType, encoding, filenameExtension, streamids, warnings) pages.Add(New Metafile(New MemoryStream(data))) For Each pageName As String In streamids data = ReportViewer1.ServerReport.RenderStream("Image", pageName, deviceInfo, mimeType, encoding) pages.Add(New Metafile(New MemoryStream(data))) Next doc.Print() Catch ex As Exception ' 异常处理 End Try
Private Sub PrintPageHandler(ByVal sender As Object, ByVal e As PrintPageEventArgs) fnName = "PrintPageHandler" Try Dim page As Metafile = pages(pageIndex) pageIndex += 1 Dim pWidth As Integer = 827 Dim pHeight As Integer = 1100 e.Graphics.DrawImage(page, 0, 0, pWidth, pHeight) e.HasMorePages = pageIndex < pages.Count Catch ex As Exception ' 异常处理 End Try End Sub
问题根源
- 状态未正确重置:
pageIndex未在打印前重置为0,多次打印会导致起始索引错误;pages集合未清空,可能残留旧页面数据。 - 页面范围限制:原
deviceInfo中固定设置<EndPage>10</EndPage>,若报表页数不足或超出此范围会导致打印异常。 - 事件重复绑定:未移除旧的
PrintPage事件处理器,多次触发会引发逻辑混乱。
VB.NET完整解决方案
' 类级别变量声明 Private pages As New List(Of Metafile)() Private pageIndex As Integer = 0 Private doc As Printing.PrintDocument Private Sub PrintSSRSReport() Try ' 重置打印状态,避免旧数据干扰 pages.Clear() pageIndex = 0 doc = New Printing.PrintDocument() ' 先移除旧事件处理器,防止重复绑定 RemoveHandler doc.PrintPage, AddressOf PrintPageHandler AddHandler doc.PrintPage, AddressOf PrintPageHandler doc.DefaultPageSettings.Landscape = False ' 设备信息配置:EndPage设为-1表示打印所有页面 Dim deviceInfo As String = "<DeviceInfo>" & "<OutputFormat>emf</OutputFormat>" & "<PageWidth>8.3in</PageWidth>" & "<PageHeight>11.7in</PageHeight>" & "<MarginTop>0.14in</MarginTop>" & "<MarginLeft>0.22in</MarginLeft>" & "<MarginRight>0.22in</MarginRight>" & "<MarginBottom>0.14in</MarginBottom>" & "<StartPage>0</StartPage>" & "<EndPage>-1</EndPage>" & "</DeviceInfo>" Dim warnings() As Microsoft.Reporting.WinForms.Warning Dim streamids() As String Dim mimeType As String = "", encoding As String = "", filenameExtension As String = "" ' 渲染第一页 Dim data() As Byte = ReportViewer1.ServerReport.Render("Image", deviceInfo, mimeType, encoding, filenameExtension, streamids, warnings) pages.Add(New Metafile(New MemoryStream(data))) ' 渲染剩余所有页面 For Each pageName As String In streamids data = ReportViewer1.ServerReport.RenderStream("Image", pageName, deviceInfo, mimeType, encoding) pages.Add(New Metafile(New MemoryStream(data))) Next ' 执行打印 doc.Print() Catch ex As Exception MessageBox.Show("打印失败:" & ex.Message) End Try End Sub Private Sub PrintPageHandler(ByVal sender As Object, ByVal e As PrintPageEventArgs) Try ' 无剩余页面则终止打印 If pageIndex >= pages.Count Then e.HasMorePages = False Return End If Dim page As Metafile = pages(pageIndex) pageIndex += 1 ' 按打印页面实际尺寸绘制,避免固定尺寸导致失真 Dim pageRect As New Rectangle(0, 0, e.PageBounds.Width, e.PageBounds.Height) e.Graphics.DrawImage(page, pageRect) ' 判断是否还有后续页面 e.HasMorePages = pageIndex < pages.Count Catch ex As Exception MessageBox.Show("打印页处理失败:" & ex.Message) e.HasMorePages = False End Try End Sub
C#完整解决方案
// 类级别变量声明 private List<Metafile> pages = new List<Metafile>(); private int pageIndex = 0; private PrintDocument doc; private void PrintSSRSReport() { try { // 重置打印状态 pages.Clear(); pageIndex = 0; doc = new PrintDocument(); // 移除旧事件处理器,防止重复绑定 doc.PrintPage -= PrintPageHandler; doc.PrintPage += PrintPageHandler; doc.DefaultPageSettings.Landscape = false; // 设备信息配置:EndPage设为-1表示打印所有页面 string deviceInfo = @"<DeviceInfo> <OutputFormat>emf</OutputFormat> <PageWidth>8.3in</PageWidth> <PageHeight>11.7in</PageHeight> <MarginTop>0.14in</MarginTop> <MarginLeft>0.22in</MarginLeft> <MarginRight>0.22in</MarginRight> <MarginBottom>0.14in</MarginBottom> <StartPage>0</StartPage> <EndPage>-1</EndPage> </DeviceInfo>"; Warning[] warnings; string[] streamids; string mimeType = "", encoding = "", filenameExtension = ""; // 渲染第一页 byte[] data = reportViewer1.ServerReport.Render("Image", deviceInfo, out mimeType, out encoding, out filenameExtension, out streamids, out warnings); pages.Add(new Metafile(new MemoryStream(data))); // 渲染剩余所有页面 foreach (string pageName in streamids) { data = reportViewer1.ServerReport.RenderStream("Image", pageName, deviceInfo, out mimeType, out encoding); pages.Add(new Metafile(new MemoryStream(data))); } // 执行打印 doc.Print(); } catch (Exception ex) { MessageBox.Show($"打印失败:{ex.Message}"); } } private void PrintPageHandler(object sender, PrintPageEventArgs e) { try { if (pageIndex >= pages.Count) { e.HasMorePages = false; return; } Metafile page = pages[pageIndex]; pageIndex++; // 按打印页面实际尺寸绘制 Rectangle pageRect = new Rectangle(0, 0, e.PageBounds.Width, e.PageBounds.Height); e.Graphics.DrawImage(page, pageRect); // 判断是否还有后续页面 e.HasMorePages = pageIndex < pages.Count; } catch (Exception ex) { MessageBox.Show($"打印页处理失败:{ex.Message}"); e.HasMorePages = false; } }
关键修复点
- 将
deviceInfo中的<EndPage>设为-1,自动适配报表所有页数。 - 每次打印前清空
pages集合并重置pageIndex,确保打印状态干净。 - 增加事件处理器的移除逻辑,避免重复绑定导致的异常。
- 按打印页面的实际边界绘制报表,避免固定尺寸引发的失真或截断问题。
内容的提问来源于stack exchange,提问作者PrakNHS
相关产品推荐
相关产品推荐

