此文出現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>
<html xmlns="
http://www.w3.org/1999/xhtml">
<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;
}
================================ 效果圖。。 ![]() ![]() |