C# 報表(report)和LocalReport類如何實現打印?


    在這里與大家一起來分享下LocalReport類與報表(report)打印的使用。在做項目時候,報表打印是常常會用到的。它們是如何實現 打印的呢?今天根據自己在項目中用到的部分報表打印,再次重溫一下它們的原理。(該項目是c版 C#windows forms)

     在這里我就不在設計報表格式和其他的的內容了,根據自己的理解來給大家說下原理,若有不對還請見諒!我項目中關於報表打印的設計,還有數據源等都已經具備有的,在以下代碼中有部分是省略了的。

           //加載報表一個類 (表示不用連接到報表服務器而在本地處理和呈現的報表。)
  LocalReport report = new LocalReport();        /*
這里創建二張表dt1=rdlcbiz.Get_tj_sqdlx_hd(tjbh, tjcs)
        和dt2=rdlcbiz.Get_v_tj_tjdjb(tjbh, tjcs) 是根據方法來查詢數據得到的兩張表。
       */
DataTable dt1
= rdlcbiz.Get_tj_sqdlx_hd(tjbh, tjcs); DataTable dt2 = rdlcbiz.Get_v_tj_tjdjb(tjbh, tjcs);
       //加載報表的路徑   
report.ReportPath
= Application.StartupPath + @"/rdlcreport/Report_tjsqd.rdlc"; //以圖片顯示
report.EnableExternalImages
= true;
       /*
    這里要要注意的:根據設計報表時需要傳入參數值(ReportParameter)
ReportParameter rp1 = new ReportParameter("tjdw", str_tjdw);//第 個參數是變量,第二個參數是值

        以下代碼:是向報表Report_tjsqd.rdlc中傳入參數變量為tjdw,barcode並且把值傳進到
*/ 
ReportParameter rp1
= new ReportParameter("tjdw", str_tjdw); ReportParameter rp2 = new ReportParameter("barcode", str_path);         
       //清除之前的報表數據 
report.DataSources.Clear();
       //設置好的報表參數以數組的形式傳入
report.SetParameters(
new ReportParameter[] { rp1, rp2 });
       //獲得報表使用的數據源集合,並且添加一個構造命名的數據源集合“ReportDataSource("PEISDataSet_tj_sqdlx_hd", dt1))”
report.DataSources.Add(
new ReportDataSource("PEISDataSet_tj_sqdlx_hd", dt1)); report.DataSources.Add(new ReportDataSource("PEISDataSet_v_tj_tjdjb", dt2));        //RdlcPrintNew這是一個打印的類也調用硬件的類(一會兒會重點講)
RdlcPrintNew rdlcprint
= new RdlcPrintNew(); rdlcprint.Run(report, "報表打印名稱(可以修改)", false, "A4");//第一個參數:是本地報表,第二參數是報表打印名稱(可以修改) 第三個參數是否顯示打印設置對話框

    以上的代碼就是當我點擊打印某張報表時,調用的一個方法。里面 rdlcprint.Run(report, "報表打印名稱(可以修改)", false, "A4");這個方法就可以調硬件打印機啊。原理就是:利用LocalReport類把報表設計好,並且放在本地;再把報表中的參數和數據源,加載在指定的報表中;調用rdlcprint.Run(report, "報表打印名稱(可以修改)", false, "A4");實現打印。接下來重點講解這個方法。

using System;
using System.IO;
using System.Data;
using System.Text;
using System.Drawing.Imaging;
using System.Drawing.Printing;
using System.Collections.Generic;
using Microsoft.Reporting.WinForms;
using System.Windows.Forms;
using System.Drawing;

namespace PEIS.xtgg
{
    public class RdlcPrintNew : IDisposable
    {
      
        string PaperName = "";//紙張名字
        string PageWidth = "";//紙張寬度
        string PageHeight = "";//紙張高度
        string MarginTop = "";//上邊距
        string MarginLeft = "";//左邊距
        string MarginRight = "";//右邊距
        string MarginBottom = "";//下邊距
        string PagePrinter = "";//打印機

        private bool hxdy = false;
        int m_PageIndex = 0;//需要打印的當前頁 2012-08-14

        /// <summary>
        /// 獲取一個值,指示是否為橫向打印,默認為縱向
        /// </summary>
        public bool Hxdy
        {
            set { hxdy = value; }
        }

        /// <summary>
        /// 用來記錄當前打印到第幾頁了
        /// </summary>
        private int m_currentPageIndex;

        /// <summary>
        /// //聲明一個Stream對象的列表用來保存報表的輸出數據  
        ///LocalReport對象的Render方法會將報表按頁輸出為多個Stream對象。
        /// </summary>
        private IList<Stream> m_streams;//文件流


        ///用來提供Stream對象的函數,用於LocalReport對象的Render方法的第三個參數
        /// 提供 Stream 對象以進行呈現的 CreateStreamCallback 委托指向的方法  
        /// 這里為將報表的每一個頁面作為一個EMF圖片存放,通常用於報表呈現  
        /// </summary>  
        /// <param name="name">流的名稱</param>  
        /// <param name="fileNameExtension">創建文件流時要使用的文件擴展名</param>  
        /// <param name="encoding">指定流的字符編碼的 Encoding 枚舉器值。如果流不包含字符,則此值可能為 null。</param>  
        /// <param name="mimeType">一個包含流的 MIME 類型的 string</param>  
        /// <param name="willSeek">指示流是否需要支持查找的 Boolean 值。如果值為 false,則流將為只前推,並將按其創建順序發送到塊區中的客戶端。如果值為 true,則流可以任何順序寫入。</param>  
        /// <returns>ReportViewer 控件可以寫入數據的 Stream 對象</returns>  
        private Stream CreateStream(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek)
        {
            //如果需要將報表輸出的數據保存為文件,請使用FileStream對象。
            Stream stream = new FileStream(name + XtNumber.Name.ToString() + "." + fileNameExtension, FileMode.Create);
            m_streams.Add(stream);
            return stream;
        }


        /// <summary>
        /// 導出報表的每一個頁面到一個EMF文件   
        /// </summary>
        /// <param name="report">ReportViewer.LocalReport</param>
        /// <param name="PageName">頁面設置</param>
        private void Export(LocalReport report, string PageName)
        {
            string deviceInfo = "";

        
            if (PageName == "")//單據名稱
            {
                deviceInfo =
                   "<DeviceInfo>" +
                   "  <OutputFormat>EMF</OutputFormat>" +
                   "  <PageWidth>21cm</PageWidth>" +
                   "  <PageHeight>29.7cm</PageHeight>" +
                   "  <MarginTop>1cm</MarginTop>" +
                   "  <MarginLeft>1cm</MarginLeft>" +
                   "  <MarginRight>1cm</MarginRight>" +
                   "  <MarginBottom>1cm</MarginBottom>" +
                   "</DeviceInfo>";

            }
            else
            {
                deviceInfo =
                    "<DeviceInfo>" +
                    "  <OutputFormat>EMF</OutputFormat>" +
                    "  <PageWidth>" + PageWidth + "</PageWidth>" +
                    "  <PageHeight>" + PageHeight + "</PageHeight>" +
                    "  <MarginTop>" + MarginTop + "</MarginTop>" +
                    "  <MarginLeft>" + MarginLeft + "</MarginLeft>" +
                    "  <MarginRight>" + MarginRight + "</MarginRight>" +
                    "  <MarginBottom>" + MarginBottom + "</MarginBottom>" +
                    "</DeviceInfo>";

            }
            Warning[] warnings;
            m_streams = new List<Stream>();
            try
            {
                //report.DisplayName = PageName;//
                //將報表的內容按照deviceInfo指定的格式輸出到CreateStream函數提供的Stream中。
                report.Render("Image", deviceInfo, CreateStream, out warnings);
                report.Dispose();
            }
            catch (Exception ex)
            {
                Exception innerEx = ex.InnerException;//取內異常。因為內異常的信息才有用,才能排除問題。   
                while (innerEx != null)
                {
                    MessageBox.Show(innerEx.Message);
                    innerEx = innerEx.InnerException;
                }
            }

            foreach (Stream stream in m_streams)
            {
                stream.Position = 0;
            }
            

        }

        /// <summary>
        /// 縮略圖形的調用函數
        /// </summary>
        /// <returns></returns>
        public bool DelegateGetThumbnailImageAbort()
        {
            return false;
        }

        /// <summary>   
        /// 當前頁打印的輸出   
        /// </summary>   
        /// <param name="sender"></param>   
        /// <param name="ev"></param>   
        private void PrintPage(object sender, PrintPageEventArgs ev)
        {


            if (m_PageIndex == 0)//沒有指定頁碼打印所有的
            {
                //把數據流轉化把EMF矢量圖片 
                Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]);

//設置高質量插值法 ev.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High; //設置高質量,低速度呈現平滑程度 ev.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //在指定位置並且按指定大小繪制原圖片的指定部分 ev.Graphics.DrawImage(原始圖片, new System.Drawing.Rectangle(0, 0, 縮略圖片的寬, 縮略圖片的高), new System.Drawing.Rectangle(0, 0, 原始圖片的寬, 原始圖片的高), System.Drawing.GraphicsUnit.Pixel); ev.Graphics.DrawImage(pageImage, new System.Drawing.Rectangle(0, 0, ev.PageBounds.Width, ev.PageBounds.Height), new System.Drawing.Rectangle(0, 0, pageImage.Width, pageImage.Height), System.Drawing.GraphicsUnit.Pixel); m_currentPageIndex++; ev.HasMorePages = (m_currentPageIndex < m_streams.Count); } else//指定頁面后只打印指定頁碼 { if (m_PageIndex > m_streams.Count) { ev.HasMorePages = false;//當終止頁數大於總頁數 ev.Cancel = true; MessageBox.Show("自定義頁面填寫有誤,終止頁數不能大於總頁數,請檢查!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } while (m_currentPageIndex + 1 < m_PageIndex) { m_currentPageIndex++; } Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]); ev.Graphics.DrawImageUnscaledAndClipped(pageImage, new System.Drawing.Rectangle(0, 0, ev.PageBounds.Width, ev.PageBounds.Height)); ev.HasMorePages = false; pageImage.Dispose(); } } /// <summary> /// //用來記錄當前打印到第幾頁了 /// </summary> /// <param name="DocumentName"></param> /// <param name="DispalyPageSetupDialog"></param> private void Print(string DocumentName, bool DispalyPageSetupDialog)//"體檢指引單打印", false { if (m_streams == null || m_streams.Count == 0) { return; } PrintDocument printDoc = new PrintDocument(); printDoc.DocumentName = DocumentName; if (!PrinterExists())//檢查是否有打印機 { return; } if (PagePrinter != "")//打印機 { bool IsExists = false;//設置打印機名稱是否存在 for (int x = 0; x < PrinterSettings.InstalledPrinters.Count; x++) { if (PrinterSettings.InstalledPrinters[x].ToString() == PagePrinter) { printDoc.PrinterSettings.PrinterName = PagePrinter;//獲得打印機的名稱 IsExists = true; break; } } if (!IsExists) { MessageBox.Show("打印機:" + "" + PagePrinter + "】不存在,請聯系管理員!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } } if (PaperName != "")//紙張名稱:A4,A3 { if (!Printer.FormInPrinter(printDoc.PrinterSettings.PrinterName, PaperName))//紙張不存在自己創建 { decimal width = Convert.ToDecimal(PageWidth.Replace("cm", "")) * 10; decimal height = Convert.ToDecimal(PageHeight.Replace("cm", "")) * 10; Printer.AddCustomPaperSize(printDoc.PrinterSettings.PrinterName, PaperName, width, height); } int index = 0;//紙張的索引 bool IsExists = false;//打印機紙張是否存在該紙張名稱 for (int j = 0; j < printDoc.PrinterSettings.PaperSizes.Count; j++) { if (printDoc.PrinterSettings.PaperSizes[j].PaperName == PaperName) {
index = j; IsExists = true; break; } } if (IsExists) { printDoc.DefaultPageSettings.PaperSize = printDoc.PrinterSettings.PaperSizes[index]; } else { MessageBox.Show("" + PaperName + "】自定義紙張不存在,請聯系管理員!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } } //事件委托 printDoc.PrintPage += new PrintPageEventHandler(PrintPage); if (DispalyPageSetupDialog) { PageSetupDialog pageDialog = new PageSetupDialog(); pageDialog.Document = printDoc; if (pageDialog.ShowDialog() == DialogResult.OK) { printDoc.Print(); } } else { if (hxdy)//橫向打印 { printDoc.DefaultPageSettings.Landscape = true; } printDoc.Print(); } } /// <summary> /// 打印rdlc文件 /// </summary> /// <param name="report">本地報表</param> /// <param name="DocumentName">打印文件名稱</param> /// <param name="DispalyPageSetupDialog">是否顯示打印設置對話框</param> /// <param name="PageName">打印單據的名字</param> public void Run(LocalReport report, string DocumentName, bool DispalyPageSetupDialog, string PageName)//report, "體檢指引單打印", false, "A4" { // pw.StartThread(); if (PageName != "")//取自定義紙張大小 { xtBiz xtbiz = new xtBiz(); DataTable dt = xtbiz.Get_Xt_ggdy(PageName);//獲得到設置的紙張的大小. if (dt.Rows.Count == 1) { PaperName = dt.Rows[0]["PaperName"].ToString(); PageWidth = dt.Rows[0]["PageWidth"].ToString(); PageHeight = dt.Rows[0]["PageHeight"].ToString(); MarginTop = dt.Rows[0]["MarginTop"].ToString(); MarginLeft = dt.Rows[0]["MarginLeft"].ToString(); MarginRight = dt.Rows[0]["MarginRight"].ToString(); MarginBottom = dt.Rows[0]["MarginBottom"].ToString(); PagePrinter = dt.Rows[0]["PagePrinter"].ToString(); if (PageWidth == "") PageWidth = "0cm"; if (PageHeight == "") PageHeight = "0cm"; if (MarginTop == "") MarginTop = "0cm"; if (MarginLeft == "") MarginLeft = "0cm"; if (MarginRight == "") MarginRight = "0cm"; if (MarginBottom == "") MarginBottom = "0cm"; } else { MessageBox.Show("該單據紙張配置沒有設置,請聯系管理員!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } } Export(report, PageName);//導出報表的每一個頁面到一個EMF文件 m_currentPageIndex = 0; Print(DocumentName, DispalyPageSetupDialog);// "體檢指引單打印", false //釋放資源
Dispose();//一定釋放資源
}
/// <summary> /// 打印rdlc文件 /// </summary> /// <param name="report">本地報表</param> /// <param name="DocumentName">打印文件名稱</param> /// <param name="DispalyPageSetupDialog">是否顯示打印設置對話框</param> /// <param name="PageName">打印單據的名字</param> /// <param name="PageFw">打印單據的范圍</param> public void Run(LocalReport report, string DocumentName, bool DispalyPageSetupDialog, string PageName, string PageFw) { //pw.StartThread(); if (PageName != "")//取自定義紙張大小 { xtBiz xtbiz = new xtBiz(); DataTable dt = xtbiz.Get_Xt_ggdy(PageName); if (dt.Rows.Count == 1) { PaperName = dt.Rows[0]["PaperName"].ToString(); PageWidth = dt.Rows[0]["PageWidth"].ToString(); PageHeight = dt.Rows[0]["PageHeight"].ToString(); MarginTop = dt.Rows[0]["MarginTop"].ToString(); MarginLeft = dt.Rows[0]["MarginLeft"].ToString(); MarginRight = dt.Rows[0]["MarginRight"].ToString(); MarginBottom = dt.Rows[0]["MarginBottom"].ToString(); PagePrinter = dt.Rows[0]["PagePrinter"].ToString(); if (PageWidth == "") PageWidth = "0cm"; if (PageHeight == "") PageHeight = "0cm"; if (MarginTop == "") MarginTop = "0cm"; if (MarginLeft == "") MarginLeft = "0cm"; if (MarginRight == "") MarginRight = "0cm"; if (MarginBottom == "") MarginBottom = "0cm"; } else { MessageBox.Show("該單據紙張配置沒有設置,請聯系管理員!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } }
       //導出報表的每一個頁面到一個EMF文件  
Export(report, PageName);
if (PageFw == "") { m_currentPageIndex = 0; Print(DocumentName, DispalyPageSetupDialog);
} else { string[] str_fw = PageFw.Split('-'); int begin = 0; int end = 0; try { if (str_fw.Length == 1) { begin = Convert.ToInt32(str_fw[0]); end = Convert.ToInt32(str_fw[0]); } else { begin = Convert.ToInt32(str_fw[0]); end = Convert.ToInt32(str_fw[1]); } if (begin > end) { MessageBox.Show("該單據自定義打印頁數填寫有誤,請檢查!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } } catch { MessageBox.Show("該單據自定義打印頁數填寫有誤,請檢查!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } for (int i = begin; i <= end; i++) { m_PageIndex = i; m_currentPageIndex = 0; Print(DocumentName, DispalyPageSetupDialog); //pw.StopThread(); } } //釋放資源 Dispose(); } /// <summary> /// 釋放資料源
/// </summary> public void Dispose() { if (m_streams != null) { foreach (Stream stream in m_streams) stream.Close(); m_streams = null; } } /// <summary> /// 判斷系統中是否存在打印機 /// </summary> /// <returns>TRUE:存在打印機;FALSE:不存在打印機</returns> private bool PrinterExists() { PrinterSettings.StringCollection snames = PrinterSettings.InstalledPrinters; foreach (string s in snames) { if (s.ToLower().Trim() == s.ToLower().Trim()) { return true; } }

MessageBox.Show("沒找到打印機!\n只有安裝了打印機才能進行打印", "沒找到打印機", MessageBoxButtons.OK, MessageBoxIcon.Warning); return false; } } }

     這樣就可以調用硬件的打印機啊。。里面的原理就是:把之前設計好的報表參數和數據源加載裝填好之后調用該方法,這個方法做了什么呢?它就是把這個本地報表將輸出的數據保存為文件( Stream stream = new FileStream(name + XtNumber.Name.ToString() + "." + fileNameExtension, FileMode.Create);),再次把數據流轉化把EMF矢量圖片並且保存放在本地( Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]);),在指定位置並且按指定大小繪制原圖片的指定部分 (注意重點: 一不小心打印出就會出問題,所以要注意這個方法的使用“ev.Graphics.DrawImage(原始圖片, new System.Drawing.Rectangle(0, 0, 縮略圖片的寬, 縮略圖片的高), new System.Drawing.Rectangle(0, 0, 原始圖片的寬, 原始圖片的高), System.Drawing.GraphicsUnit.Pixel);”),相當於矢量圖片縮略為系統設置的值。如:A4、A3等。然后就調用 “Print(DocumentName, DispalyPageSetupDialog);"就可ok 了。
     

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM