MVC+RDLC報表+PrintPreviewDialog(winform控件)打印、打印預覽?!


 此文出現MVC,就是網頁上調用winform打印控件PrintPreviewDialog,好詭異,出線了! 
好了,開始。。。。
首先你要做一個報表:RDLC (微軟的東東)
圖片

當然這個微軟的RDLC需要配置一個數據源xsd(不用鏈接數據庫,我這就是手動在數據源里面創建個table對象而已),
圖片
然后需要一個aspx頁面來顯示這個報表
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="TongJi.aspx.cs" Inherits="Jaya.Web.Reports.TongJi" ValidateRequest="false" %>
 
<%@ Register Assembly="Microsoft.ReportViewer.WebForms, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" Namespace="Microsoft.Reporting.WebForms" TagPrefix="rsweb" %>
 
<!DOCTYPE html>
 
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:DropDownList ID="DropDownList1" runat="server" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">
            <asp:ListItem Value="100" Text="100"></asp:ListItem>
            <asp:ListItem Value="80" Text="80"></asp:ListItem>
            <asp:ListItem Value="50" Text="50"></asp:ListItem>
            <asp:ListItem Value="30" Text="30"></asp:ListItem>
        </asp:DropDownList>
        <div id="mainPanel" style=" overflow-x: hidden; height: 680px; border-left: 1px solid scrollbar;">
            <asp:Button ID="Button13" runat="server" Text="打印" OnClick="Button2_Click" />
            <asp:Button ID="Button1" runat="server" Text="刷新" OnClick="Button7_Click" />
            <asp:Button ID="Button2" runat="server" Text="首頁" OnClick="Button8_Click" />
            <asp:Button ID="Button3" runat="server" Text="上一頁" OnClick="Button9_Click" />
            <asp:Button ID="Button4" runat="server" Text="下一頁" OnClick="Button10_Click" />
             <asp:Button ID="Button5" runat="server" Text="尾頁" OnClick="Button11_Click" />
             <asp:Button ID="Button6" runat="server" Text="導出EXCEL" OnClick="Button5_Click" />
             <asp:Button ID="Button7" runat="server" Text="導出圖片" OnClick="Button4_Click" />
             <asp:Button ID="Button8" runat="server" Text="導出PDF" OnClick="Button3_Click" />
             <asp:Button ID="Button9" runat="server" Text="導出WORD" OnClick="Button6_Click" />
             
            <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
            <rsweb:ReportViewer ID="ReportViewer1" runat="server" Font-Names="Verdana" Font-Size="8pt" WaitMessageFont-Names="Verdana" WaitMessageFont-Size="14pt" Width="680px" Height="670px">
                <LocalReport ReportPath="Reports\rep_examroom.rdlc">
                </LocalReport>
            </rsweb:ReportViewer>
 
        </div>
    </form>
</body>
</html>

-----------------------華麗的分割線 上面是前台代碼 下面是后台代碼------------------------

 
    public enum FileType
    {
 
        PDF = 0,
        Image = 1,
        Excel = 2,
        Word = 3
    }
   
    public partial class TongJi : System.Web.UI.Page
    {
        DataTable dt1 = null;
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                string rpath;
                Hashtable ht = new Hashtable();
                DataTable dt = GetData(out rpath, ref ht);
 
                ReportDataSource rds = new ReportDataSource("DataSet1", dt);//真數據源
                ReportViewer1.LocalReport.DataSources.Clear();
                ReportViewer1.LocalReport.DataSources.Add(rds);
                List<ReportParameter> rps = new List<ReportParameter>();
                foreach (var item in ht.Keys)//自定義報表需要的參數
                {
                    ReportParameter rp1 = new ReportParameter(item.ToString(), ht[item].ToString());
                    rps.Add(rp1);
                }
                //ReportParameter rp1 = new ReportParameter("kskm", "123");
                //ReportParameter rp2 = new ReportParameter("rq", "123");
                ReportViewer1.LocalReport.SetParameters(rps.ToArray());
                ReportViewer1.LocalReport.ReportPath = "Reports\\" + rpath + ".rdlc";//rep_examroom
                ReportViewer1.LocalReport.Refresh();
                ReportViewer1.DataBind();
            }
 
        }
        private DataTable GetData(out string rpath, ref Hashtable ht)
        {
            string jsondata = Request["jsondata"];//必傳數據json
            rpath = Request["rpath"];//必傳數據報表路徑
 
            foreach (string key in Request.QueryString.AllKeys)//自定義參數
            {
                if (key != "rpath" && key != "jsondata")
                {
                    ht.Add(key, Request[key].ToString());
                }
            }
 
 
            DataTable dt = Common.CuryHelp.JsonToDataTable(jsondata);//json字符串轉換DataTable對象
            return dt;
 
        }
 
        /// <summary>
        /// 打印
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Button2_Click(object sender, EventArgs e)
        {
            string rpath;
            Hashtable ht = new Hashtable();
            DataTable dt2 = GetData(out rpath, ref ht);
            new PrintHelp().Run(AppDomain.CurrentDomain.BaseDirectory + "\\Reports\\" + rpath + ".rdlc", dt2, "DataSet1", ht);
 
        }
 
        /// <summary>
        /// 刷新
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Button7_Click(object sender, EventArgs e)
        {
            this.ReportViewer1.LocalReport.Refresh();
 
        }
 
        /// <summary>
        /// 首頁
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Button8_Click(object sender, EventArgs e)
        {
            this.ReportViewer1.CurrentPage = 1;
 
        }
        /// <summary>
        /// 上一頁
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Button9_Click(object sender, EventArgs e)
        {
            if (this.ReportViewer1.CurrentPage != 1)
            {
                this.ReportViewer1.CurrentPage--;
 
            }
        }
        /// <summary>
        /// 下一頁
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Button10_Click(object sender, EventArgs e)
        {
            if (this.ReportViewer1.CurrentPage != this.ReportViewer1.LocalReport.GetTotalPages())
            {
                this.ReportViewer1.CurrentPage++;
 
            }
        }
 
        /// <summary>
        /// 尾頁
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Button11_Click(object sender, EventArgs e)
        {
            this.ReportViewer1.CurrentPage = this.ReportViewer1.LocalReport.GetTotalPages();
        }
        
        /// <summary>
        /// 縮放
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.ReportViewer1.ZoomMode = ZoomMode.Percent;
            this.ReportViewer1.ZoomPercent = Convert.ToInt32(this.DropDownList1.SelectedValue);
        }
        protected void Button3_Click(object sender, EventArgs e)
        {
            ExportFile(FileType.PDF, "out.pdf");
        }
 
        protected void Button4_Click(object sender, EventArgs e)
        {
            ExportFile(FileType.Image, "out.jpeg");//這里可以使用任意的圖片格式  只要修改out.jpeg為其他格式的名字就可以了
        }
 
        protected void Button5_Click(object sender, EventArgs e)
        {
            ExportFile(FileType.Excel, "out.xls");
        }
 
        protected void Button6_Click(object sender, EventArgs e)
        {
            ExportFile(FileType.Word, "out.doc");
        }
 
        #region 導出文件
        private void ExportFile(FileType ft, string filename)
        {
            CreateFile(ft, filename);
 
            string strPath = Server.MapPath(filename);
            DownloadFile(strPath, filename);
        }
 
        private void CreateFile(FileType ft, string filename)
        {
            Warning[] warnings;
            string[] streamids;
            string mimeType;
            string encoding = "utf-8";
            string extension;
 
            byte[] bytes = this.ReportViewer1.LocalReport.Render(ft.ToString(), null, out mimeType,
                           out encoding, out extension, out streamids, out warnings);
 
            FileStream fs = new FileStream(HttpContext.Current.Server.MapPath(filename), FileMode.Create);
            fs.Write(bytes, 0, bytes.Length);
            fs.Close();
            fs.Dispose();
        }
 
        public void DownloadFile(string path, string name)
        {
            try
            {
                System.IO.FileInfo file = new System.IO.FileInfo(path);
                Response.Clear();
                Response.Charset = "utf-8";
                Response.ContentEncoding = System.Text.Encoding.UTF8;
                // 添加頭信息,為"文件下載/另存為"對話框指定默認文件名
                Response.AddHeader("Content-Disposition", "attachment; filename=" + Server.UrlEncode(name));
                // 添加頭信息,指定文件大小,讓瀏覽器能夠顯示下載進度
                Response.AddHeader("Content-Length", file.Length.ToString());
                // 指定返回的是一個不能被客戶端讀取的流,必須被下載
                Response.ContentType = "application/octet-stream";
                // 把文件流發送到客戶端
                Response.WriteFile(file.FullName);
                // 停止頁面的執行 
                HttpContext.Current.ApplicationInstance.CompleteRequest();
            }
            catch (Exception ex)
            {
                Response.Write("<script>alert('系統出現以下錯誤://n" + ex.Message + "!//n請盡快與管理員聯系.')</script>");
            }
        }
        #endregion
    } 

 -----------------------------------------------是不是有點多,沒關系 無腦復制即可 有錯就刪掉它!----------
需要一個幫助類 已經封裝好 (當然你也可以根據自己需要修改擴展):
 /// <summary>
    /// PrintHelp 的摘要描述
    /// </summary>
    public class PrintHelp
    {
 
 
        private int m_currentPageIndex;
        private IList<Stream> m_streams;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="reportPath">報表路徑</param>
        /// <param name="printerName">打印機名稱(使用默認打印機,不賦值)</param>
        /// <param name="dt1">報表數據源1</param>
        /// <param name="dt1SourceName">報表中數據源1對應名稱</param>
        /// <param name="dt2">報表數據源2</param>
        /// <param name="dt2SourceName">報表中數據源2對應名稱</param>
        public void Run(string reportPath, string printerName, DataTable dt1, string dt1SourceName, DataTable dt2, string dt2SourceName, bool isHindeLogo)
        {
            LocalReport report = new LocalReport();
            report.ReportPath = reportPath;//加上報表的路徑
            report.DataSources.Add(new ReportDataSource(dt1SourceName, dt1));
            report.DataSources.Add(new ReportDataSource(dt2SourceName, dt2));
            report.EnableExternalImages = true;
            ReportParameter rp = new ReportParameter("isHindeLogoImg", isHindeLogo.ToString());//這里我在報表里弄的參數
            report.SetParameters(rp);
            Export(report);
            m_currentPageIndex = 0;
            Print(printerName);
        }
//我用的是下面這個方法  方法按自己的需要去修改封裝
        public void Run(string reportPath,  DataTable dt1, string dt1SourceName,Hashtable ht )
        {
            LocalReport report = new LocalReport();
            report.ReportPath = reportPath;//加上報表的路徑
            report.DataSources.Add(new ReportDataSource(dt1SourceName, dt1));
            report.EnableExternalImages = true;
            List<ReportParameter> rps = new List<ReportParameter>();
            foreach (var item in ht.Keys)
            {
                ReportParameter rp1 = new ReportParameter(item.ToString(), ht[item].ToString());
                rps.Add(rp1);
            }
            report.SetParameters(rps);
            Export(report);
            m_currentPageIndex = 0;
            Print("");
        }
        private void Export(LocalReport report)
        {
            string deviceInfo =
              "<DeviceInfo>" +
              "  <OutputFormat>EMF</OutputFormat>" +
              "  <PageWidth>210mm</PageWidth>" +
              "  <PageHeight>297mm</PageHeight>" +
              "  <MarginTop>5mm</MarginTop>" +
              "  <MarginLeft>10mm</MarginLeft>" +
              "  <MarginRight>10mm</MarginRight>" +
              "  <MarginBottom>5mm</MarginBottom>" +
              "</DeviceInfo>";//這里是設置打印的格式 邊距什么的
            Warning[] warnings;
            m_streams = new List<Stream>();
            try
            {
                report.Render("Image", deviceInfo, CreateStream, out warnings);//一般情況這里會出錯的  使用catch得到錯誤原因  一般都是簡單錯誤
            }
            catch (Exception ex)
            {
                Exception innerEx = ex.InnerException;//取內異常。因為內異常的信息才有用,才能排除問題。
                while (innerEx != null)
                {
                    //MessageBox.Show(innerEx.Message);
                    string errmessage = innerEx.Message;
                    innerEx = innerEx.InnerException;
                }
            }
            foreach (Stream stream in m_streams)
            {
                stream.Position = 0;
            }
        }
 
        private Stream CreateStream(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek)
        {
            //name 需要進一步處理
            Stream stream = new FileStream(name + DateTime.Now.Millisecond + "." + fileNameExtension, FileMode.Create);//為文件名加上時間
            m_streams.Add(stream);
            return stream;
        }
 
        private void Print(string printerName)
        {
            //string printerName = this.TextBox1.Text.Trim();// "傳送至 OneNote 2007";
            if (m_streams == null || m_streams.Count == 0)
                return;
            PrintDocument printDoc = new PrintDocument();
            // string aa = printDoc.PrinterSettings.PrinterName;
            if (printerName.Length > 0)
            {
                printDoc.PrinterSettings.PrinterName = printerName;
            }
            foreach (PaperSize ps in printDoc.PrinterSettings.PaperSizes)
            {
                if (ps.PaperName == "A4")
                {
                    printDoc.PrinterSettings.DefaultPageSettings.PaperSize = ps;
                    printDoc.DefaultPageSettings.PaperSize = ps;
                    // printDoc.PrinterSettings.IsDefaultPrinter;//知道是否是預設定的打印機
                }
            }
            if (!printDoc.PrinterSettings.IsValid)
            {
                string msg = String.Format("Can't find printer " + printerName);
                System.Diagnostics.Debug.WriteLine(msg);
                return;
            }
            printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
            PrintPreview(printDoc);//這個地方測試打印預覽 這個地方很詭異 他會在網頁上彈出winform 有木有? 當然這個窗口在網頁后面,需要alt+tab切一下看到啦(藏得深,怕你找不到)。。。。
            //printDoc.Print();//這地方是直接打印 放開注釋就是直接去打印機打印啦
 
 
        }
        //下面是測試用的三種打印預覽 都是winform控件哦
        private void RuntimeDialog(PrintDocument pDoc)
        {
            PrintPreviewDialog pPDlg;
            pPDlg = new PrintPreviewDialog();
            pPDlg.Document = pDoc;
            pPDlg.WindowState = FormWindowState.Normal;//設置窗口
            pPDlg.PrintPreviewControl.Zoom = 1.0;//設置百分比大小
            pPDlg.PrintPreviewControl.Columns = 1;
          
            pPDlg.ShowDialog();
            //pPDlg.Dispose();
        }
        private void PrintPreviewControl(PrintDocument pDoc)
        {
            Form formPreview = new Form();
            PrintPreviewControl previewControl = new PrintPreviewControl();
            previewControl.Document = pDoc;
          
            previewControl.StartPage = 1;
            formPreview.WindowState = FormWindowState.Normal;
 
            formPreview.Controls.Add(previewControl);
            formPreview.Controls[0].Dock = DockStyle.Fill;
            formPreview.ShowDialog();
            //formPreview.Dispose();
        }
        private void PrintPreview(PrintDocument pDoc)
        {
            PrintPreviewDialog pPDlg;
            pPDlg = new PrintPreviewDialog();
            PrintPreviewControl previewControl = new PrintPreviewControl();
            //設置頁面的預覽的頁碼 
            //設置顯示頁面顯示的大小(也就是原頁面的倍數) 
            pPDlg.PrintPreviewControl.StartPage = 0;
            pPDlg.PrintPreviewControl.Zoom = 1.0;
            //設置或返回窗口狀態,即該窗口是最小化、正常大小還是其他狀態。 
            pPDlg.WindowState = FormWindowState.Maximized;
            //設置和獲取需要預覽的文檔 
            //將窗體顯示為指定者的模式對話框 
            pPDlg.Document = pDoc;
            pPDlg.ShowDialog();
        }
     
        private void PrintPage(object sender, PrintPageEventArgs ev)
        {
            Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]);
            ev.Graphics.DrawImage(pageImage, 0, 0, 827, 1169);//設置打印尺寸 單位是像素
            m_currentPageIndex++;
            ev.HasMorePages = (m_currentPageIndex < m_streams.Count);
        }
      
    } 
======================好了 下面開始MVC部分
需要一個視圖  然后寫一個ajax 去后台獲取數據(相信這部分都會把) 然后拿到數據后 用js拼接一個iframe把上面的那個aspx頁面嵌套到你的mvc頁面中來,具體可以參考下面代碼(其中用到了json字符串地址欄傳輸,到那邊可以用一個方法把json字符串轉換城DataTable),下面提供轉換代碼。注意我封裝后的傳參(可以修改自己需要的,下面代碼僅供參考,無腦復制肯定不行的)
有幾個重要參數:rpath是調用的報表文件名稱,jsondata是需要傳送的數據(可以理解為真數據源),其它都是自定義參數,按照你報表上需要的參數自己設置。
(至於后台如何把數據轉換json傳到前台,別的日志里面有,至於前台怎么把json對象轉換成json字符串,請使用JSON2.js) 
 
    function chaxun() {
        var _cd1 = $('#d1').val();
        var _cd2 = $('#d2').val();
        if (_cd1 != "" && _cd2 != "") {
            $.post('/Drv_statistics/TJ_ExamRoomPost', { kskm: $('#_km').val(), d1: _cd1, d2: _cd2 }, function (data) {
                //接收參數
                var _d1 = data.Date1;
                var _d2 = data.Date2;
                //組織報表需要變量
                var _km = data.KM;
                var _rq = _d1 + " 至 " + _d2;
                //要使用的報表名稱
                var _rpath = "rep_examroom";
                //報表要使用的數據
                var str_json = JSON.stringify(data.JData);
                var strhtml = "<iframe width='700' height='650' id='' src='/Reports/TongJi.aspx?rpath=" + _rpath + "&kskm=" + _km + "&rq=" + _rq + "&jsondata=" + str_json + "'  frameborder='no' border='0' marginwidth='0' marginheight='0' scrolling='no' allowtransparency='yes' style='overflow:hidden;height:700px'></iframe>";
                $('#_ifmdiv').html(strhtml);
            })
        }
    } 
==================================== json to DataTable
 /// <summary>
        /// 將json轉換為DataTable
        /// </summary>
        /// <param name="strJson">得到的json</param>
        /// <returns></returns>
        public static DataTable JsonToDataTable(string strJson)
        {
            //轉換json格式
            strJson = strJson.Replace(",\"", "*\"").Replace("\":", "\"#").ToString();
            //取出表名   
            var rg = new Regex(@"(?<={)[^:]+(?=:\[)", RegexOptions.IgnoreCase);
            string strName = rg.Match(strJson).Value;
            DataTable tb = null;
            //去除表名   
            strJson = strJson.Substring(strJson.IndexOf("[") + 1);
            strJson = strJson.Substring(0, strJson.IndexOf("]"));
 
            //獲取數據   
            rg = new Regex(@"(?<={)[^}]+(?=})");
            MatchCollection mc = rg.Matches(strJson);
            for (int i = 0; i < mc.Count; i++)
            {
                string strRow = mc[i].Value;
                string[] strRows = strRow.Split('*');
 
                //創建表   
                if (tb == null)
                {
                    tb = new DataTable();
                    tb.TableName = strName;
                    foreach (string str in strRows)
                    {
                        var dc = new DataColumn();
                        string[] strCell = str.Split('#');
 
                        if (strCell[0].Substring(0, 1) == "\"")
                        {
                            int a = strCell[0].Length;
                            dc.ColumnName = strCell[0].Substring(1, a - 2);
                        }
                        else
                        {
                            dc.ColumnName = strCell[0];
                        }
                        tb.Columns.Add(dc);
                    }
                    tb.AcceptChanges();
                }
 
                //增加內容   
                DataRow dr = tb.NewRow();
                for (int r = 0; r < strRows.Length; r++)
                {
                    dr[r] = strRows[r].Split('#')[1].Trim().Replace(",", ",").Replace(":", ":").Replace("\"", "");
                }
                tb.Rows.Add(dr);
                tb.AcceptChanges();
            }
 
            return tb;
        }
================================ 效果圖。。
  圖片


免責聲明!

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



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