这些年的工作当中,最早是在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 = ; i < ; i++)
{
list.Add(new SbData
{
标题= "帝国游戏集团游戏装备标牌",
使用科室 = "机要部" + i,
启用日期 = DateTime.Now.AddDays(i).ToString(),
型号 = "XH34534-" + i,
序列号 = "XLH-3452" + i,
序号 = (i + ).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 > )
{
PropertyInfo[] propertys = list[].GetType().GetProperties();
foreach (PropertyInfo pi in propertys)
{
if (propertyNameList.Count == )
{
result.Columns.Add(pi.Name, pi.PropertyType);
}
else
{
if (propertyNameList.Contains(pi.Name))
result.Columns.Add(pi.Name, pi.PropertyType);
}
} for (int i = ; i < list.Count; i++)
{
ArrayList tempList = new ArrayList();
foreach (PropertyInfo pi in propertys)
{
if (propertyNameList.Count == )
{
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打开即可运行。

源码下载:点击原文链接进行下载

使用FastReport.net 报表在网页上实现打印功能的更多相关文章

  1. 网页上facebook分享功能的具体实现

    1,一个链接: 参数是要分享的页面的链接 代码如下: <a style="width:35px; height:40px; position:relative; top:10px; l ...

  2. 在Winform开发中使用FastReport创建报表

    FastReport.Net是一款适用于Windows Forms, ASP.NET和MVC框架的功能齐全的报表分析解决方案.可用在Microsoft Visual Studio 2005到2015, ...

  3. 使用FastReport报表工具实现信封套打功能

    在较早期的报表套打的时候,我倾向于使用LODOP的ActiveX进行报表的打印或者套打,BS效果还是很不错的.之前利用它在Winform程序里面实现信封套打功能,详细参考<基于信封套打以及批量打 ...

  4. “此网页上的某个 Web 部件或 Web 表单控件无法显示或导入。找不到该类型,或该类型未注册为安全类型。”

    自从vs装了Resharper,看见提示总是手贱的想去改掉它.于是乎手一抖,把一个 可视web部件的命名空间给改了. 喏,从LibrarySharePoint.WebPart.LibraryAddEd ...

  5. [moka同学收藏]网页上的“返回上一页”的几种实现代码

    我们在制作网页的时候,经常在网页上要用到"返回上一页"的功能.这一功能在制作网页的时候会有多种编码方法,在此,笔者将比较常用的几种编码写作方法在下面列出来,供各位技术人员参考使用. ...

  6. 使用chrome查看网页上效果的实现方式

    使用chrome查看网页上效果的实现方式 chrome是一个极为强大的工具,很多时候,我们不知道一个效果怎么实现的,我们完全可以找到响应的网页,然后找到其html文件,和js文件,查看源码,获得其实现 ...

  7. css015 定位网页上的元素

    css015 定位网页上的元素 一.   定位属性的功能 1.         四中类型的定位 Position: absolute relative fixed static a. 绝对定位 绝对定 ...

  8. CSS3-基于浮动的布局,响应式WEB设计,定位网页上的元素,设计打印页面的css技术

    基于浮动的布局: 1.除非图片设置了宽度,否则始终应该要对浮动的图片设置一个宽度,这样可以让浏览器给其他内容腾出环绕的空间 2.当侧边栏的高度与主内容区的高度不一致的时候,可以用个margin进行调整 ...

  9. 如何获取网页上的LOGO

    一般公司网页上的图片都会禁止右键另存为,用截图工具接下来的图会带背景色,PS成背景透明有点费时间. 用Google Chrome 或Firefox 打开目标网页,右键点击审查元素,将鼠标放在图片上,一 ...

随机推荐

  1. 关于CEdit控件的透明(重绘)

    摘自:http://www.jcwcn.com/html/VC/10_19_51_12.htm 做一个透明的Edit控件的主要问题是字符的输出,在Edit里输出的刷新有几个时机,一个是在接收到键盘或鼠 ...

  2. HTML连载8-video标签

    ​一.video标签 1.作用:播放视频 2.格式:<video src="视频地址“></video> 3.可添加的属性: (1)autoplay="au ...

  3. YARN分析系列之二 -- Hadoop YARN各个自模块说明

    先做如下声明,本代码版本是基于 3.1.2 版本. 其实,我们自己在写代码的时候,会有意识地将比较大的功能项独立成包,独立成module, 独立成项目,项目之间的关系既容易阅读理解,又便于管理. 如下 ...

  4. SpringBoot整合日志框架LogBack

    日志可以记录我们应用程序的运行情况,我们可以通过日志信息去获取应用程序更多的信息.常用处理java日志的组件有:slf4j.log4j.logback.common-logging等.其中log4j是 ...

  5. 我所理解的Vue——学习心得体会1(Vue对象)

    初学Vue,总结如下: 1.首先要区分html的dom和js的dom 2.html的dom是View的范畴,js的dom是Model的范畴. 3.vue这库就是创建了伟大的new Vue()对象,把h ...

  6. l论文查重平台

    推荐大家一个靠谱的论文检测平台.重复的部分有详细出处以及具体修改意见,能直接在文章上做修改,全部改完一键下载就搞定了.怕麻烦的话,还能用它自带的降重功能.哦对了,他们现在正在做毕业季活动, 赠送很多免 ...

  7. php+mysql新无线级分类

    create table cat( id int unsigned not null primary key auto_increment, pid , path ) not null default ...

  8. SHELL 中条件语句的运用 if for 条件测试语句

    if条件测试语句可以让脚本根据实际情况自动执行相应的命令.从技术角度来讲,if语句分为单分支结构.双分支结构.多分支结构:其复杂度随着灵活度一起逐级上升. if条件语句的单分支结构由if.then.f ...

  9. 浅谈C#泛型

    一.为什么要提出泛型的概念 我们在声明对象或者方法中,对象中成员变量的定义或者函数参数都传递都要指定具体的对象类型,但是有的时候参数的类型是变化的,但是实现的功能却又差不多,这个时候我们就想,是否存在 ...

  10. TypeScript算法与数据结构-数组篇

    数组是数据结构中最简单,也是使用最广泛的一种.在原生的js中,数组给我们提供了很多方便的操作方法,比如push(), pop(), shift(), unshift().但是出于对数据结构的学习,我们 ...