• ReportViewer 不预览,直接导出 PDF文件


    作为笔记记着,以免以后再到处找资料

    1. 在不预览的情况下导出文件

    先看一个方法说明,想知道ReportViewer支持导出哪些文件类型,在Render方法说明中就有描述

    //
    // Summary:
    // Processes the report and renders it in the specified format using a stream
    // provided by a callback function.
    //
    // Parameters:
    // format:
    // The format in which to render the report. This argument maps to a rendering
    // extension. Supported formats include Excel, PDF, Word, and Image. To access
    // the list of available rendering extensions, use the Microsoft.Reporting.WinForms.LocalReport.ListRenderingExtensions()
    // method.
    //
    // deviceInfo:
    // An XML string that contains the device-specific content that is required
    // by the rendering extension specified in the format parameter. For more information
    // about device information settings for specific output formats, see fe718939-7efe-4c7f-87cb-5f5b09caeff4
    // Device Information Settings in SQL Server Books Online.
    //
    // createStream:
    // A Microsoft.Reporting.WinForms.CreateStreamCallback delegate function that
    // will be used to provide a System.IO.Stream object for rendering.
    //
    // warnings:
    // [out] An array of Microsoft.Reporting.WinForms.Warning objects that describes
    // any warnings that occurred during report processing and rendering.
    public void Render(string format, string deviceInfo, CreateStreamCallback createStream, out Warning[] warnings);

    调用方法Microsoft.Reporting.WinForms.LocalReport.ListRenderingExtensions()就知道了,如果要把支持导出的文件类型列表显示出来,这个方法就是必须的,但是我没试过。

    下面的代码主要是参数msdn的例子:https://msdn.microsoft.com/zh-cn/library/ms252091(v=vs.110).aspx

    测试例子时,没用他的数据源

    抄下代码运行,发现没有像他说的那样导出文件,然后看了下源码,发现他只把文件写进MemoryStream对象,并没看到将其输出到文件的代码,于是补充了点代码,把内存里的

    输出到文件中,然后定义了个ExportFileType枚举,又添加了一个ExportToFile方法,其他代码与示例相同

    打印的代码我不关心,所以没理他

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using System.IO;
    using System.Data;
    using Microsoft.Reporting.WinForms;
    using System.Drawing.Printing;
    using System.Drawing.Imaging;
    using System.Drawing;
    namespace PrintLocalReport
    {
        public enum ExportFileType
        {
            PDF
        }
       public class ReportViewerPrinter:IDisposable
       {
           private int m_currentPageIndex = 0;
           private IList<Stream> m_streams;
    
      
    private Stream CreateStream(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek) { Stream stream = new MemoryStream(); m_streams.Add(stream); return stream; } public void ExportToFile(LocalReport report,string targetPath, ExportFileType fileType) { Export(report, targetPath, fileType); } private void Export(LocalReport report, string targetPath, ExportFileType fileType) { string deviceInfo = @"<DeviceInfo> <OutputFormat>EMF</OutputFormat> </DeviceInfo>";
           //根据我的测试,这里的参数会覆盖rdlc中定义的参数,所以我尝试删除了,发现删除了行为是可预期的,是正确的
           //如果需要,这里可以实现定制化了
    //<PageWidth>8.5in</PageWidth> //<PageHeight>11in</PageHeight> //<MarginTop>0.25in</MarginTop> //<MarginLeft>0.25in</MarginLeft> //<MarginRight>0.25in</MarginRight> //<MarginBottom>0.25in</MarginBottom> Warning[] warnings; m_streams = new List<Stream>(); report.Render(fileType.ToString(), deviceInfo, CreateStream, out warnings); int bufferLength = 1024; byte[] buffer = new byte[bufferLength]; using (FileStream fs = new FileStream(targetPath, FileMode.CreateNew, FileAccess.Write)) { foreach (Stream stream in m_streams) { stream.Position = 0; MemoryStream ms = stream as MemoryStream; int readLength = 0; while (true) { readLength = ms.Read(buffer, 0, bufferLength); if (readLength == 0) break; fs.Write(buffer, 0, readLength); } } } } private void PrintPage(object sender, PrintPageEventArgs ev) { Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]); 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.Wheat, adjustedRect); ev.Graphics.DrawImage(pageImage, adjustedRect); m_currentPageIndex++; ev.HasMorePages = (m_currentPageIndex < m_streams.Count); } 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(); } } public void Dispose() { if (m_streams != null) { foreach (Stream stream in m_streams) { stream.Close(); } m_streams = null; } } } }

    调用代码如下

     static void Main(string[] args)
            {
    
                LocalReport report = new LocalReport();
                report.ReportPath = @"....
    eport.rdlc";
            //这个tablename要和rdlc指定的数据源名字一致,有多少个数据源挨着挨着添加 report.DataSources.Add(new ReportDataSource("tablename", LoadSalesData()));
            //这里是定义的参数,也挨着挨着添加 IList<ReportParameter> list = new List<ReportParameter>() { new ReportParameter("paramName","ParamVale") }; report.SetParameters(list.ToArray()); try { new ReportViewerPrinter().ExportToFile(report, "test.pdf", ExportFileType.PDF); } catch (Exception ex) { } }

    2. 后台导出的代码很简单,主要纠结的地方是在绘制报表的时候

    主要是两个问题:

    1. 导出到pdf文件后,本来是一页的内容,他纵向劈开,在pdf中分成两页显示了

    2.把导出的pdf文件拿去打印,在打印的时候最后一页除了页眉页脚,中间区域是空白的,而pdf中没有这一页(真他妈奇怪)

    这两个问题的原因都是报表的尺寸问题,不超宽,他就不会纵向劈开,不超高,他就不会有空白页,我设置如下解决了这两个问题

    我的报表设置的Paper size是 A4 21cm 29.7cm ,Margins 都为0 (右键报表设计界面的黑色区域(也就是非报表绘制区域),选择Report Properties 属性)

    鼠标左键点击报表绘制区域,打开Properties窗口,属性窗口中也有一个Size属性,这个是报表绘制的宽度

    这里的宽度和高度加上Paper size的Margins值 要小于等于Paper size属性的高度宽度

    我的设置是Width:21cm,Height:10cm

    即时上面设置没问题,如果打印机的设置有问题,打印的最终效果也会有差异,但是我不需要打印,所以没纠结他。

    3.推荐个工具,做过ui的可能或者基本都知道,FSCapture,很好用,美工的mark图出的不好时,要做出1:1的ui,就得靠自己了,这次做报表也多亏他。1:1真的很烦。

    部署:

    记录一下部署遇到的问题,其实就是依赖的动态库没弄全

    官方部署方案:https://msdn.microsoft.com/zh-cn/library/ms251723.aspx

    里面说:运行 ReportViewer.exe 时,以下文件安装在部署计算机上的全局程序集缓存文件夹中

    • Microsoft.ReportViewer.Common.dll

    • Microsoft.ReportViewer.ProcessingObjectModel.dll

    • Microsoft.ReportViewer.WebForms.dll

    • Microsoft.ReportViewer.WinForms.dll

    • Microsoft.ReportViewer.DataVisualization.dll

     这个说明上面的库是ReportViewer的依赖项,他说了会部署在GAC中,那就从GAC中把他拷贝出来,GAC中拷贝只能使用shell命令

    如果有VS开发环境,默认安装的话,上面的库就已经打到GAC中了,不是的话就得安装ReportViewer.exe 

    如果不是开发环境,下面安装官方说的ReportViewer.exe,安装主要是为了提取动态库

    ReportViewer.exe 下载地址提供一个:https://www.microsoft.com/en-us/download/details.aspx?id=35747

    安装他的时候,要是没有system clr types for sql server 2012,会无法安装,真他的操蛋,说明ReportViewer对SqlServer还有依赖

    于是找,链接来了:https://www.microsoft.com/en-us/download/details.aspx?id=29065

    但是我特么的下载的是一个txt文档,没鸟他,我直接去在我的开发电脑的GAC里面找Sql Server相关的库,把名字带SqlServer全拷贝出来,和上面的动态库一起,打包,放到一个没环境的电脑上,成功了运行了,然后一个一个试试,最后发现有Misrosoft.SqlServer.Types.dll就能导出成功,

    下一步就是资源包,官方文档提到了:

    ReportViewer 控件本地化为十种 Visual Studio 语言:简体中文、繁体中文、法语、德语、意大利语、日语、朝鲜语、葡萄牙语(巴西)、俄语和西班牙语。

    因为程序是全球提供,要求统一为英语,娘的,为毛没有英语包,这不科学,难道默认就是英语,这也不科学(本地化这块一点不熟悉,才接触),不过由于后台导出,没有窗口,除了表格图片,其他全是报

    表数据,所以有不有语言包也无所谓

    运行 ReportViewer.exe 时,以下文件安装在部署计算机上的全局程序集缓存文件夹中

  • 相关阅读:
    《思帝乡·春日游》——[唐]韦庄
    《临江仙·梦后楼台高锁》——[宋]晏几道
    《西江月·夜行黄沙道中》——辛弃疾
    CentOS7 安装 MySQL 5.7.10
    CentOS6 下安装JDK7
    Makefile基础
    CentOS6 下Vim安装和配置
    CentOS6 下MySQL option file
    CentOS6 下编译安装 MySQL 5.6.26
    slice和substring的区别
  • 原文地址:https://www.cnblogs.com/maoyuanwai/p/5823390.html
Copyright © 2020-2023  润新知