ReportViewer下的RDLC(二)

 

ReportViewer下的RDLC(一) 

http://blog.csdn.net/dnfon/article/details/7673081


今天,分享下ReportViewer"后台打印"的实现方法!

至于,怎么自定义批量打印,我后面仅提供下我自己的实现方法.不过,可实现的方法很多!

首先,给出微软官方的解决方案:

http://msdn.microsoft.com/zh-cn/library/ms252091%28v=vs.100%29.aspx

而且,如果有这方面需求的朋友,应该都这网上搜索过,网上的帖子,基本都是复制粘贴的微软源码,有的把注释翻译了一下!

是不是不好用啊,格式错乱有木有?

其实,微软给出的解决方案,确实能解决这个后台打印的问题.

而且,我也是用的这个方案.不过,我稍微做了点修改!

咱们先看这部分代码:

private void Export(LocalReport report)
     {
         string deviceInfo =
           @"<DeviceInfo>
                 <OutputFormat>EMF</OutputFormat>
                 <PageWidth>8.5in</PageWidth>
                 <PageHeight>11in</PageHeight>
                 <MarginTop>0.25in</MarginTop>
                 <MarginLeft>0.25in</MarginLeft>
                 <MarginRight>0.25in</MarginRight>
                 <MarginBottom>0.25in</MarginBottom>
             </DeviceInfo>";
         Warning[] warnings;
         m_streams = new List<Stream>();
         report.Render("Image", deviceInfo, CreateStream,
            out warnings);
         foreach (Stream stream in m_streams)
             stream.Position = 0;
     }


 

这个强行做了报表的页宽,页高和上下左右的边距设置.

然后,将报表的内容按照deviceInfo指定的格式输出到CreateStream函数提供的Stream中。

这里就有了个小问题,我们自己实现的报表,上面的这些边距设置,都是早就固定好的.

所以,只要和上面代码不同边距设置的,打印后,格式就全乱套了.

当然,也可以手动编码为和报表一样的设置,但是你要是有几十张报表,累死你,而且,也不便于维护.

直接给大家,看我修改后的代码:

 

这下通用了!其中,"EMF"可以理解为,文件后缀名.

这样就解决了报表的设置问题.

但是,微软给出的解决方案里,还有个问题,可能有朋友实验的时候,碰到了!

就是,这个方案,只能打印纵向单据,打不了横向的(或者说,报表的第一页,打不了横向的).

大家看这里:


 

private void Print()
     {
         if (m_streams == null || m_streams.Count == 0)
             throw new Exception("Error: no stream to print.");
         PrintDocument printDoc = new PrintDocument();
         if (!printDoc.PrinterSettings.IsValid)
         {
             throw new Exception("Error: cannot find the default printer.");
         }
         else
         {
             printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
             m_currentPageIndex = 0;
             printDoc.Print();
         }
     }


 

这里的"printDoc"没有相关的打印设置(或者说,没有提高可操作的参数).

下面是我修改后的.

private void PrintSetting()
 {
     if (m_streams == null || m_streams.Count == 0)
         throw new Exception("错误:没有检测到打印数据流");
     //声明PrintDocument对象用于数据的打印
     PrintDocument printDoc = new PrintDocument();
     //判断指定的打印机是否可用
     if (!printDoc.PrinterSettings.IsValid)
     {
         throw new Exception("错误:找不到打印机");
     }
     else
     {
         //设置打印机方向遵从报表方向
         printDoc.DefaultPageSettings.Landscape = isLandSapces;
         //声明PrintDocument对象的PrintPage事件,具体的打印操作需要在这个事件中处理。
         printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
         m_currentPageIndex = 0;
         //执行打印操作,Print方法将触发PrintPage事件。
         printDoc.Print();
     }
 }


 

//设置打印机方向遵从报表方向printDoc.DefaultPageSettings.Landscape = isLandSapces;

其中"isLandSapces"是我这个类中,定义的一个全局bool值.

问题就来了,这个isLandSapces是根据什么取得值?

/// <summary>
 /// 为Report.rdlc创建本地报告加载数据,输出报告到.emf文件,并打印,同时释放资源www.it165.net
 /// </summary>
 /// <param name="rv">参数:ReportViewer.LocalReport</param>
 public void PrintStream(LocalReport lr)
 {
      //获取LocalReport中的报表页面方向
      isLandSapces = lr.GetDefaultPageSettings().IsLandscape;
      Export(lr);
     PrintSetting();
     Dispose();
 }


 

这是我在类中添加的一个方法!

对,这个isLandSapces,就是取自ReportViewer.LocalReport,这个bool值,你用来加载报表的ReportViewer控件是肯定知道的,把它传递进来,就OK了!

下面给出完整的后台打印代码:


 

View Code 
 using System;
 using System.Collections.Generic;
 using System.Drawing;
 using System.Drawing.Imaging;
 using System.Drawing.Printing;
 using System.IO;
 using System.Text;
 using Microsoft.Reporting.WinForms;
 
 namespace HYC.RDLC
 {
     public class ReportViewer_Stream_Print : IDisposable
     {
         /// <summary>
         /// 用来记录当前打印到第几页了
         /// </summary>
         private int m_currentPageIndex;
 
         /// <summary>
         /// 声明一个Stream对象的列表用来保存报表的输出数据,LocalReport对象的Render方法会将报表按页输出为多个Stream对象。
         /// </summary>
         private IList<Stream> m_streams;
 
         private bool isLandSapces = false;
 
         /// <summary>
         /// 用来提供Stream对象的函数,用于LocalReport对象的Render方法的第三个参数。
         /// </summary>
         /// <param name="name"></param>
         /// <param name="fileNameExtension"></param>
         /// <param name="encoding"></param>
         /// <param name="mimeType"></param>
         /// <param name="willSeek"></param>
         /// <returns></returns>
         private Stream CreateStream(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek)
         {
             //如果需要将报表输出的数据保存为文件,请使用FileStream对象。
             Stream stream = new MemoryStream();
             m_streams.Add(stream);
             return stream;
         }
 
         /// <summary>
         /// 为Report.rdlc创建本地报告加载数据,输出报告到.emf文件,并打印,同时释放资源
         /// </summary>
         /// <param name="rv">参数:ReportViewer.LocalReport</param>
         public void PrintStream(LocalReport rvDoc)
         {
             //获取LocalReport中的报表页面方向
             isLandSapces = rvDoc.GetDefaultPageSettings().IsLandscape;
             Export(rvDoc);
             PrintSetting();
             Dispose();
         }
 
         private void Export(LocalReport report)
         {
             string deviceInfo =
             @"<DeviceInfo>
                 <OutputFormat>EMF</OutputFormat>
             </DeviceInfo>";
             Warning[] warnings;
             m_streams = new List<Stream>();
             //将报表的内容按照deviceInfo指定的格式输出到CreateStream函数提供的Stream中。
             report.Render("Image", deviceInfo, CreateStream, out warnings);
             foreach (Stream stream in m_streams)
                 stream.Position = 0;
         }
 
         private void PrintSetting()
         {
             if (m_streams == null || m_streams.Count == 0)
                 throw new Exception("错误:没有检测到打印数据流");
             //声明PrintDocument对象用于数据的打印
             PrintDocument printDoc = new PrintDocument();
             //判断指定的打印机是否可用
             if (!printDoc.PrinterSettings.IsValid)
             {
                 throw new Exception("错误:找不到打印机");
             }
             else
             {
                 //设置打印机方向遵从报表方向
                 printDoc.DefaultPageSettings.Landscape = isLandSapces;
                 //声明PrintDocument对象的PrintPage事件,具体的打印操作需要在这个事件中处理。
                 printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
                 m_currentPageIndex = 0;
                 //执行打印操作,Print方法将触发PrintPage事件。
                 printDoc.Print();
             }
         }
 
         /// <summary>
         /// 处理程序PrintPageEvents
         /// </summary>
         /// <param name="sender"></param>
         /// <param name="ev"></param>
         private void PrintPage(object sender, PrintPageEventArgs ev)
         {
             //Metafile对象用来保存EMF或WMF格式的图形,
             //我们在前面将报表的内容输出为EMF图形格式的数据流。
             Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]);
 
             //调整打印机区域的边距www.it165.net
             Rectangle adjustedRect = new Rectangle(
                 ev.PageBounds.Left - (int)ev.PageSettings.HardMarginX,
                 ev.PageBounds.Top - (int)ev.PageSettings.HardMarginY,
                 ev.PageBounds.Width,
                 ev.PageBounds.Height);
 
             //绘制一个白色背景的报告
             //ev.Graphics.FillRectangle(Brushes.White, adjustedRect);
 
             //获取报告内容
             //这里的Graphics对象实际指向了打印机
             ev.Graphics.DrawImage(pageImage, adjustedRect);
             //ev.Graphics.DrawImage(pageImage, ev.PageBounds);
 
             // 准备下一个页,已确定操作尚未结束
             m_currentPageIndex++;
 
             //设置是否需要继续打印
             ev.HasMorePages = (m_currentPageIndex < m_streams.Count);
         }
 
         public void Dispose()
         {
             if (m_streams != null)
             {
                 foreach (Stream stream in m_streams)
                     stream.Close();
                 m_streams = null;
             }
         }
     }
 }


 

调用方法:

ReportViewer_Stream_Print rvsp = new ReportViewer_Stream_Print();
rvDoc.LocalReport.ReportEmbeddedResource = string.Format("项目名称.Report.{0}.rdlc", reportname);
rvsp.PrintStream(rvDoc.LocalReport);

后台打印完成!

自定义批量打印:

其实,这个就是用上面的调用方法,

然后,遍历一组报表名称,传递给其中的"reportname"参数!

这个组可以是一维数组,也可以是二维数组,[0]里记录报表名称,[1]里记录打印份数!

当然,也不一定非是数组,方法多多!

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值