這些年的工作當中,最早是在8年前接觸到FastReport這個報表工具,從名字上來看,直譯過來就是快速報表,正所謂天下武功,唯快不破,FastReport報表早些年確實是制作報表的不二之選,8年前的工作中,涉入到了醫療行業,項目中要使用FastReport.net 打印基因檢測報告,效果確實是滿足了項目要求。
最新版FastReport.net支持.net core
雞肋的FastReport.net網頁版
回過來看,最近幾年的工作中,報表也是一直使用的是FastReport.net ,但轉到了BS端,即在網頁上打印業務單據,基本上不復雜的效果完全滿足要求,而且我還開發了基於ActiveX的控件,以解決瀏覽器上FastReport報表BS版本比較雞肋的功能,FastReport.net的網頁版本的打印是通過生成PDF文件,然后調用PDF的打印功能來實現打印,如果原生的瀏覽器打印功能,會存在着頁腳被添加一串URL地址、翻頁,定制頁不能打印的問題。通過開發FastReport.net的ActiveX控件,可以實現用戶自定義報表功能,網頁直接打印功能,指定默認打印機功能,反正跟桌面版本體驗一致的效果。但唯一的缺點是基於IE內核,因ActiveX是彌補IE的缺陷而生的一項技術,等將來有興趣了,我或許會移植該程序以支持基於Chrome瀏覽器,讓FastReport.net這個報表,不管任何瀏覽器都獲得跟桌面版本一致的體驗。
今天要分享給大家的是使用FastReport.net 2017版本而編寫的一個demo程序,並提供了示例程序下載;為何使用FastReport.net 2017,那是因為購買的授權是這個版本,當時想着該版本支持 .net core,但實際情況是該版本只是一個過渡版本,對.net core的支持有問題,官方示例程序我是沒有運行起來,於是我就變通一下,直接使用 webform方式來實現,因為該報表對webform實現支持是比較良好的,如果有朋友或公司購買了FastReport.net老版本的授權,但想要它支持.net core是行不通的,必須最新版本才行,因此可以像我這樣變通解決網頁版打印問題。
解決方法如下
1、單獨新建一個webform的網站項目,只添加報表相關文件和代碼,我們暫且將這個項目稱之為FastReport.Print,它是一個BS版本的基於FastReport.net實現打印需求的網站項目,如果您的業務單據較多,可以建很多目錄,同時將報表文件扔到相應目錄即可,只需要在代碼里面指定報表文件即可。
2、正式的網站項目,我們稱之為XXXX.Portal,在Portal某個目錄的頁面上發起打印請求,該頁面上放置一個打印按鈕,名字叫:批量打印,觸發批量打印事件后,從后台獲取到數據,然后將打印數據按報表所需要的格式Post到FastReport.Print對應的打印頁面即可。記住,一定是發送post請求,至於格式,你可以是任意的,只需要您自己能解析出來即可,將解析出來的數據,在Print項目的頁面的C#代碼里面,向FastReport.net注冊數據源即可。
示例代碼解讀
下面是aspx頁面代碼
<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %> <%@ Register assembly="FastReport.Web" namespace="FastReport.Web" tagprefix="cc2" %> <asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server"> <div> <h3><a href="https://jhrs.com" target="_blank"> jhrs.com</a> 出品 FastReport 打印功能示例</h3> </div> <div class="row"> <cc2:WebReport ID="WebReport1" runat="server" ShowCsvExport="true" ShowExports="true" /> </div> </asp:Content>
頁面代碼是一個WebReport的標簽,即FastReport的服務器端標簽,下面是后台C#代碼:
public partial class _Default : Page { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { string reportFile = Server.MapPath("/report/設備標牌.frx"); //這里為了演示,直接new一個集合,您應該從另外一個項目將數據post過來再反序列化。通過Request.Form["參數名"],將它反序列化即可。 List<SbData> list = new List<SbData>(); for (int i = 0; i < 5; i++) { list.Add(new SbData { 標題= "帝國游戲集團游戲裝備標牌", 使用科室 = "機要部" + i, 啟用日期 = DateTime.Now.AddDays(i).ToString(), 型號 = "XH34534-" + i, 序列號 = "XLH-3452" + i, 序號 = (i + 1).ToString(), 條碼 = "BH20190302002" + i, 生產廠家 = "帝國" + i + "科技有限公司", 規格 = "GGX-1" + i, 設備名稱 = "X射線髮射器", 責任人 = "趙佳仁" + i, 質保日期 = DateTime.Now.AddYears(i).ToString() }); } var dt = ToDataTable(list); WebReport1.RegisterData(dt, "設備管理標牌"); WebReport1.Report.Load(reportFile); WebReport1.Prepare(); } } /// <summary> /// 將泛型集合類轉換成DataTable /// </summary> /// <typeparam name="T">集合項類型</typeparam> /// <param name="list">集合</param> /// <returns>數據集(表)</returns> public DataTable ToDataTable<T>(IList<T> list) { List<string> propertyNameList = new List<string>(); DataTable result = new DataTable(); if (list.Count > 0) { PropertyInfo[] propertys = list[0].GetType().GetProperties(); foreach (PropertyInfo pi in propertys) { if (propertyNameList.Count == 0) { result.Columns.Add(pi.Name, pi.PropertyType); } else { if (propertyNameList.Contains(pi.Name)) result.Columns.Add(pi.Name, pi.PropertyType); } } for (int i = 0; i < list.Count; i++) { ArrayList tempList = new ArrayList(); foreach (PropertyInfo pi in propertys) { if (propertyNameList.Count == 0) { object obj = pi.GetValue(list[i], null); tempList.Add(obj); } else { if (propertyNameList.Contains(pi.Name)) { object obj = pi.GetValue(list[i], null); tempList.Add(obj); } } } object[] array = tempList.ToArray(); result.LoadDataRow(array, true); } } return result; } } public class SbData { public string 標題 { get; set; } public string 序號 { get; set; } public string 設備名稱 { get; set; } public string 規格 { get; set; } public string 型號 { get; set; } public string 啟用日期 { get; set; } public string 序列號 { get; set; } public string 生產廠家 { get; set; } public string 條碼 { get; set; } public string 責任人 { get; set; } public string 使用科室 { get; set; } public string 質保日期 { get; set; } }
上面的代碼,是一個aspx頁面后置代碼,我們可以在Page_Load事件里面接收正式項目提交過來的打印數據,建議使用json,因為你只需要直接反序列化即可,方便。然后將獲取到的值還要轉為DataTable,因為FastReport注冊數據源我這兒使用的是DataTable類型,至於其它類型,我沒有去煙酒是否正常。
FastReport.net打印網頁版運行效果一覽
網頁版的打印效果如下:
上面的報表,排版格式是很簡單的,二維碼FastReport自帶,這里不介紹使用教程,這個示例只是一個很簡單的應用,它的更多功能,可以看官方示例及源碼。
基於asp.net 的Demo源碼下載
以下提供的demo程序,下載后直接使用VS打開即可運行。
源碼下載:點擊原文鏈接進行下載