知方号

知方号

帆软报表填报自定义提交

帆软报表填报自定义提交

帆软报表填报前期步骤按api或者百度就可以完成,今天我这里着重讲解自定义提交(访问web后台服务进行提交)。

填报提交有两种方式: 1)内置SQL:没什么难度,按教程来就行。

2)自定义提交:对应后台服务进行数据处理保存。

自定义提交大致分为以下几个步骤:

1)编写自定义帆软接收类(上图的Fill类)

自定义接收类我这里以ReportFillDataHandler类为例,继承TotalSubmitJob(可以一次处理多行数据),话不多说直接上代码

public class ReportFillDataHandler extends TotalSubmitJob{ private static final String SUFFIN_IN = "-NN"; protected JobValue hiddenLineNum;// 指定不保存入库的行号所存放的单元格,单元格中行号以逗号分隔,如:5,13 protected JobValue sortTable; //指定表执行的先后顺序,格式:类名-顺序编号,从小到大排序,以逗号分隔 protected boolean removeRepeat; //是否去点重复数据 protected List delIndex = new ArrayList(); //纪录删除行索引 protected List flagNameList; //保存定义成“单元格”或“常量”变量名,不再读取数据 protected HashMap hideColMap = new HashMap(); protected boolean removeNotNull; //对于propertyCode-NN形式的非空字段,如果值为空则忽略掉 private static ApplicationContext ac; static { ServletContext servletContext = ContextLoader.getCurrentWebApplicationContext().getServletContext(); ac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext); } @Override protected void doTotalJob(Data data, Calculator calculator) throws Exception { //初始化参数 initPara(); //初始化flagNameList flagNameList = new ArrayList(); flagNameList.add("hiddenLineNum"); flagNameList.add("SortTable"); flagNameList.add("removeRepeat"); flagNameList.add("removeNotNull"); //获取隐藏行号 if (hiddenLineNum != null && !"".equals(hiddenLineNum.getValue())) { for (String hstr: hiddenLineNum.getValue().toString().split(",")) { hideColMap.put(hstr,hstr); } } //预处理 preProcess(data); //读取数据集 Map sheets = new HashMap();//报表数据集,格式: try { readDataSet(sheets,data); } catch (Exception ex) { ex.printStackTrace(); throw new WriteSubmitException("保存失败:" + ex.getMessage()); } //表排序,用sortTable中带有序号的表名替换原表名 if (sortTable != null && !"".equals(sortTable.getValue())) { String[] tableSorts = sortTable.getValue().toString().split(","); String[] tbAndNum = null; for (String tableSort: tableSorts) { if (tableSort == null && "".equals(tableSort)) { continue; } tbAndNum = tableSort.split("-"); if (tbAndNum.length < 2) { continue; } if (sheets.get(tbAndNum[0]) != null) { sheets.put(tableSort,sheets.get(tbAndNum[0])); sheets.remove(tbAndNum[0]);//去除原数据 } } } //去重 if (removeRepeat) { sheets = getNewSheetMap(sheets); } //去除非空字段为null的行 if (removeNotNull) { sheets = removeNullField(sheets); } //其他处理 sheets = afterProcess(sheets); System.out.println("最终数据:"+sheets.toString()); String result = JSON.toJSONString(sheets); System.out.println("最终数据jsonResult:"+result); //调用入库服务接口---开始后台数据保存 ReportFillUtils reportFillUtils = (ReportFillUtils) ac.getBean("reportcenter.utils.reportFillUtils"); reportFillUtils.reportDataCommit(sheets); } /** * 初始化公共参数,由于帆软不能实例化父类中的JobValue,故提供子类给父类赋值的变通方式 */ protected void initPara() {} /** * 解析获取数据集前进行处理,供子类覆盖实现过程 */ private void preProcess(Data data) {} /** 从AbstractTotalJob.Data读取数据到Map中,这是默认实现,如有特殊需求在子类覆盖即可 * @param sheets * @param data */ private void readDataSet(Map sheets, Data data) throws Exception { List rows; //行数据 String[] keyArray; //表名和字段名的拆分数组 String returnRes = ""; for (int i = 0; i < data.getColumnCount(); i++) { //如果是标识列就跳过 if (flagNameList.indexOf(data.getColumnName(i)) > -1) { continue; } //字段属性名必须包含- keyArray = data.getColumnName(i).toString().split("-"); if (keyArray.length < 2) { throw new Exception("模板列" + data.getColumnName(i).toString() + "配置格式不正确"); } if (!sheets.containsKey(keyArray[0])) { rows = new ArrayList(); sheets.put(keyArray[0],rows); } else { rows = sheets.get(keyArray[0]); } returnRes = fullRowsByColumn(data,i,rows); if (!"".equals(returnRes)) { throw new Exception(returnRes); } } } /** 根据某列填充行信息的默认实现,子类可重写*/ private String fullRowsByColumn(Data data, int column, List rows) { try { HashMap tempHideMap = (HashMap) hideColMap.clone(); Map row; if (rows.size() == 0) { for (int i = 0; i < data.getRowCount(); i++) { //判断是否进行行删除 if (!delIndex.isEmpty() && delIndex.indexOf(i) > -1) { continue; } Object value = data.getValueAt(i, column); if (value instanceof JobValue) { JobValue ce = (JobValue) value; if (ce.getValue() instanceof FArray) { FArray valueList = (FArray) ce.getValue(); System.out.println("rows:" + rows.size() + " valueList:" + valueList.length() + "第" + column + "列: " + valueList.toString()); System.out.print("插入记录:"); for (int j = 0; j < valueList.length(); j++) { if (tempHideMap.containsKey("" + j)) { tempHideMap.remove("" + j); continue; } row = new HashMap(); System.out.print("{" + data.getColumnName(column).substring(data.getColumnName(column).indexOf("-") + 1) + ":" + valueList.elementAt(j) + "} "); if (valueList.elementAt(j) != null) { row.put(data.getColumnName(column).substring(data.getColumnName(column).indexOf("-")+1),valueList.elementAt(j).toString()); } else { row.put(data.getColumnName(column).substring(data.getColumnName(column).indexOf("-")+1),""); } rows.add(row); } } else { row = new HashMap(); row.put(data.getColumnName(column).substring(data.getColumnName(column).indexOf("-")+1),ce.getValue().toString()); rows.add(row); } } } } else { int index = 0; for (int i = 0; i < data.getRowCount(); i++) { //判断是否进行行删除 if (!delIndex.isEmpty() && delIndex.indexOf(i) > -1) { continue; } Object value = data.getValueAt(i, column); if (value instanceof JobValue) { JobValue ce = (JobValue) value; if (ce.getValue() instanceof FArray) { FArray valueList = (FArray) ce.getValue(); System.out.println("rows:" + rows.size() + " valueList:" + valueList.length() + "第" + column + "列: " + valueList.toString()); System.out.print("插入记录:"); for (int j = 0; j < valueList.length(); j++) { if (tempHideMap.containsKey("" + j)) { tempHideMap.remove("" + j); continue; } if (index < rows.size()) { if (valueList.elementAt(j) != null) { rows.get(index).put(data.getColumnName(column).substring(data.getColumnName(column).indexOf("-") + 1), valueList.elementAt(j).toString()); } else { rows.get(index).put(data.getColumnName(column).substring(data.getColumnName(column).indexOf("-") + 1), ""); } index++; } else { break; } } } else { if (index < rows.size()) { rows.get(index).put(data.getColumnName(column).substring(data.getColumnName(column).indexOf("-") + 1), ce.getValue().toString()); index++; } else { break; } } } } } return ""; } catch (Exception ex) { return "获取行数据失败" + ex.getMessage(); } } /** * 解析获取数据集后进行处理,供子类覆盖实现过程 */ private Map afterProcess(Map sheets) { return sheets; } //去除非空字段为null的行 private Map removeNullField(Map sheets) { Map newSheet = new HashMap(); for (Map.Entry entry:sheets.entrySet()) { String entityCode = entry.getKey(); Set tmpRows = new HashSet(entry.getValue()); List newRows = new ArrayList(); boolean remove; for (Map row:tmpRows) { remove = false; Map newRow=new HashMap(); //对于propertyCode-NN形式的非空字段,如果值为空则忽略掉 for (Map.Entry field:row.entrySet()) { String key = field.getKey(); String value=String.valueOf(field.getValue()); if (key.endsWith(SUFFIN_IN)) { if (StringUtils.isEmpty(value)) { remove = true; break; } else { newRow.put(key.substring(0,key.length()-3),value); } } else { newRow.put(key,value); } } if (!remove) { newRows.add(newRow); } } //如果有数据才放入Map if (!newRows.isEmpty()) { newSheet.put(entityCode, newRows); } } return newSheet; } //去除重复的行 private Map getNewSheetMap(Map sheets) { Map newSheet = new HashMap(); Iterator iterator = sheets.entrySet().iterator(); while (iterator.hasNext()) { List newRow = new ArrayList(); Map.Entry entry = iterator.next(); String key = entry.getKey(); List list = entry.getValue(); for (int i = 0; i < list.size(); i++) { if (newRow.indexOf(list.get(i)) > -1) { continue; } else { newRow.add(list.get(i)); } } newSheet.put(key,newRow); } return newSheet; }}

       上面代码中封装了好多方法,诸如是否删除行,是否删除重复数据,以及非空处理等等,大家可以各取所需;个人感觉在入库保存前的代码是可以复用的,只是接下来的名字规则,与后台保存可能会有部分差异。

2)在填报属性界面中,添加对应的属性(这里的名字规则,尤为重要,下文详细讲)

       由于填报时我们需要把对应实体以及实体属性存放在cpt中,所以我们这里设定了“实体名-属性名”,作为报表单元格的属性,

并在上面(1)中以Map方式保存单元格数据,map对应的key即为我们的实体类名。

3)编写后台数据保存代码

         上面两步我们已经获得了Map方式保存的单元格数据,我们此时需要根据key实例化我们的实体类,而key只是字符串名称,因此可以用反射获取对应实例,Class.forName(name),又有个问题name是全限定名,我们只有单单类名,这里我们项目实体类都在一个包下,是固定的我就直接写死了;还有service也是同理,获取实例调用更新或者保存方法进行数据的提交。下面直接上代码:

public class ReportFillUtils { private static final String entityPath = "com.reportcenter.business.entity."; private static final String servicePath = "com.reportcenter.productSum.service.impl."; @Autowired @Qualifier("reportcenter.productSum.proGasSumDao") private IProGasSumDAO proGasSumDAO; //对填报的数据进行存储 public String reportDataCommit(Map sheets) { if (sheets != null && sheets.size() > 0) { for (Map.Entry sheet : sheets.entrySet()) { String project = sheet.getKey(); List entityList = sheet.getValue(); String entityName = project+"Entity"; //获取实体类名称 String serviceName = project+"ServiceImpl"; //获取服务类名称 List rowInsertList = new ArrayList(); List rowUpdateList = new ArrayList(); try { //获取对应实体类 Class clazz = Class.forName(entityPath + entityName); if (entityList != null && entityList.size() > 0) { for (Map entityMap:entityList) { //将map中的数据填充到实体中 Object entity = Utils.mapToEntity(entityMap, clazz); if (entityMap.containsKey("identifier")) { rowUpdateList.add(entity); } else { rowInsertList.add(entity); } } //实例化服务类 Class serviceClass = Class.forName(servicePath + serviceName); Object serviceEntity = serviceClass.newInstance(); //由于反射获取的实例,并不会注入对应的属性,因此我们需要自己注入 Method setProGasSumDAO = serviceClass.getMethod("setProGasSumDAO", IProGasSumDAO.class); if (setProGasSumDAO != null) { setProGasSumDAO.invoke(serviceEntity,proGasSumDAO); } if (rowInsertList.size() > 0) { Method insert = serviceEntity.getClass().getMethod("insertFromReport",List.class); Object invoke = insert.invoke(serviceEntity,rowInsertList); } if (rowUpdateList.size() > 0) { Method update = serviceEntity.getClass().getMethod("updateFromReport", List.class); Object invoke = update.invoke(serviceEntity,rowUpdateList); } } } catch (Exception e) { return e.getMessage(); } } } return null; }} public class Utils { //实体类转换为map public static HashMap convertToMap(Object obj) throws Exception { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); HashMap map = new HashMap(); Field[] fields = obj.getClass().getDeclaredFields(); for (int i = 0, len = fields.length; i < len; i++) { String varName = fields[i].getName(); boolean accessFlag = fields[i].isAccessible(); fields[i].setAccessible(true); Object o = fields[i].get(obj); if (o != null) { if ( o instanceof Date){ String str= sdf.format((Date)o); map.put(varName,str); continue; } map.put(varName, o.toString()); fields[i].setAccessible(accessFlag); } } return map; } //map转换为实体类 public static T mapToEntity(Map map,Class entity) throws Exception{ T t = entity.newInstance(); BeanInfo beanInfo = Introspector.getBeanInfo(t.getClass()); PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor field:propertyDescriptors) { String key = field.getName(); if (map.containsKey(key)) { Object obj = map.get(field.getName()); Method setter = field.getWriteMethod(); if (obj != null && !obj.toString().equals("")) { if (field.getPropertyType().toString().equals("class java.lang.String")) { setter.invoke(t,obj); } else if (field.getPropertyType().toString().equals("class java.lang.Integer") || field.getPropertyType().toString().equals("int")) { setter.invoke(t,Integer.valueOf(obj.toString())); } else if (field.getPropertyType().toString().equals("class java.lang.Double") || field.getPropertyType().toString().equals("double")) { setter.invoke(t,Double.valueOf(obj.toString())); } else if (field.getPropertyType().toString().equals("class java.util.Date")) { setter.invoke(t,DateFormatUtils.parse(obj.toString())); } else if (field.getPropertyType().toString().equals("class java.lang.Long") || field.getPropertyType().toString().equals("long")) { setter.invoke(t,Boolean.valueOf(obj.toString())); } else if (field.getPropertyType().toString().equals("class java.lang.Boolean") || field.getPropertyType().toString().equals("boolean")) { setter.invoke(t,Boolean.valueOf(obj.toString())); } } } } return t; }}

上面就是报表填报--》数据解析--》数据保存的代码了,最后保存和更新的服务这里就不上了CRUD相信大家都会的。

注意:

由于是在spring框架的项目,我们的这些类都需要在spring.xml进行定义(),这里也不贴了。数据保存或者更新时大家要多多注意,因为填报是整页提交,我们也需要在dao一次提交更新,一条一条更新,那样填报一次耗时太长,也需要多次获取数据库连接,体验太差。(下面我贴下我更新的代码,可参考) // 继承了SqlMapClientDaoSupport public void insertFromReport(String statementName, List list) throws Exception { SqlMapClient sqlMapClient = getSqlMapClient(); sqlMapClient.startBatch(); for (Object entity:list) { sqlMapClient.insert(statementName,entity); } //一次提交入库 sqlMapClient.executeBatch(); }

至此全部结束,这个思想大家可以借鉴,网上帆软的帖子太少了,填报更少了,搞了两天才搞好。大家有指正的,欢迎在留言区指正;有收获的欢迎点赞。(纸上得来终觉浅,绝知此事要躬行!加油)

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至lizi9903@foxmail.com举报,一经查实,本站将立刻删除。

上一篇 没有了

下一篇没有了