RDLC报表(五)


        随着Visual Studio 2005中文版的推出,Microsoft汉化了MSDN的大部分内容,开发者再也不用啃英文了,本来想介绍一下LocalReport的Render方法,现在您可以到http://msdn2.microsoft.com/zh-cn/library/ms252207(VS.80).aspx获得关于这部分的详细信息。之所以以前想介绍这个方法,是因为我将想大家介绍一种在Crystal Report中无法实现的自定义票据打印纸张的方法。Anyway,现在我直接向大家介绍这种方法,可能这种方法并不是很好的,但是确实是我经过一段时间的摸索总结出来的。萝卜(http://luobos.cnblogs.com)曾经提到过的变通的方法不知道是不是我要介绍的这一种,欢迎和我进行交流!

        要想使用RDLC报表并进行页面设置,我们先来看一下LocalReport是否有类似PageSettings的类、属性、方法或事件等,我仔细找了一下,发现Microsoft.Reporting.WinForms.ReportPageSettings类具有PaperSize属性和Margin属性,但可惜的是它们都是只读的,对我们来说没有意义;另外,LocalReport具有GetDefaultPageSettings()方法,这也只能是获取当前报表的页面设置。没办法,只能采用变通的方法了。在.NET中如果想使用自定义纸张,最好的方法莫过于使用System.Drawing.Printing.PrintDocument类了,还记得我在前面提到的一个GotReportViewer的例子吗?

    private int m_currentPageIndex;
    
private IList<Stream> m_streams;

    
private Stream CreateStream(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek)
    
{
        Stream stream 
= new FileStream(name + "." + fileNameExtension, FileMode.Create);
        m_streams.Add(stream);
        
return stream;
    }


    
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;
    }


    
private void PrintPage(object sender, PrintPageEventArgs ev)
    
{
        Metafile pageImage 
= new Metafile(m_streams[m_currentPageIndex]);
        ev.Graphics.DrawImage(pageImage, ev.PageBounds);

        m_currentPageIndex
++;
        ev.HasMorePages 
= (m_currentPageIndex < m_streams.Count);
    }


    
private void Print()
    
{
        
const string printerName = "Microsoft Office Document Image Writer";

        
if (m_streams == null || m_streams.Count == 0)
            
return;

        PrintDocument printDoc 
= new PrintDocument(); 
        printDoc.PrinterSettings.PrinterName 
= printerName;
        
if (!printDoc.PrinterSettings.IsValid)
        
{
            
string msg = String.Format("Can't find printer \"{0}\".", printerName);
            Console.WriteLine(msg);
            
return;
        }

        printDoc.PrintPage 
+= new PrintPageEventHandler(PrintPage);
        printDoc.Print();
    }


    
private void Run()
    
{
        LocalReport report 
= new LocalReport();
        report.ReportPath 
= "Report.rdlc";
        report.DataSources.Add(
new ReportDataSource("Sales", LoadSalesData()));

        Export(report);

        m_currentPageIndex 
= 0;
        Print();
    }

        对,就是那个通过命令行而不是ReportViewer的GUI界面进行打印报表的例子,这个例子就使用LocalReport的Render方法将报表的内容导出为EMF图像流,然后在PrintDocument的PrintPage事件中使用时事件参数System.Drawing.Printing.PrintEventArgs类的DrawImage方法将EMF图像流输出到打印机。我在上面说的变通的方法也要使用这种方法。具体的细节将在以后的随笔中陆续给出。


        既然我们使用这种方法进行报表的打印,那么Visual Studio的控件ReportViewer的工具栏就不再符合我们的要求了。因为这个报表浏览器的工具栏上的按钮虽然可以设置属性显示或隐藏其中的一部分,但是我们却不能自己往这个工具栏上添加按钮(显然,我们需要实现自己的页面设置、预览和打印按钮),在这一点上,建议Microsoft将工具栏和报表浏览器分离,应该做得和BindingNavigator那样就好了。

        我们先设置ReportViewer控件的ShowToolBar方法为false,然后在ReportViewer控件纸上添加除页面设置、预览、打印外的应该有的按钮,像刷新、终止、导出、缩放、搜索、导航等,这些按钮的Click事件定义如下:

        /// <summary>
        
/// 获取当前时间组成的字符串,用作生成不会重复的文件名
        
/// </summary>
        
/// <returns></returns>

        private string GetTimeStamp()
        
{
            
string strRet = string.Empty;
            System.DateTime dtNow 
= Pub.DateTimeEx.ServerTime;
            strRet 
+=   dtNow.Year.ToString() +
                        dtNow.Month.ToString(
"00"+
                        dtNow.Day.ToString(
"00"+
                        dtNow.Hour.ToString(
"00"+
                        dtNow.Minute.ToString(
"00"+
                        dtNow.Second.ToString(
"00"+
                        System.DateTime.Now.Millisecond.ToString(
"000");
            
return strRet;

        }


        
/// <summary>
        
/// 导出到Excel
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

        private void toolExcel_Click(object sender, EventArgs e)
        
{

            Microsoft.Reporting.WinForms.Warning[] Warnings;
            
string[] strStreamIds;
            
string strMimeType;
            
string strEncoding;
            
string strFileNameExtension;

            
byte[] bytes = this.rptViewer.LocalReport.Render("Excel"nullout strMimeType, out strEncoding, out strFileNameExtension, out strStreamIds, out Warnings);

            
string strFilePath = @"D:\" + this.GetTimeStamp() + ".xls";

            
using (System.IO.FileStream fs = new FileStream(strFilePath, FileMode.Create))
            
{
                fs.Write(bytes, 
0, bytes.Length);
            }


            
if (Pub.WinForm.Msg.Question("报表打印: \r\n    成功导出Excel文件!" + strFilePath + "\r\n    要现在打开文件" + strFilePath + "吗?"== DialogResult.Yes)
            
{
                System.Diagnostics.Process.Start(strFilePath);
            }


        }


        
/// <summary>
        
/// 刷新报表数据
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

        private void tool刷新_Click(object sender, EventArgs e)
        
{
            
this.rptViewer.RefreshReport();
        }


        
/// <summary>
        
/// 在加载报表数据时终止报表数据的加载
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

        private void tool终止_Click(object sender, EventArgs e)
        
{
            
this.rptViewer.CancelRendering(0);
        }


        
/// <summary>
        
/// 从DrillThrough报表返回到导航页面
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

        private void tool返回_Click(object sender, EventArgs e)
        
{
            
if (this.rptViewer.LocalReport.IsDrillthroughReport)
                
this.rptViewer.PerformBack();
        }


        
/// <summary>
        
/// 回到报表的第一页
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

        private void tool第一页_Click(object sender, EventArgs e)
        
{
            
this.rptViewer.CurrentPage = 1;
        }


        
/// <summary>
        
/// 跳转到报表的最后一页
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

        private void tool最后一页_Click(object sender, EventArgs e)
        
{
            
this.rptViewer.CurrentPage = this.rptViewer.LocalReport.GetTotalPages();
        }


        
/// <summary>
        
/// 以25%的比例显示报表
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

        private void tool25_Click(object sender, EventArgs e)
        
{
            
this.rptViewer.ZoomMode = ZoomMode.Percent;
            
this.rptViewer.ZoomPercent = 25;
        }


        
/// <summary>
        
/// 以50%的比例显示报表
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

        private void tool50_Click(object sender, EventArgs e)
        
{
            
this.rptViewer.ZoomMode = ZoomMode.Percent;
            
this.rptViewer.ZoomPercent = 50;
        }


        
/// <summary>
        
/// 以100%的比例显示报表
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

        private void tool100_Click(object sender, EventArgs e)
        
{
            
this.rptViewer.ZoomMode = ZoomMode.Percent;
            
this.rptViewer.ZoomPercent = 100;
        }


        
/// <summary>
        
/// 以200%的比例显示报表
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

        private void tool200_Click(object sender, EventArgs e)
        
{
            
this.rptViewer.ZoomMode = ZoomMode.Percent;
            
this.rptViewer.ZoomPercent = 200;
        }


        
/// <summary>
        
/// 以400%的比例显示报表
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

        private void tool400_Click(object sender, EventArgs e)
        
{
            
this.rptViewer.ZoomMode = ZoomMode.Percent;
            
this.rptViewer.ZoomPercent = 400;
        }


        
/// <summary>
        
/// 将缩放模式设置为整页
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

        private void tool整页_Click(object sender, EventArgs e)
        
{
            
this.rptViewer.ZoomMode = ZoomMode.FullPage;
        }


        
/// <summary>
        
/// 将缩放模式设置为页宽
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

        private void tool页宽_Click(object sender, EventArgs e)
        
{
            
this.rptViewer.ZoomMode = ZoomMode.PageWidth;
        }


        
/// <summary>
        
/// 在报表中搜索txtSearch中的字符
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

        private void tool搜索_Click(object sender, EventArgs e)
        
{
            
if (this.txtSearch.Text.Trim() == string.Empty)
                
return;

            
this.rptViewer.Find(this.txtSearch.Text.Trim(), 1);
        }


        
/// <summary>
        
/// 搜索报表中下一处txtSearch中的字符
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

        private void tool搜索下一个_Click(object sender, EventArgs e)
        
{
            
if (this.txtSearch.Text.Trim() == string.Empty)
                
return;

            
this.rptViewer.FindNext();
        }


        
/// <summary>
        
/// 跳转到上一页
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

        private void tool上一页_Click(object sender, EventArgs e)
        
{
            
if (this.rptViewer.CurrentPage != 1)
                
this.rptViewer.CurrentPage--;
        }


        
/// <summary>
        
/// 跳转到下一页
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

        private void tool下一页_Click(object sender, EventArgs e)
        
{
            
if (this.rptViewer.CurrentPage != this.rptViewer.LocalReport.GetTotalPages())
                
this.rptViewer.CurrentPage++;
        }


        
/// <summary>
        
/// 跳转到由txt跳转中指定的页数
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

        private void tool跳转_Click(object sender, EventArgs e)
        
{
            
if (this.txt跳转.Text.Trim() == string.Empty)
                
return;

            
int intJump = 0;

            
if (System.Int32.TryParse(this.txt跳转.Text.Trim(), out intJump))
                
if (intJump <= this.rptViewer.LocalReport.GetTotalPages())
                    
this.rptViewer.CurrentPage = intJump;

        }


        待续……

        相关随笔:
                RDLC报表(一)
                RDLC报表(二)
                RDLC报表(三)
                RDLC报表(四)

       

posted @ 2006-03-03 22:28  蜡人张  阅读(56558)  评论(46编辑  收藏  举报