1 packagecom.eptok.util;2
3 importjava.io.ByteArrayOutputStream;4 importjava.io.FileOutputStream;5 importjava.io.IOException;6 importjava.io.OutputStream;7 importjava.io.UnsupportedEncodingException;8 importjava.math.BigDecimal;9 importjava.text.DecimalFormat;10 importjava.util.ArrayList;11 importjava.util.HashMap;12 importjava.util.List;13 importjava.util.Map;14
15 importjavax.servlet.http.HttpServletResponse;16
17 importorg.apache.poi.hssf.util.HSSFColor;18 importorg.apache.poi.ss.usermodel.Cell;19 importorg.apache.poi.ss.usermodel.CellStyle;20 importorg.apache.poi.ss.usermodel.Font;21 importorg.apache.poi.ss.usermodel.HorizontalAlignment;22 importorg.apache.poi.ss.usermodel.Row;23 importorg.apache.poi.ss.usermodel.Sheet;24 importorg.apache.poi.ss.usermodel.VerticalAlignment;25 importorg.apache.poi.ss.util.CellRangeAddress;26 importorg.apache.poi.xssf.streaming.SXSSFSheet;27 importorg.apache.poi.xssf.streaming.SXSSFWorkbook;28
29 importhikefa.core.web.page.Pager;30
31 public classExportExcle {32
33 /**最大导出行数*/
34 public static final int MAX_ROWS = 500000;35
36 /**分页行数*/
37 public static final int PAGING_ROWS = 50000;38
39 /**SXSSF操作行数*/
40 public static final int SXSSF_ROWS = 100;41
42 /**缓存行数*/
43 public static final int CACHE_ROWS = 1000;44
45 /**创建Workbook*/
46 SXSSFWorkbook workbook = newSXSSFWorkbook(SXSSF_ROWS);47
48 /**当前Sheet*/
49 Sheet sheet;50
51 /**内容总数*/
52 private int contentCount = 0;53
54 /**总页数*/
55 private intpageCount;56
57 /**分页列表*/
58 private List pagerList = new ArrayList<>();59
60 /**标题*/
61 privateString title;62
63 /**表头数组*/
64 privateObject[][] headerArray;65
66 /**导出列数*/
67 private intcolCount;68 /**标题行数*/
69 private int titleRows = 0;70 /**标题行数*/
71 private int headerRows = 0;72
73 /**样式Map*/
74 private Map styleMap = new HashMap<>();75
76 /**列宽数组*/
77 privateInteger[] intArray;78
79 /**构造方法*/
80 publicExportExcle() {81 }82 // //***Demo***83 //ExportExcle exportExcle = new ExportExcle();//新建导出对象84 //int contentCount = 0;//从数据库获取内容总数(可选)----------step_0(数据量大于50000,建议设置)85 //exportExcle.setContentCount(contentCount);//设置内容总数(可选)----------step_0(数据量大于50000,建议设置)86 //Object[] headerArray = new Object[] {//表头数组87 //"",88 //""};89 //exportExcle.setTitleAndHeader("标题", headerArray);//设置标题和表头----------step_190 // //遍历分页列表进行操作91 //for(Pager pager : exportExcle.getPagerList()) {92 //List contentList = new ArrayList<>();//内容列表93 // //---------- 将从数据库获取的数据封装成List开始94 //Paginater paginater = server.findSplitPage(pager);95 //for(Object object : paginater.getData()) {96 //Map map = (Map) object;97 //Object[] objArr = new Object[] {};98 //contentList.add(objArr);//增加内容99 //}100 // //---------- 将从数据库获取的数据封装成List结束101 //exportExcle.setContentPagerDate(contentList, pager);//设置需要导出的内容列表----------step_2102 //}103 //exportExcle.exportWorkbook(response);//将文件写入输出流----------step_3
104
105
106 /**step_0:设置内容总数(不设置则默认为单页导出)*/
107 public void setContentCount(intcontentCount) {108 this.contentCount = contentCount; //设置内容总数
109 }110
111 /**step_1:设置标题和表头数组(单行),并初始化参数*/
112 public voidsetTitleAndHeader(String title, Object[] headerArray) {113 Object[][] headerArrayTemp = new Object[1][];114 headerArrayTemp[0] =headerArray;115 setTitleAndHeader(title, headerArrayTemp);116 }117 /**step_1:设置标题和表头数组(多行),并初始化参数*/
118 public voidsetTitleAndHeader(String title, Object[][] headerArray) {119 this.title =title;120 this.headerArray =headerArray;121 parameterChecking(); //校验参数
122 }123
124 /**step_2:设置需要导出的内容列表*/
125 public void setContentPagerDate(ListcontentList, Pager pager) {126 LogUtil.APP.info("开始将[" + title + "] - 第" + pager.getPageNumber() +"页数据写入Excle文件 - "
127 + DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss"));128 if(null == contentList ||contentList.isEmpty()) {129 throw new IllegalArgumentException("查询不到需要导出的数据[contentList]");130 }131 //---------- 导出数据到Excle文件Sheet页开始
132 String sheetName = "第" + pager.getPageNumber() +"页 - 共" + pageCount + "页"; //sheet名称
133 sheet = workbook.createSheet(sheetName); //创建工作表
134 writeTitle(); //写入标题
135 writeHeader(); //写入表头数组
136 writeContent(contentList); //写入内容列表
137 autoColumnSize(); //自适应列宽,并冻结窗格138 //---------- 导出数据到Excle文件Sheet页结束
139 contentList.clear(); //清空列表
140 LogUtil.APP.info("将[" + title + "] - 第" + pager.getPageNumber() +"页数据写入Excle文件结束 - "
141 + DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss"));142 }143
144 /**step_3:将文件写入输出流*/
145 public voidexportWorkbook() {146 exportWorkbook("D:/"); //默认导出到D盘根目录
147 }148 /**step_3:将文件写入输出流*/
149 public voidexportWorkbook(String path) {150 FileOutputStream fos = null;151 try{152 fos = new FileOutputStream(path + title + ".xlsx");153 workbook.write(fos);154 ((SXSSFWorkbook) workbook).dispose();155 } catch(IOException e) {156 e.printStackTrace();157 } finally{158 if (fos != null) {159 try{160 fos.close();161 } catch(IOException e) {162 e.printStackTrace();163 }164 }165 }166 }167 /**step_3:将文件写入输出流*/
168 public voidexportWorkbook(HttpServletResponse response) {169 ByteArrayOutputStream baos = null;170 OutputStream os = null;171 try{172 baos = newByteArrayOutputStream();173 workbook.write(baos);174 ((SXSSFWorkbook) workbook).dispose();175 String fileName = new String(title.getBytes("gbk"), "ISO8859-1");176 response.reset(); //清空输出流
177 response.setHeader("Content-disposition", "attachment; filename=" + fileName + ".xlsx");178 response.setContentType("application/msexcel");179 response.setContentLength(baos.size());180 os =response.getOutputStream();181 baos.writeTo(os);182 os.flush();183 } catch(IOException e) {184 e.printStackTrace();185 } finally{186 if (baos != null) {187 try{188 baos.close();189 } catch(IOException e) {190 e.printStackTrace();191 }192 }193 if (os != null) {194 try{195 os.close();196 } catch(IOException e) {197 e.printStackTrace();198 }199 }200 }201 }202
203
204 //--------------------------------------------------调用的方法--------------------------------------------------
205
206
207 /**校验参数*/
208 private voidparameterChecking() {209 if(null ==title) {210 throw new IllegalArgumentException("标题未设置");211 }212 if(null == headerArray || headerArray.length == 0) {213 throw new IllegalArgumentException("表头数组未设置");214 } else{215 if(null != headerArray[0] && 0 < headerArray[0].length) {216 headerRows = headerArray.length; //设置表头行数
217 colCount = headerArray[0].length; //设置导出列数
218 intArray = new Integer[colCount]; //初始化列宽数组
219 } else{220 throw new IllegalArgumentException("无法确定导出列数");221 }222 }223 if(contentCount <= 0) {224 contentCount = PAGING_ROWS; //默认为单页导出
225 }226 setPagerList(); //设置分页信息
227 initStyleMap(); //初始化样式Map
228 }229
230 /**设置分页列表*/
231 private voidsetPagerList() {232 if(contentCount >MAX_ROWS) {233 contentCount =MAX_ROWS;234 }235 //计算总页数
236 pageCount = contentCount % PAGING_ROWS > 0 ? contentCount / PAGING_ROWS + 1 : contentCount /PAGING_ROWS;237 //设置分页列表
238 for (int i = 1; i <= pageCount; i++) {239 //int paging = i == pageCount && contentCount % PAGING_ROWS > 0 ?240 //contentCount % PAGING_ROWS : PAGING_ROWS;//当前分页行数241 //pagingList.add(i, new Pager(i, paging));
242 pagerList.add(newPager(i, PAGING_ROWS));243 }244 }245 /**获取分页列表*/
246 public ListgetPagerList() {247 returnpagerList;248 }249
250
251 //--------------------------------------------------Excle操作--------------------------------------------------
252
253
254 /**写入表头标题*/
255 private voidwriteTitle() {256 //创建行对象
257 Row row = sheet.createRow(0); //创建行对象
258 Cell cell = row.createCell(0); //创建单元格
259 cell.setCellValue(title); //写入内容
260 setRowStyle(0, styleMap.get("titleStyle")); //设置行样式
261 mergedRegion(0, 0, 0, colCount-1); //合并单元格
262 titleRows = 1; //记录标题行数
263 }264
265 /**写入表头数组headerArray[row][col]*/
266 private voidwriteHeader() {267 for(int rowNum=0; rowNum < headerRows; rowNum++) {268 if(null == headerArray[rowNum] || 0 ==headerArray[rowNum].length) {269 continue; //行数据为空,跳出当次循环
270 }271 //创建行对象
272 Row row = sheet.createRow(rowNum +titleRows);273 for(int colNum=0; colNum < colCount; colNum++) {274 Cell cell = row.createCell(colNum); //创建单元格
275 cell.setCellStyle(styleMap.get("headerStyle")); //设置表头样式
276 if(null == headerArray[rowNum][colNum] || "*".equals(headerArray[rowNum][colNum])) {277 continue; //单元格数据为空,跳出当次循环
278 }279 setCellValue(cell, headerArray[rowNum][colNum], colNum); //写入内容值
280 }281 }282 }283
284 /**写入内容列表contentList*/
285 private void writeContent(ListcontentList) {286 for(int rowNum = 0; rowNum < contentList.size(); rowNum++) {287 Object[] array =contentList.get(rowNum);288 if(null == array || 0 ==array.length) {289 continue; //数组为空,跳出当次循环
290 }291 //创建行对象
292 Row row = sheet.createRow(rowNum + titleRows + titleRows); //在表头之后
293 for(int colNum = 0; colNum < array.length; colNum++) {294 if(null ==array[colNum]) {295 continue; //跳出当次循环
296 }297 Cell cell = row.createCell(colNum); //创建单元格
298 cell.setCellStyle(styleMap.get("contentStyle")); //设置样式
299 setCellValue(cell, array[colNum], colNum); //写入内容值
300 }301 //每当行数达到设置的值就刷新数据到硬盘,以清理内存
302 if(rowNum % CACHE_ROWS == 0){303 try{304 ((SXSSFSheet) sheet).flushRows();305 } catch(IOException e) {306 e.printStackTrace();307 }308 }309 }310 autoMergedRegion(); //自动合并单元格
311 }312
313 /**自适应列宽*/
314 private voidautoColumnSize() {315 /*//自适应列宽316 for(int colNum=0; colNum
324 //批量设置列宽
325 for(int i=0; i
328 intArray[i] =sheet.getDefaultColumnWidth();329 }330 sheet.setColumnWidth(i, (int)((intArray[i] + 2 + 0.72) * 256)); //参数为列index,列宽(字符数)
331 }332 //冻结窗格
333 sheet.createFreezePane(0, titleRows + headerRows, 0, titleRows +headerRows);334 }335
336
337
338 /**设置单元格的值*/
339 private void setCellValue(Cell cell, Object obj, intcolNum) {340 //格式化参数
341 if(obj instanceof BigDecimal || obj instanceofDouble) {342 Double decimal = Double.valueOf(obj.toString().replace(" ", ""));343 obj = new DecimalFormat("#0.00").format(decimal);344 }345 cell.setCellValue(obj.toString()); //写入内容
346 try{347 int length = obj.toString().getBytes("gbk").length;348 if(intArray[colNum] == null || intArray[colNum]
356 /**自动合并单元格*/
357 private voidautoMergedRegion() {358 if(null == headerArray || 0 ==headerArray.length) {359 return; //表头数组为空,退出方法
360 }361 if(null == headerArray[0][0]) {362 headerArray[0][0] = ""; //初始项不能空
363 }364 //设置表头数值
365 for(int rowNum=0; rowNum < headerRows; rowNum++) {366 for(int colNum=0; colNum < colCount; colNum++) {367 if(null != headerArray[rowNum][colNum] && !"*".equals(headerArray[rowNum][colNum])) {368 autoMergedRegion(rowNum ,colNum); //执行合并操作
369 }370 }371 }372 }373 /**执行合并操作*/
374 private void autoMergedRegion(int firstRow ,intfirstCol) {375 int lastRow = headerRows - 1; //最后一行
376 int lastCol = colCount - 1; //最后一列377 //如果不为最后一行
378 if(firstRow !=lastRow) {379 for(int row = firstRow+1; row < headerRows; row++) {380 if(null !=headerArray[row][firstCol]) {381 if("*".equals(headerArray[row][firstCol])) {382 lastRow = row; //定位最后一行,占位符不减1
383 } else{384 lastRow = row-1; //定位最后一行
385 }386 break;387 }388 }389 }390 //如果不为最后一列
391 if(firstCol !=lastCol) {392 for(int col=firstCol+1; col < colCount; col++) {393 if(null !=headerArray[firstRow][col]) {394 if("*".equals(headerArray[firstRow][col])) {395 lastCol = col; //定位最后一列,占位符不减1
396 } else{397 lastCol = col-1; //定位最后一列
398 }399 break;400 }401 }402 }403 if(firstRow == lastRow && firstCol ==lastCol) {404 return; //无操作,不执行方法
405 }406 mergedRegion(firstRow + titleRows, lastRow +titleRows, firstCol, lastCol);407 }408 /**合并单元格*/
409 private void mergedRegion(int firstRow, int lastRow, int firstCol, intlastCol) {410 sheet.addMergedRegion(newCellRangeAddress(firstRow, lastRow, firstCol, lastCol));411 }412
413 /**设置行样式*/
414 private void setRowStyle(introwNum, CellStyle style) {415 if(null ==style) {416 return; //样式为空,退出方法
417 }418 Row row =sheet.getRow(rowNum);419 if(row == null) {420 row = sheet.createRow(rowNum); //如果行对象为空,则创建
421 }422 for(int colNum = 0; colNum < colCount; colNum++) {423 Cell cell=row.getCell(colNum);424 if( cell == null){425 cell =row.createCell(colNum);426 cell.setCellValue("");427 }428 cell.setCellStyle(style); //设置样式
429 }430 }431
432 /**初始化样式Map*/
433 private voidinitStyleMap() {434 CellStyle titleStyle =workbook.createCellStyle();435 titleStyle.setAlignment(HorizontalAlignment.CENTER);//水平对齐方式
436 titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直对齐方式437 //style.setFillForegroundColor(HSSFColor.AQUA.index);//前景色438 //style.setFillPattern(FillPatternType.SOLID_FOREGROUND);//模式(前景色)439 //style.setWrapText(true);//自动换行
440 Font font1 = workbook.createFont();//生成一个字体
441 font1.setColor(HSSFColor.RED.index);//字体颜色
442 font1.setFontHeightInPoints((short) 16);//字体大小443 //font.setBold(true);//字体加粗
444 font1.setFontName("Arial");//字体名称
445 titleStyle.setFont(font1);//设置字体
446 styleMap.put("titleStyle", titleStyle); //放入样式Map
447
448 CellStyle headerStyle =workbook.createCellStyle();449 headerStyle.setAlignment(HorizontalAlignment.CENTER);//水平对齐方式
450 headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直对齐方式451 //style.setBorderTop(BorderStyle.THIN);//上边框452 //style.setBorderBottom(BorderStyle.THIN);//下边框453 //style.setBorderLeft(BorderStyle.THIN);//左边框454 //style.setBorderRight(BorderStyle.THIN);//右边框
455 Font font2 = workbook.createFont();//生成一个字体
456 font2.setColor(HSSFColor.BLUE.index);//字体颜色
457 font2.setFontHeightInPoints((short) 10);//字体大小
458 font2.setFontName("Arial");//字体名称
459 headerStyle.setFont(font2);//设置字体
460 styleMap.put("headerStyle", headerStyle); //放入样式Map
461
462 CellStyle contentStyle =workbook.createCellStyle();463 contentStyle.setAlignment(HorizontalAlignment.CENTER);//水平对齐方式
464 contentStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直对齐方式
465 Font font3 = workbook.createFont();//生成一个字体
466 font3.setFontHeightInPoints((short) 10);//字体大小
467 font3.setFontName("Arial");//字体名称
468 contentStyle.setFont(font3);//设置字体
469 styleMap.put("contentStyle", contentStyle); //放入样式Map
470 }471
472 }