浏览 4967 次
精华帖 (1) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-06-26
最后修改:2009-11-12
在企业应用系统中,经常会要要求生成报表。 偶公司向来生成报表的任务都交由给数据库组来完成 不巧,新项目上线 要求鄙人要完成一个展现在浏览器下的报表 鄙人不太会用什么报表工具,也不是很复杂的报表 只需要按要求抓起数据 用HTML或者Excel显示 方案: 定时触发器 Spring自带的quartz Oracle存储过程执行我要抓取的数据 POI显示成报表形式 目的: 作为一个开发手记,积累工作经验 先从数据生成开始,我吧要抓起的数据用新建的表来存放 代码可能会贴很多 create or replace procedure outcall_report_pro ( /*前置时间 字符格式*/ --PREFIX_YMD IN VARCHAR2, -- 前置 处理年月日 2009-06-25 /*后置时间 字符格式*/ --POSTPOSITION_YMD IN VARCHAR2 /*某天的时间*/ INPUT_YMD IN VARCHAR2 -- 条件 处理年月日 /*无返回值*/ ) is w_RESULT NUMBER; /*定义一个游标存放读取的记录*/ CURSOR cur_read_result IS SELECT MAINTABLE.cscalltime , MAINTABLE.cscallresult , MAINTABLE.cscallrtcause , MAINTABLE.csoperatorid , MAINTABLE.userid , MAINTABLE.ascalltime , MAINTABLE.ascallresult , MAINTABLE.ascallrtcause , MAINTABLE.asoperatorid , MAINTABLE.orderid , ASALLOT.asallotat , CSALLOT.csallotat FROM ( select cstable.calltime as cscalltime , cstable.callresult as cscallresult , cstable.callrtcause as cscallrtcause , cstable.operatorid as csoperatorid , cstable.userid , astable.calltime as ascalltime , astable.callresult as ascallresult , astable.callrtcause as ascallrtcause , astable.operatorid as asoperatorid , astable.orderid from ( select cst.calltime , cst.callresult , cst.callrtcause , cst.operatorid , cst.userid , cst.orderid from erp2_usercommunicate_log cst where cst.callway = 1 and cst.callobject = 1 and to_char(cst.calltime,'yyyy-MM-dd')=INPUT_YMD order by cst.calltime desc ) cstable, ( select cst.calltime , cst.callresult , cst.callrtcause , cst.operatorid , cst.userid , cst.orderid from erp2_usercommunicate_log cst where (orderid,calltime) in ( select orderid,max(calltime) from erp2_usercommunicate_log cst where cst.callway = 1 and cst.callobject = 2 and to_char(cst.calltime,'yyyy-MM-dd')=INPUT_YMD group by orderid ) ) astable where cstable.orderid = astable.orderid(+) ) MAINTABLE, ( select allot.allottime as asallotat , allot.userid as asuserid from erp2_userallot_log allot where (userid, allottime) in ( select userid, min(allottime) from erp2_userallot_log where state=2 and to_char(allottime,'yyyy-MM-dd')=INPUT_YMD group by userid ) ) ASALLOT, ( select allot.allottime as csallotat , allot.userid as csuserid from erp2_userallot_log allot where (userid, allottime) in ( select userid, min(allottime) from erp2_userallot_log where state=1 and to_char(allottime,'yyyy-MM-dd')=INPUT_YMD group by userid ) ) CSALLOT where MAINTABLE.userid = ASALLOT.asuserid(+) and MAINTABLE.userid = CSALLOT.csuserid(+) ; /* 插入记录函数 */ FUNCTION fnc_record -- 返回0正常,异常为-1 ( p_csallotat IN DATE , p_cscalltime IN DATE , p_cscallresult IN NUMBER , p_cscallresultcause IN VARCHAR2 , p_asallotat IN DATE , p_ascalltime IN DATE , p_ascallresult IN NUMBER , p_ascallresultcause IN VARCHAR2 , p_userid IN NUMBER , p_asoperatorid IN NUMBER , p_csoperatorid IN NUMBER , p_orderid IN NUMBER ) RETURN NUMBER IS BEGIN INSERT INTO ERP2_OUTCALL_REPORT ( ID , REPORTAT , CSALLOTAT , CSCALLAT , CSCALLRESULT , CSCALLRESULTCAUSE , ASCALLAT , ASCALLRESULT , ASCALLRESULTCAUSE , ASALLOTAT , USERID , ASID , CSID , ORDERID ) values ( seq_erp2_outcall_report_id.nextval , sysdate , p_csallotat , p_cscalltime , p_cscallresult , p_cscallresultcause , p_ascalltime , p_ascallresult , p_ascallresultcause , p_asallotat , p_userid , p_asoperatorid , p_csoperatorid , p_orderid ); RETURN 0; EXCEPTION WHEN OTHERS THEN RETURN -1; END fnc_record; /*执行函数*/ FUNCTION fnc_excute RETURN NUMBER IS w_RES NUMBER := 0; BEGIN IF w_RES = 0 THEN FOR rec IN cur_read_result LOOP w_RES := fnc_record(rec.csallotat , rec.cscalltime , rec.cscallresult , rec.cscallrtcause , rec.asallotat , rec.ascalltime , rec.ascallresult , rec.ascallrtcause , rec.userid , rec.asoperatorid , rec.csoperatorid , rec.orderid); EXIT WHEN w_RES != 0; END LOOP; END IF; RETURN w_RES; EXCEPTION WHEN OTHERS THEN RETURN -1; END fnc_excute; begin w_RESULT := 0; IF w_RESULT = 0 THEN w_RESULT := fnc_excute; END IF; IF w_RESULT != 0 THEN ROLLBACK; END IF; EXCEPTION WHEN OTHERS THEN ROLLBACK; end outcall_report_pro; 然后就是在ssh架构下执行 调用存储过程(没用过的可要看好了 啊) /** * * @version 创建时间:2009-6-25 类说明:外呼报表-电话沟通详单查询 * */ @SuppressWarnings({"serial","unused","unchecked"}) public class OutCallReportManageImpl { /* * 打印日志 */ Log log = LogFactory.getLog(OutCallReportManageImpl.class); private StatisticsDao statisticsdao; public StatisticsDao getStatisticsdao() { return statisticsdao; } public void setStatisticsdao(StatisticsDao statisticsdao) { this.statisticsdao = statisticsdao; } //--------------------- excute core method ----------------------- public void processOutCallReport(){ Connection conn = null; CallableStatement proc = null; try { conn = statisticsdao.getHibernateTemplate(). getSessionFactory().getCurrentSession().connection(); proc = conn.prepareCall("{ call outcall_report_pro(?) }"); proc.setString(1, getTime("yyyy-MM-dd")); proc.execute(); log.info("....Procedure调用成功!"); } catch (Exception e) { e.printStackTrace(); } finally { try { if (null != proc) { proc.close(); } if (null != conn) { conn.close(); } } catch (Exception ex) { } } } } 注意这里的类名字定义的了吗? 为什么为定义成*ManageImpl后缀呢? 因为鄙人在开发中直接用到spring管理的session 用普通的POJO的时候 会报不在事务内招不到相应的session 请看 //..... conn = statisticsdao.getHibernateTemplate(). getSessionFactory().getCurrentSession().connection(); 和spring 中用aop配置事务的方式 <xml?> <aop:config proxy-target-class="true"> <aop:pointcut id="ServiceOperation" expression="execution(* com.chinadim.erp2..*ManageImpl.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="ServiceOperation"/> </aop:config> </xml> 其中执行存储过程的那个方法 也被定义在事务执行方法内... 省 下面就是如何在伸手不见五指的 黑夜 来一触即发 很显然要配置 quartz.xml <?xml version="1.0" encoding="UTF-8"?> <!-- 指定Spring配置文件的Schema信息 --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> <!-- add by sam 2009-06-25 电话沟通详单报表 --> <bean id="outCallReport" class="com.chinadim.erp2.datacollection.OutCallReportManageImpl"> <property name="statisticsdao"> <ref bean="statisticsdao"/> </property> </bean> <!-- 指定自启动的目标类和目标方法 --> <!-- add by sam 2009-06-25 电话详单沟通查询报表 --> <bean id="Target_outCallReport" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <!--指定目标类--> <property name="targetObject"> <ref bean="outCallReport"/> </property> <!--指定目标类方法--> <property name="targetMethod"> <value>processOutCallReport</value> </property> </bean> <!-- add by sam 2009-06-25 电话详单查询报表工作JOB --> <bean id="Trigger_outCallReport" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail"> <ref bean="Target_outCallReport"/> </property> <property name="cronExpression"> <value>0 48 15 * * ?</value> </property> </bean> <!-- add by sam 2009-06-25 电话详单查询报表 --> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="autoStartup"> <value>true</value> </property> <property name="triggers"> <list> <ref local="Trigger_outCallReport"/> </list> </property> </bean> </beans> 后面是生成报表的部分 细节 省... 用apache POI实现的导出报表 /** * * @version 创建时间:2009-5-6 类说明:利用开源组件POI3.0.2动态导出EXCEL文档 * * @param <T> 应用泛型,代表任意一个符合javabean风格的类 */ @SuppressWarnings({"serial","unused","unchecked"}) public abstract class ExportExcel<T> { public void exportExcel(String title, Collection<T> dataset, OutputStream out) { exportExcel(title, null, dataset, out, "yyyy-MM-dd"); } public void exportExcel(Collection<T> dataset, OutputStream out) { exportExcel("测试POI导出EXCEL文档", null, dataset, out, "yyyy-MM-dd"); } public void exportExcel(String title, String[] headers, Collection<T> dataset, OutputStream out) { exportExcel(title, headers, dataset, out, "yyyy-MM-dd"); } public void exportExcel(String[] headers, Collection<T> dataset, OutputStream out) { exportExcel("测试POI导出EXCEL文档", headers, dataset, out, "yyyy-MM-dd"); } public void exportExcel(String[] headers, Collection<T> dataset, OutputStream out, String pattern) { exportExcel("测试POI导出EXCEL文档", headers, dataset, out, pattern); } /** * 这是一个通用的方法,利用了JAVA的反射机制, * 可以将放置在JAVA集合中并且符号一定条件的数据以EXCEL 的形式输出到指定IO设备上 * * @param title * 表格标题名 * @param headers * 表格属性列名数组 * @param dataset * 需要显示的数据集合,集合中一定要放置符合javabean风格的类的对象。此方法支持的 * javabean属性的数据类型有基本数据类型及String,Date,byte[](图片数据) * @param out * 与输出设备关联的流对象,可以将EXCEL文档导出到本地文件或者网络中 * @param pattern * 如果有时间数据,设定输出格式。默认为"yyy-MM-dd" */ public void exportExcel(String title, String[] headers, Collection<T> dataset, OutputStream out, String pattern) { // 声明一个工作薄 HSSFWorkbook workbook = new HSSFWorkbook(); // 生成一个表格 HSSFSheet sheet = workbook.createSheet(title); // 设置表格默认列宽度为15个字节 sheet.setDefaultColumnWidth((short) 15); // 生成一个样式 HSSFCellStyle style = workbook.createCellStyle(); // 设置这些样式 style.setFillForegroundColor(HSSFColor.SKY_BLUE.index); style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); style.setBorderBottom(HSSFCellStyle.BORDER_THIN); style.setBorderLeft(HSSFCellStyle.BORDER_THIN); style.setBorderRight(HSSFCellStyle.BORDER_THIN); style.setBorderTop(HSSFCellStyle.BORDER_THIN); style.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 生成一个字体 HSSFFont font = workbook.createFont(); font.setColor(HSSFColor.VIOLET.index); font.setFontHeightInPoints((short) 12); font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); // 把字体应用到当前的样式 style.setFont(font); // 生成并设置另一个样式 HSSFCellStyle style2 = workbook.createCellStyle(); style2.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index); style2.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); style2.setBorderBottom(HSSFCellStyle.BORDER_THIN); style2.setBorderLeft(HSSFCellStyle.BORDER_THIN); style2.setBorderRight(HSSFCellStyle.BORDER_THIN); style2.setBorderTop(HSSFCellStyle.BORDER_THIN); style2.setAlignment(HSSFCellStyle.ALIGN_CENTER); style2.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); // 生成另一个字体 HSSFFont font2 = workbook.createFont(); font2.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL); // 把字体应用到当前的样式 style2.setFont(font2); // 声明一个画图的顶级管理器 HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); // 定义注释的大小和位置,详见文档 HSSFComment comment = patriarch.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short) 4, 2, (short) 6, 5)); // 设置注释内容 comment.setString(new HSSFRichTextString("可以在POI中添加注释!")); // 设置注释作者,当鼠标移动到单元格上是可以在状态栏中看到该内容. comment.setAuthor("leno"); //产生表格标题行 HSSFRow row = sheet.createRow(0); for (short i = 0; i < headers.length; i++) { HSSFCell cell = row.createCell(i); cell.setCellStyle(style); HSSFRichTextString text = new HSSFRichTextString(headers[i]); cell.setCellValue(text); } //这里可以定制的调用被子类实例的抽象方法 createRowsAndCells(dataset, sheet, row, style2, headers.length, pattern); try { workbook.write(out); } catch (IOException e) { e.printStackTrace(); } } /** * 抽象方法 子类去实现 */ public abstract void createRowsAndCells(Collection<T> dataset, HSSFSheet sheet, HSSFRow row, HSSFCellStyle style, int columns, String pattern); /** * 测试主函数 * @param args */ public static void main(String[] args) { } } 以上定义的抽象类 定义导出报表的样式 格式颜色等 子类要实现的只是去继承即可.... /** * * @version 创建时间:2009-6-25 类说明: * */ @SuppressWarnings({"serial","unused","unchecked"}) public class ExportExcelOutCallReport extends ExportExcel<OutCallReportWrap>{ @Override public void createRowsAndCells(Collection<OutCallReportWrap> dataset, HSSFSheet sheet, HSSFRow row, HSSFCellStyle style, int columns, String pattern) { int index = 0; for (OutCallReportWrap oe:dataset){ index ++; //创建行 row = sheet.createRow(index); for (int i=0; i < columns; i++){ //创建列 并设置样式 HSSFCell cell = row.createCell((short)i); cell.setCellStyle(style); switch (i) { case 0: //第一列:省份 String province = oe.getOutCallReportEntity().getUserObject().getProvince(); cell.setCellValue(new HSSFRichTextString(province)); break; case 1: //第二列:城市 String city = oe.getOutCallReportEntity().getUserObject().getCity(); cell.setCellValue(new HSSFRichTextString(city)); break; case 2: //第三列:导入时间 if (null != oe.getOutCallReportEntity().getUserObject().getImporttime()){ String importTime = getTime(oe.getOutCallReportEntity(). getUserObject().getImporttime(), "yyyy-MM-dd"); cell.setCellValue(new HSSFRichTextString(importTime)); } break; case 3: //第四列:电话号码 String mobile = oe.getOutCallReportEntity().getUserObject().getMobile(); cell.setCellValue(new HSSFRichTextString(mobile)); break; case 4: //第五列:下单分配时间 if (null != oe.getOutCallReportEntity().getCsAllotAt()){ String csAllotTime = getTime(oe.getOutCallReportEntity().getCsAllotAt(),"yyyy-MM-dd"); cell.setCellValue(new HSSFRichTextString(csAllotTime)); } break; case 5: //第六列:下单拨打时间 if (null != oe.getOutCallReportEntity().getCsCallAt()){ String csCallTime = getTime(oe.getOutCallReportEntity().getCsCallAt(),"yyyy-MM-dd"); cell.setCellValue(new HSSFRichTextString(csCallTime)); } break; case 6: //第七列:下单拨打结果 String csCallResult = UsercommunicateLogEntity. getContactResultTreeMapForCallResult(false).get(oe.getOutCallReportEntity().getCsCallResult()); cell.setCellValue(new HSSFRichTextString(csCallResult)); break; case 7: //第八列:下单拨打结果原因 String csCallResultCause = oe.getOutCallReportEntity().getCsCallResultCause(); cell.setCellValue(new HSSFRichTextString(csCallResultCause)); break; case 8: //第九列:下单坐席编号 String csSeatingNo = oe.getOutCallReportEntity().getCsOperator().getSeatingNo(); cell.setCellValue(new HSSFRichTextString(csSeatingNo)); break; case 9: //审单分配时间 if (null != oe.getOutCallReportEntity().getOrderObject()){ String asAllotTime = getTime(oe.getOutCallReportEntity().getAsAllotAt(),"yyyy-MM-dd"); cell.setCellValue(new HSSFRichTextString(asAllotTime)); } break; case 10: //审单拨打时间 if (null != oe.getOutCallReportEntity().getOrderObject()){ String asCallTime = getTime(oe.getOutCallReportEntity().getAsCallAt(),"yyyy-MM-dd"); cell.setCellValue(new HSSFRichTextString(asCallTime)); } break; case 11: //审单拨打结果 if (null != oe.getOutCallReportEntity().getOrderObject()){ String asCallResult = UsercommunicateLogEntity. getContactResultTreeMapForCallResult(false).get(oe.getOutCallReportEntity().getAsCallResult()); cell.setCellValue(new HSSFRichTextString(asCallResult)); } break; case 12: //审单拨打结果原因 if (null != oe.getOutCallReportEntity().getOrderObject()){ String asCallResultCause = oe.getOutCallReportEntity().getAsCallResultCause(); cell.setCellValue(new HSSFRichTextString(asCallResultCause)); } break; case 13: //审单坐席编号 if (null != oe.getOutCallReportEntity().getOrderObject()){ String asSeatingNo = oe.getOutCallReportEntity().getAsOperator().getSeatingNo(); cell.setCellValue(new HSSFRichTextString(asSeatingNo)); } break; case 14: //订单编号 if (null != oe.getOutCallReportEntity().getOrderObject()){ String orderNo = oe.getOutCallReportEntity().getOrderObject().getOrderNo(); cell.setCellValue(new HSSFRichTextString(orderNo)); } break; case 15: //订单状态 if (null != oe.getOutCallReportEntity().getOrderObject()){ String orderState = OrdersEntity.getContactResultTreeMapForOrderState(false). get(oe.getOutCallReportEntity().getOrderObject().getOrderState()); cell.setCellValue(new HSSFRichTextString(orderState)); } break; case 16: //套餐名称 if (null != oe.getOutCallReportEntity().getOrderObject()){ String packageNames = oe.getPackageNames(); cell.setCellValue(new HSSFRichTextString(packageNames)); } break; case 17: //订单备注 if (null != oe.getOutCallReportEntity().getOrderObject()){ String orderRemark = oe.getOutCallReportEntity().getOrderObject().getRemark(); cell.setCellValue(new HSSFRichTextString(orderRemark)); } break; } } } } } 贴了很多代码 开始遇到过些错误 都慢慢解决了 个人感觉 在不熟悉用报表工具开发的时候 写写存储过程还是蛮方便的抓起数据 在效益上也有保障 // ----------------------- 下一步 J2EE报表开发 --> 朋友 一起努力吧 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |