入职后参与的第一个项目是“烟草GIS项目”,分配给我的任务参主要是用户对系统数据Excel格式的录入和导出,满足此项需求可以在很大程度上为用户在项目外对数据的处理中提供很大便利,使其可以利用Excel的强大功能来实现一些统计运算,但是java自带的API中并没有直接操作Excel表格的的方法,为解决问题,只能借助第三方的解决方案。
根据了解所知,在java处理Excel领域已经存在很多的开源解决方案,其中比较突出的有ApachePOI和JExcelApi(jxl)。
*Apache是世界上使用排名第一的Web服务器软件,它的跨平台和安全性使其成为最流行的Web服务器软件之一,ApachePOI是Apache基金组织Jakarta项目的子项目,它包括一系列的API,可以操作多种格式的Microsoft Office文件,通过这些API使java更方便的操作Excel、Word等格式的Office文件
*JExcelApi(jxl)是一个韩国人写的java操作Excel的工具,名气虽然逊于ApachePOI,但同样有自己的的特色
功能上POI要强一些,对于图形图表的支持更完善,但是JExcelApi(jxl)对于以下方面有着明显的优势:1、合并单元格加边框问题;2、中文乱码问题等等
接下来要记录的就是用ApachePOI对Excel的基本操作:
我把项目中对Excel操作划分为三大部分:1、生成Excel模板,方便用户导出后填充;2、完善Excel表格,数据导入处理;3、读取数据库数据,Excel格式导出数据。本文章中记录是对模板生成导出的分析整理
* 模板导出
接下来我会以“个人信息”的excel为例,为大家做示范(如图1.1所示),虽然这只是一个最简单的模板,但是复杂的模板无非是在基础上的堆积,可能多些麻烦,但是基本作法大体都是雷同的
图1.1
首先先阐述需要到处模板的样式和要求(如图1.1所示):
一、模板有3行标题栏(即:方便用户观看,但是读取时不会读取的行);
二、模板中第1行占据5列;
三、模板中1、3、5列的第2行和第3行都是合并的;
四、模板中第2行的3、4列是合并的;
五、特殊要求:(很有效,也很常用)
部门只有固定的几个,为避免录入时录入不明确、模糊信息,模板中设定部门一列中有个选择框,设定只能选择(“研发部”,“财务部”,“工程部”)
六、留给用户填写的空的表格;
七、标题栏的字体多为宋体、加粗;
八、标题栏中和填充栏中都无底色;
九、能够导出,导出存放位置自选;(这点很关键,是个小技巧,但我查了好多资料,关键是查询时不会表述)
下面我们进行代码编写
1、导入要用到的ApachePOI的jar包,我导入的有下图中的这些:
2、我们先来实现纯java语言来实现生成excel并导出到指定位置
(ApachePOI将Excel划分为HSSFWorkBook、HSSFSheet、HSSFRow、HSSFCell几部分,按部就班的填充即可)
1 public boolean createExcelModel()throws Exception{ 2 //这是基本步骤,创建一个工作簿,在工作簿上创建一页并命名 3 HSSFWorkBook excel=new HSSFWorkBook(); 4 HSSFSheet sheet=excel.createSheet(); 5 excel.setSheetName(0, "个人信息模板"); 6 //创建第一列的样式 7 HSSFCellStyle style=excel.createCellStyle(); 8 style.setAlignment(HSSFCellStyle.ALIGN_CENTER); style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); style.setBorderBottom(HSSFCellStyle.BORDER_MEDIUM); 9 style.setBorderLeft(HSSFCellStyle.BORDER_MEDIUM); 10 style.setBorderRight(HSSFCellStyle.BORDER_MEDIUM); 11 style.setBorderTop(HSSFCellStyle.BORDER_MEDIUM); 12 //创建第一格中字体样式 13 HSSFFont font=model.createFont(); 14 font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); 15 //将设置的字体样式加入单元格样式中 16 style.setFont(font); 17 //创建第一格单元格,并将之前设置的样式加入 18 HSSFRow row=sheet.createRow((short)0); 19 HSSFCell cell=row.createCell((short)0); 20 cell.setCellValue("个人信息录入"); 21 cell.setCellStyle(style); 22 //这个地方加入每个列都是“”,并不是没有用处的 23 //POI对于合并后边框问题处理并不好,这样更美观些,也可能有其他办法 24 HSSFCell cella=null; 25 for (int i = 1; i < 5; i++) { 26 cella=row.createCell((short)i); 27 cella.setCellValue(""); 28 cella.setCellStyle(style); 29 } 30 //设置接下来两行标题的样式 31 HSSFCellStyle styleTitle=excel.createCellStyle(); 32 //加边框 styleTitle.setBorderBottom(HSSFCellStyle.BORDER_MEDIUM); 33 styleTitle.setBorderLeft(HSSFCellStyle.BORDER_MEDIUM); styleTitle.setBorderRight(HSSFCellStyle.BORDER_MEDIUM); 34 styleTitle.setBorderTop(HSSFCellStyle.BORDER_MEDIUM); 35 HSSFFont fontTitle = model.createFont(); 36 fontTitle.setBoldweight((short) 10);// 设置字体的宽度 37 fontTitle.setFontHeightInPoints((short) 10);// 设置字体的高度 38 fontTitle.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);// 粗体显示 39 styleTitle.setFont(fontTitle);// 设置style1的字体 40 styleTitle.setWrapText(true);// 设置自动换行 41 // 设置单元格字体显示居中(左右方向) 42 styleTitle.setAlignment(HSSFCellStyle.ALIGN_CENTER); 43 // 设置单元格字体显示居中(上下方向) styleTitle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); 44 //创建第二行,并将上面设置的标题样式加入 45 HSSFRow rowTitle=sheet.createRow((short)1); 46 //第二行四列数据 47 HSSFCell cellNum=rowTitle.createCell((short)0); 48 cellNum.setCellValue("编号"); 49 cellNum.setCellStyle(styleTitle); 50 HSSFCell cellName=rowTitle.createCell((short)1); 51 cellName.setCellValue("姓名"); 52 cellName.setCellStyle(styleTitle); 53 HSSFCell cellMsg=rowTitle.createCell((short)2); 54 cellMsg.setCellValue("验证信息"); 55 cellMsg.setCellStyle(styleTitle); 56 HSSFCell cellDept=rowTitle.createCell((short)4); 57 cellDept.setCellValue("部门"); 58 cellDept.setCellStyle(styleTitle); 59 //第三行两列数据 60 HSSFRow rowAT=sheet.createRow((short)2); 61 HSSFCell cellS=null; 62 for (int i = 0; i < 2; i++) { 63 cellS=rowAT.createCell((short)i); 64 cellS.setCellValue(""); 65 cellS.setCellStyle(styleTitle); 66 } 67 HSSFCell cellSss=rowAT.createCell((short)2); 68 cellSss.setCellValue("密码"); 69 cellSss.setCellStyle(styleTitle); 70 HSSFCell cellCard=rowAT.createCell((short)3); 71 cellCard.setCellValue("身份证号"); 72 cellCard.setCellStyle(styleTitle); 73 HSSFCell cellD=rowAT.createCell((short)4); 74 cellD.setCellValue(""); 75 cellD.setCellStyle(styleTitle); 76 //将标题的合并合并起来 77 Region region=null; 78 region=new Region((short)0,(short)0,(short)0,(short)4); 79 sheet.addMergedRegion(region); 80 region=new Region((short)1,(short)0,(short)2,(short)0); 81 sheet.addMergedRegion(region); 82 region=new Region((short)1,(short)1,(short)2,(short)1); 83 sheet.addMergedRegion(region); 84 region=new Region((short)1,(short)4,(short)2,(short)4); 85 sheet.addMergedRegion(region); 86 region=new Region((short)1,(short)2,(short)1,(short)3); 87 sheet.addMergedRegion(region); 88 //生成填充表格 89 HSSFRow rowi=null; 90 HSSFCell celli=null; 91 for (int i = 3; i < 10; i++) { 92 rowi=sheet.createRow(i); 93 for (int j = 0; j < 5; j++) { 94 celli=rowi.createCell((short)j); 95 celli.setCellValue(""); 96 celli.setCellStyle(styleTitle); 97 } 98 } 99 for (int i = 0; i < 5; i++) { 100 sheet.setColumnWidth((short) i, (short) 4000); 101 } 102 }