FineReport 填报报表数据自定义提交
今年7月分刚毕业,8月中旬入职一家刚起步不久的小公司。在这之前还在一家在国内比较著名的集团分公司研发中心呆过一个月,感觉不是我喜欢做的工作,于是果断辞职。我想大概我是那家公司入职最短的员工吧,还不满一个月。来到新的东家,便跟着项目经理接手一个已经做了一部分的项目,该项目主要是收集、处理和展示数据。其中使用到了FineReport 这个报表工具,这个报表工具的确是很强大,在业内也是具有良好的口碑的。我觉得,软件就是用来解决现实生活中的问题的,只要能解决我的问题,它就很好。好了,不废话,直接进入正题。
在报表中填好的数据如何入库呢?该工具提供了两种方式入库:内置SQL和自定义提交。我没有使用内置SQL, 因为我收集的数据需要经过后台方法过滤,所以选择了自定义提交。在此项目中,我为该自定义提交分了两种方式:非grid式和grid式;
非grid:对应的数据表只有一张,即单表操作,所有填报的数据就一条记录。这种情况的提交方式比较简单,直接简单地配置属性和属性值即可提交到后台处理。在一般开发中实体的属性和数据库表的字段是一致的,我们公司要求一致(大写)。以下是报表填报属性的自定义提交配置图:
图 1
从图中可以看到,名字就是你的实体属性,而值就是要从单元格中取来的。这里有8种取法供你选择,如下图所示,我一般使用单元格和公式,而且公式也是我在grid式报表的主要取值手段。
图 2
对于单元格,你填报的数据在哪个格子上,就直接该格子对应的坐标即可,就跟Excel一样,例如:F13。对于公式,我们可以使用报表工具提供的公式方便地对要取的数据做一些预处理,以便后台进行处理,比如:CONCATENATE(C7,D7,E7,F7,G7,H7,I7,J7,K7,L7,M7,N7),表示拼接C7~N7这个些格子的值,并返回一个字符串。当然,你也可以在公式中直接输入格子的坐标来拼接,比如需要使用‘-’来拼接,直接在公式中输入:U15+'-'+V15+'-'+W15即可。
现在需要提交的数据配置好了,那么就需要将这些数据提交到后台处理了。在图 1中,有没有看到需要配置一个类,对!这个类就是用来接收你要提交的数据的。所以你需要自定义一个类并继承该报表工具提供的一个父类 TotalSubmitJob,实现该类的方法doTotalJob。以下是部分代码:
protected void doTotalJob(Data data, Calculator calculator)throws Exception {//一次提交可能含有多条记录JSONArray ja = new JSONArray();for (int i = 0; i < data.getRowCount(); i++) { // getRowCount 获取一共多少行数据Map<String, Object> result_map = new HashMap<String, Object>();for (int j = 0; j < data.getColumnCount(); j++) {Object value = data.getValueAt(i, j); // 获取对应位置的值if (value instanceof JobValue) {JobValue ce = (JobValue) value;value = ce.getValue(); // 通过JobValue的getValue方法获得单元格的值}/** 网格式报表 得到的value 可能有 FArray和"{....}"格式数据。模版上做了特殊配置。* 非网格式的报表每次得到的数据为普通字符串* */if(value instanceof FArray){FArray fArray = (FArray)value;List list = fArray.toList();JSONArray jsonArr = new JSONArray();for(int k = 0; k < list.size(); k++){jsonArr.add(JSONObject.fromObject(list.get(k)));}value = jsonArr;} else if(String.valueOf(value).startsWith("{") && String.valueOf(value).endsWith("}")){JSONArray jsonArr = new JSONArray();jsonArr.add(JSONObject.fromObject(value));value = jsonArr;} else { //表单式报表 现在不需要做任何处理,}result_map.put(data.getColumnName(j), value);}//System.out.println(JSONObject.fromObject(result_map).toString());ja.add(JSONObject.fromObject(result_map));}//特殊处理如表311的值json,对于表111报表式的报表将JSONArray-->JSONObjectJSONObject jo = JsonobjMerger(ja.toString());
//省略之后的代码
}
我们可以从 data 这个参数中取得我们需要的数据,至于取得的数据的状态是什么样的,想了解具体细节的可参考: 点击打开链接,将取到的数据放到一个JSONArray中。然而在这个JSONArray中对于grid式的报表可能存在重复数据,所将其合并返回一个JSONObject。
private JSONObject JsonobjMerger(String jsonStr) {JSONArray jsonArr = JSONArray.fromObject(jsonStr);JSONObject jsonObj = new JSONObject();for (int i = 0; i < jsonArr.size(); i++) {JSONObject jo = jsonArr.getJSONObject(i);if (jsonObj.size() == 0) {jsonObj = jo;} else {for (Object keyObj : jo.keySet()) {String key = keyObj + "";if (jo.get(key) instanceof JSONArray) {JSONArray tempJa = JSONArray.fromObject(jo.get(key));for (int j = 0; j < tempJa.size(); j++) {if (jsonObj.containsKey(key)) {if (jsonObj.getJSONArray(key).indexOf(tempJa.get(j)) == -1) {jsonObj.accumulate(key, tempJa.get(j));}} else {jsonObj.accumulate(key, tempJa);}}} else {jsonObj.accumulate(key, jo.get(key));}}}}return jsonObj;}
所以对于非grid式的报表,就可以处理入库。
//非网格式填报报表if(jo.containsKey("table_index")) {jo = processMainData(jo);String table_index = (String) jo.remove("table_index");//补充报表式报表中缺少的数据,例如:创建人,创建时间等if(VTools.StringIsNullOrSpace((String)jo.get("ID"))) {jo.remove("ID");jo.put("ID", VTools.getNewUUID());}jo.put("CREATE_USER", "");jo.put("CREATE_TIME", VTools.getTimeNow("yyyy-MM-dd HH:mm:ss"));jo.put("STATE", "1");jo.put("AUTH_USER", "");jo.put("AUTH_USER", "");jo.put("AUTH_TIME", "");jo.put("MORGID", "");ISession session = SessionFactory.openSession();session.getTransaction().begin();saveHBRReportOfMain(table_index, jo, session); //利用反射设置实体属性session.getTransaction().commit();DBUtil.closeSession(session);}
对于grid式的报表,处理在属性配置上的公式配置有所不同之外,其后台思路大致是一样的。这种类型的报表一般设计为主-子表。我们先来看属性配置:如图3-1、图3-2所示:
图 3-1
图3-2
其关键点在于grid式报表一个属性(某些特殊属性除外)对应一个实体(一条记录)。所以需要将此种属性的值配置成图3-2所示,将属性和属性值拼接成JSON文本即可。其取值直接输入该格子对应的坐标即可。将数据传递到后台方法中,通过JsonobjMerger方法合并重复的项,利用反射设置数据,入库即可。以下是关键代码:
if(jo.containsKey("ISGRID")) { //判断是否是网格式报表JSONArray joA = jo.getJSONArray("ISGRID");String isTrue = joA.getJSONObject(0).getString("ISGRID");String main_id = null;if("true".equalsIgnoreCase(isTrue)) {ISession session = SessionFactory.openSession();session.getTransaction().begin();String table_index = null;//取得MAIN_ID和表索引table_indexif(jo.containsKey("MAIN_ID") && jo.containsKey("table_index")) {JSONArray jo_mainId = jo.getJSONArray("MAIN_ID");main_id = jo_mainId.getJSONObject(0).getString("MAIN_ID");JSONArray jo_tableIndex = jo.getJSONArray("table_index");table_index = jo_tableIndex.getJSONObject(0).getString("table_index");String table_index_item = table_index.split("_")[0];JSONArray jo_version = jo.getJSONArray("VERSION");String versionId = jo_version.getJSONObject(0).getString("VERSION");if(VTools.StringIsNullOrSpace(main_id) && !VTools.StringIsNullOrSpace(table_index_item)) {main_id = VTools.getNewUUID();//生成主表信息JSONObject jo_main = new JSONObject();jo_main.put("ID", main_id);jo_main.put("CREATE_USER", "");jo_main.put("CREATE_TIME", VTools.getTimeNow("yyyy-MM-dd HH:mm:ss"));jo_main.put("STATE", "1");jo_main.put("AUTH_USER", "");jo_main.put("AUTH_USER", "");jo_main.put("AUTH_TIME", "");jo_main.put("MORGID", "");jo_main.put("VERSION", versionId);saveHBRReportOfMain(table_index_item, jo_main, session);} }//操作子表//将josn对象中附件的信息去掉,只保留实体相关的数据jo.remove("ISGRID");jo.remove("MAIN_ID");jo.remove("table_index");jo.remove("VERSION");List entityList = null;if(jo.size() > 0) {entityList = new ArrayList();Set keySet = jo.keySet();Iterator ite = keySet.iterator();String className_item = "com.wisdragon.stdb.entity.STDB_HBR" + table_index;while (ite.hasNext()) {Object obj = ite.next();if(jo.get(obj) instanceof JSONArray) {JSONArray ja_temp = JSONArray.fromObject(jo.get(obj));for (int i = 0; i < ja_temp.size(); i++) {JSONObject jo_temp = ja_temp.getJSONObject(i);Class<?> clazz_temp = Class.forName(className_item);entityList.add(bind(clazz_temp, jo_temp));}}}//保存或更新子表saveHBRReportOfItem(main_id, entityList, session); //反射设置属性}session.getTransaction().commit();DBUtil.closeSession(session);} }
FineReport 填报报表数据自定义提交相关推荐
- FineReport填报报表
二次确认,删除行: 参考: JS实现删除时二次确认- FineReport帮助文档 - 全面的报表使用教程和学习资料 JS实现记录填报操作- FineReport帮助文档 - 全面的报表使用教程和学习 ...
- 帆软报表填报自定义提交-后台数据解析保存详解
帆软报表填报前期步骤按api或者百度就可以完成,今天我这里着重讲解自定义提交(访问web后台服务进行提交). 填报提交有两种方式: 1)内置SQL:没什么难度,按教程来就行. 2)自定义提交:对应后台 ...
- 近期要做填报报表,使用Spreadsheet还是Finereport?
又是忙碌的五月呀~~近期接到一个项目,是一家商贸公司需要去采集销售部门的销售业绩据, 以往他们使用Excel表格线下去做报表填报,传统的报表体系效率低,文件杂,汇总难.下级部门上传数据需要以多个表格来 ...
- Web报表工具FineReport填报界面键盘操作
2019独角兽企业重金招聘Python工程师标准>>> 对于一张填报数据较多的报表,需要用户频繁地操作鼠标.而FineReport填报界面除去按钮类型的控件,其余可以完全使用键盘而不 ...
- 【FineReport】--填报报表
制作流程 填报报表,就是对数据集的增删改. 控件类型 行式填报报表 行式填报报表,就是在行市报表中,增加了写入和删除功能 制作行式填报报表 数据集:select * from S产品 limit 5 ...
- 帆软报表自定义提交以及单行提交
自定义提交 描述: 在平常的报表开发中,有时需要将提交按钮放到自己想要的区域,或者自定义一个提交按钮,亦或是逐行提交.那么这些功能怎么去实现呢?下面分享一下我自己的敬仰! 一,自定义提交整个报表 选中 ...
- FineReport 报表数据根据下拉框的值进行数据联动
FineReport 报表数据根据下拉框的值进行数据联动,不用点击查询按钮 1.新建数据库查询,获得数据. SELECT * FROM [销量] where 地区 ='${area}' 2.把需要展示 ...
- 帆软填报--行式填报报表
帆软填报 准备 下载帆软设计器,自己注册账号,获取激活码 定义数据连接,分为测试库和生产库两个 配置帆软填报MySQL库测试环境 测试 帆软库建表 登录测试开发工作目录 为模板指定数据集 为模板添加数 ...
- 纵有倚天剑还要屠龙刀,实现Power BI报表服务器自定义认证
纵有倚天剑还要屠龙刀,实现Power BI报表服务器自定义认证 文章目录 纵有倚天剑还要屠龙刀,实现Power BI报表服务器自定义认证 概述 如何实现 配置部署和Demo 排错 总结 概述 在Pow ...
最新文章
- 几个数判断大小_许栩原创2020读书笔记2《魔鬼数学》:极小数的两倍仍然是极小数...
- spring系列-注解驱动原理及源码-spring容器创建流程
- UVA12325Zombie's Treasure Chest 宝箱
- python# 完成“剪刀石头布游戏”:
- 印度软件开发人员_我如何辍学并在19岁时在印度找到了一份开发人员的工作
- c语言 强制转换 作用域,C语言之总结1详解
- 统计学 贾俊平 笔记
- 局域网稳定性测试软件,局域网速度测试
- java计算机毕业设计智能外包管理平台源码+数据库+系统+lw文档
- 5G时代到底会发生什么
- CCF CSP 201609-2 火车购票 C++实现 100分
- 看片神器人人视频APP突遭下架:上亿用户慌了!
- 黑苹果详细安装教程-基于OpenCore官网指导-UPUPMO(macOS Monterey)
- 解决eclipse中java各类中文乱码问题
- Java判断字符串是否为数字(正负、小数)
- 2021-11-11
- 六,基于FPGA的高速串行通信GTX知识梳理
- 使用Jobs之创建jobs
- 【BLE】蓝牙抓包器 Ellisys 使用说明
- 我的创作纪念日-从写作到阿里云专家博主的故事