POI3级以及3级以下表头的报表处理
来源:互联网 发布:cyberghost for mac 编辑:程序博客网 时间:2024/06/03 07:09
POI3级以及3级以下表头的报表处理
最近做Excel导出,本来好好的,直接用模板导出就好了,结果需求一句话,就来句要动态导出,所以迫不得已得自己写表头啦。。。
开发人员的悲催啊。。。,需求要啥咱得给啊。。
哈哈,说笑啦,不过也确实是因为这个才弄啦这个表头处理,也是这个东西让我有感觉想写BLOG啦,算是谢谢咱家需求啦~
简单说一下这个实现的功能,其实就是通过POI导出数据,不过可以通过固定格式的字符串来定义表头,之后填写数据,然后导出,不过是WEB端的导出。
3级表头字符串如下(使用 , : _ = @ 来进行分级处理,用List太麻烦,用数组没办法处理,只能这么做啦)例如: TA:TA1=TA11@TA12_TA2,TB
2级表头字符串如下(使用 , : _ 来进行分级处理)例如: TA:TA1_TA2,TB
1级表头就没啥说啦,逗号分隔
下面干脆点,直接代码啦
import java.io.IOException;import java.io.OutputStream;import java.util.*;import javax.servlet.http.HttpServletResponse;import org.apache.poi.hssf.usermodel.*;import org.apache.poi.hssf.util.Region; /** * 文件名称:PoiUtilDetailTile.java * 模块名称:poi导出同时进行多重表头处理,以及相关的数据插入和导出 * 完成日期: * * 文件调用: * 修改记录: * 修改时间: * 修 改 人: * 修改内容: * 关联BUG: * 修改方法: */@SuppressWarnings("deprecation")public class PoiUtilDetailTitle { private HSSFCellStyle titleStyle = null; private HSSFCellStyle bodyStyle = null; /** * 初始化样式 */ private void init(HSSFWorkbook wb) { titleFont(wb); bodyFont(wb); } /** * 设置body样式 * */ private void bodyFont(HSSFWorkbook wb) { HSSFFont bodyFont = wb.createFont(); bodyFont.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL); bodyFont.setFontName("宋体"); bodyFont.setFontHeightInPoints((short) 9); bodyStyle = wb.createCellStyle(); bodyStyle.setFont(bodyFont); bodyStyle.setBorderTop((short)1); bodyStyle.setBorderRight((short)1); bodyStyle.setBorderBottom((short)1); bodyStyle.setBorderLeft((short)1); bodyStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); bodyStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); } /** * 设置标题样式 * */ private void titleFont(HSSFWorkbook wb) { HSSFFont titleFont = wb.createFont(); titleFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); titleFont.setFontName("宋体"); titleFont.setFontHeightInPoints((short) 12); titleStyle = wb.createCellStyle(); titleStyle.setFont(titleFont); titleStyle.setBorderBottom((short)1); titleStyle.setBorderTop((short)1); titleStyle.setBorderRight((short)1); titleStyle.setBorderLeft((short)1); titleStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); titleStyle.setVerticalAlignment(HSSFCellStyle.ALIGN_CENTER); } /** * createAndExportWb * 创建并导出wb * @param filename 导出文件名称 * @param itsheets * 是一个Map 的list 内容有 * name : sheet的名称 * titleType :sheet中title的类型,值有 3(3级表头),2(2级表头),他同时也对应表头的级别 * titleString :sheet中title的串(没处理1级,有功夫再写,1级的也简单) * 3级表头字符串如下(使用 , : _ = @ 来进行分级处理,用List太麻烦,用数组没办法处理,只能这么做啦) * 例如: TA:TA1=TA11@TA12_TA2,TB * 2级表头字符串如下(使用 , : _ 来进行分级处理)例如: TA:TA1_TA2,TB * * datalist : 对应的数据,要求数据中不会出现null,或者少值,因为这样会出现串列的问题 List<List<Object>> * @param response * void * @exception * @since 1.0.0 */ @SuppressWarnings({ "unchecked" }) public void createAndExportWb(String filename,List<Map<String,Object>> itsheets,HttpServletResponse response){ HSSFWorkbook wb=new HSSFWorkbook(); init(wb); for(Map<String,Object> stmap :itsheets){//循环处理sheet String name=(String) stmap.get("name"); int titleType=(int) stmap.get("titleType"); String titleString=(String) stmap.get("titleString"); List<List<Object>> datalist=(List<List<Object>>) stmap.get("datalist"); HSSFSheet sheet=wb.createSheet(name);//创建sheet doSheetFillIn(sheet,titleType,titleString,datalist);//处理sheet的主方法 } doExportExcel(response,filename,wb); } /** * doSheetFillIn * 处理sheet * @param sheet * @param titleType * @param titleString * @param datalist * void * @exception * @since 1.0.0 */ private void doSheetFillIn(HSSFSheet sheet, int titleType, String titleString, List<List<Object>> datalist) { if(3==titleType){ doSheetFillIn_Three(sheet,titleString);//处理3级表头 }else if(2==titleType){ doSheetFillIn_Two(sheet,titleString);//处理2级表头 }else if(1==titleType){ doSheetFillIn_One(sheet,titleString);//处理1级表头 } doFillInSheetData(sheet,titleType,datalist);//填写数据 } /** * doSheetFillIn_One * 处理1级表头 * @param sheet * @param titleString * void * @exception * @since 1.0.0 */ private void doSheetFillIn_One(HSSFSheet sheet, String titleString) { HSSFRow row1 = sheet.createRow(0); String[] headers=titleString.split(","); for(short i = 0; i < headers.length; i++){//i是headers的索引,也是Excel的索引 HSSFCell cellT = row1.createCell(i); cellT.setCellStyle(titleStyle); HSSFRichTextString text = new HSSFRichTextString(headers[i]); cellT.setCellValue(text); } } /** * doSheetFillIn_Two * 2级表头处理 * @param sheet * @param titleString * 字符串样例 2级表头字符串如下(使用 , : _ 来进行分级处理)例如: TA:TA1_TA2,TB * void * @exception * @since 1.0.0 */ private void doSheetFillIn_Two(HSSFSheet sheet, String titleString) { HSSFRow row1 = sheet.createRow(0); HSSFRow row2 = sheet.createRow(1); String[] headers=titleString.split(","); for(short i = 0, n = 0; i < headers.length; i++){//i是headers的索引,n是Excel的索引 HSSFCell cellT = row1.createCell(n); cellT.setCellStyle(titleStyle); HSSFRichTextString text = null; if(headers[i].contains(":")){//2级标题 String[] temp = headers[i].split(":");//子标题的分割 text = new HSSFRichTextString(temp[0]); String[] childlv1 = temp[1].split("_"); sheet.addMergedRegion(new Region(0, n, 0, (short) (n + childlv1.length -1)));//2级标题的时候可以直接根据2子标题的个数来合并 short tempI = n; for(int j = 0; j < childlv1.length -1; j++){//循环补充父标题的空格 HSSFCell cellTitleBlank = row1.createCell(++tempI); cellTitleBlank.setCellStyle(titleStyle); } for(int j = 0; j < childlv1.length; j++){//循环插入自标题的内容 HSSFCell cellChild = row2.createCell(n++); cellChild.setCellStyle(titleStyle); cellChild.setCellValue(new HSSFRichTextString(childlv1[j])); } }else{//1级标题 HSSFCell cell2 = row2.createCell(n); cell2.setCellStyle(bodyStyle); text = new HSSFRichTextString(headers[i]); sheet.addMergedRegion(new Region(0, n, 1, n));//没有子标题的时候自己独占两行 n++; } cellT.setCellValue(text); } } /** * doSheetFillIn_Three * 3级表头处理 * @param sheet * @param titleString * * 3级表头字符串如下(使用 , : _ = @ 来进行分级处理,用List太麻烦,用数组没办法处理,只能这么做啦) * 例如: TA:TA1=TA11@TA12_TA2,TB * void * @exception * @since 1.0.0 */ private void doSheetFillIn_Three(HSSFSheet sheet, String titleString) { HSSFRow row1 = sheet.createRow(0); HSSFRow row2 = sheet.createRow(1); HSSFRow row3 = sheet.createRow(2); String[] headers=titleString.split(","); for(short i = 0, n = 0; i < headers.length; i++){//i是headers的索引,n是Excel的索引 HSSFCell cellT = row1.createCell(n); cellT.setCellStyle(titleStyle); HSSFRichTextString text = null; if(headers[i].contains(":")){//有2级标题 if(headers[i].contains("=")){//有3级标题 TA:TA1=TA11@TA12_TA2 //确定3级标题的个数,确定1级标题的总长度,同时也是把各级标题分解开 String[] temp = headers[i].split(":"); //分级1级标题temp[0]是标题文字,temp[1]是子标题 text = new HSSFRichTextString(temp[0]); String[] childlv2=temp[1].split("_"); //获取temp2级标题的数组 int ttlength=0; short row2index=n; short row3index=n; for(int k=0;k<childlv2.length;k++){ //循环计算全部的2级标题对应的子标题总数 String childlv2_1=childlv2[k]; //取到2级标题的第一个 HSSFRichTextString textLV2 = null; HSSFCell cellChildlv2 = row2.createCell(row2index++); //根据row2的index进行循环 cellChildlv2.setCellStyle(titleStyle); //一层层的向下取,取到3级,并向下进行补充 if(childlv2_1.contains("=")){//2级子节点,有3级子节点 String[] childlv2_all=childlv2_1.split("="); textLV2=new HSSFRichTextString(childlv2_all[0]); String childlv3_1=childlv2_all[1]; if(childlv3_1.contains("@")){//这里说明2级子节点有多个3级子节点,那么2级子节点就需要合并,同时为 String[] childlv3_all=childlv3_1.split("@"); ttlength=ttlength+childlv3_all.length; //开始写3级节点 for(String childlv3Text : childlv3_all){ HSSFCell cellChildlv3 = row3.createCell(row3index++); cellChildlv3.setCellStyle(titleStyle); cellChildlv3.setCellValue(new HSSFRichTextString(childlv3Text)); n++;//进行EXCEL索引叠加 } //这里进行2级节点的合并,因为有多个 sheet.addMergedRegion(new Region(1, row2index, 1, (short)(row2index+childlv3_all.length-1))); //补充2级节点的空cell for(int x=0;x<childlv3_all.length-1;x++){ HSSFCell cellChildlv2Blank = row2.createCell(++row2index); cellChildlv2Blank.setCellStyle(titleStyle); } }else{//这里说明2级子节点只有一个3级子节点,那么就不用合并和补充空格啦 ttlength=ttlength+1; //写入3级节点的cell HSSFCell cellChildlv3 = row3.createCell(row3index++); cellChildlv3.setCellStyle(titleStyle); cellChildlv3.setCellValue(new HSSFRichTextString(childlv3_1)); n++;//Excel索引节点的递增 } }else{//2级子几点没有3及子节点 textLV2=new HSSFRichTextString(childlv2_1); ttlength=ttlength+1; //这个2级节点没有子节点,那么就要合并3row sheet.addMergedRegion(new Region(1, row3index, 2, row3index)); //补充3row的cell空格 HSSFCell cellChildlv3Blank = row3.createCell(row3index++); cellChildlv3Blank.setCellStyle(titleStyle); n++;//进行Excel的索引递增,避免写到一个格子里面去 } cellChildlv2.setCellValue(textLV2); } //进行3层总长度的cell合并 sheet.addMergedRegion(new Region(0, (short)(n-ttlength), 0, (short) (n-1))); //插入第一行的补充的空格 short tr1 = n; for(int j = 0; j < ttlength -1; j++){//循环补充父标题的空格,因为已经定义啦一个cell所以要减1 HSSFCell cellTitleBlank = row1.createCell(++tr1);//因为开始已经定义啦一个cell所以就是 ++tr1 cellTitleBlank.setCellStyle(titleStyle); } }else{//只有2级标题 String[] temp = headers[i].split(":");//子标题的分割 text = new HSSFRichTextString(temp[0]); String[] childlv2 = temp[1].split("_"); //只有2及标题,那么1级标题要占2行,2级标题占1行 sheet.addMergedRegion(new Region(0, n, 1, (short) (n + childlv2.length -1))); short tr1 = n; short tr2 = n; short tr3 = n; //对对应的空行进行补充,第一行 for(int j = 0; j < childlv2.length -1; j++){//循环补充父标题的空格,因为已经定义啦一个cell所以要减1 HSSFCell cellTitleBlank = row1.createCell(++tr1);//因为开始已经定义啦一个cell所以就是 ++tr1 cellTitleBlank.setCellStyle(titleStyle); } //对第二行进行补充空格,从头开始 for(int k=0;k < childlv2.length; k++){//未定义cell,所以不减1 HSSFCell cellTitleBlank = row2.createCell(tr2++);//之前未进行定义,所以是tr2++ cellTitleBlank.setCellStyle(titleStyle); } //插入子行信息 for(int j = 0; j < childlv2.length; j++){//循环插入子标题的内容 HSSFCell cellChild = row3.createCell(tr3++); cellChild.setCellStyle(titleStyle); cellChild.setCellValue(new HSSFRichTextString(childlv2[j])); n++;//这里进行啦EXCEL的索引递增,不然会都写到一个格子里面去 } } }else{//只有1级标题 HSSFCell cell2 = row2.createCell(n); cell2.setCellStyle(titleStyle); HSSFCell cell3 = row3.createCell(n); cell3.setCellStyle(titleStyle); text = new HSSFRichTextString(headers[i]); sheet.addMergedRegion(new Region(0, n, 2, n));//没有子标题的时候自己独占两行 n++; } cellT.setCellValue(text); } } /** * doFillInSheetData * 填写数据 * @param sheet * @param beginRow 开始行数 * @param datalist 数据列表,进行循环写入即可 * void * @exception * @since 1.0.0 */ private void doFillInSheetData(HSSFSheet sheet, int beginRow,List<List<Object>> datalist) { if(null != datalist && datalist.size() > 0){ int beginNum=beginRow;//设定起始地行数 HSSFRow row = null; HSSFCell cell = null; for(int i=0; i<datalist.size(); i++){//循环数据 row = sheet.createRow(beginNum++); List<Object> data=datalist.get(i); int j=0; for(Object en :data){ cell = row.createCell(j++); cell.setCellStyle(bodyStyle); cell.setCellValue(new HSSFRichTextString(String.valueOf(en))); } } } } /** * doExportExcel * 进行excel导出 * @param response * @param filename,文件名称 * @param wb * void * @exception * @since 1.0.0 */ private void doExportExcel(HttpServletResponse response,String filename,HSSFWorkbook wb){ OutputStream out=null; try { filename = new String(filename.getBytes("GBK"), "ISO8859_1");//中文处理 response.setHeader("content-disposition", "attachment; filename="+filename); response.setContentType("application/msexcel"); out=response.getOutputStream(); wb.write(out); out.flush(); } catch (Exception e) { e.printStackTrace(); } finally { if (out!=null){try {out.close();} catch (IOException e) {}} } }}
这里的导出时在web端的导出,想改成本地的自己调整下就好啦。
样式什么的自己在两个style里调整就好啦
不过还有一个问题,就是没做列的宽度自适应,想啦想,让他们自己拖去吧~~~
0 0
- POI3级以及3级以下表头的报表处理
- POI3.8中 大数据量的处理
- 用poi3和chartdirect生成带图表的excel报表
- rdlc 报表第二页没有表头处理
- POI3.8中 大数据量的excel表格处理
- BIEE多层表头报表的制作方法
- gridview的表头垂直居中以及表头多行显示
- 水晶报表设置表头
- GridView显示带有中国式报表表头的方法
- linux 的 awk 命令格式化输出报表表头
- 基于PHPexecl类生成复杂的报表表头示例
- VS2005的DataGridView 表头合并处理
- POI EXCEL多表头的处理代码
- POI EXCEL多表头的处理代码
- 1.4版本的easyUI复杂表头处理
- JQuery EasyUI DataGrid复杂表头的处理
- 表头变成英文的处理方式
- TCP/IP传输层以下的处理
- 去掉字符串中的空格
- HTML基础样式(一)
- sublime text 2 下的Markdown写作
- UVA 10344 23 out of 5
- 关于FastReport.Net 的使用技巧
- POI3级以及3级以下表头的报表处理
- spark、scala安装配置
- linux如何查看端口占用情况
- 将eclipse的项目导入android studio
- B样条曲线
- 博科300光交配置/cisco mds9000系列交换机配置
- codeforces 710D Two Arithmetic Progressions [同余方程]【数论】
- 关于ext前端Date传到后台变成String形式的解决办法
- python 下执行wget传入参数