JAVA基于POI的excel模板的导出!

最近学习了点新知识,关于excel的模板,向模板中插入数据然后在导出,就此记录一下。原理和freemarker有点类似,基于POI的基础上进行实现的excel模板导出。实现的功能是前端通过导出按钮调用后台的模板,然后把模板中的数据进行替换。

首先是工具类

AutoExcel

package com.jiuyisoft.utils.excelUtils;import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.*;public class AutoExcel {protected XSSFWorkbook workbook = null;public AutoExcel(String patternPath) throws IOException {loadWorkbook(patternPath);}protected void loadWorkbook(String path) throws IOException {FileInputStream fis = new FileInputStream(path);workbook = new XSSFWorkbook(fis);fis.close();OutputStream output = new FileOutputStream(path);workbook.write(output);output.flush();output.close();}public ExcelSheetGenerator getSheetGenerator(int patternSheetIndex, Object entity) {ExcelSheetGenerator result = null;XSSFSheet newSheet = workbook.cloneSheet(patternSheetIndex);result = new ExcelSheetGenerator(newSheet, entity);return result;}public void removeSheetRange(int startIndex, int count) {for (int i = 0; i < count; i++) {workbook.removeSheetAt(startIndex);}}public void save(String path) throws IOException {FileOutputStream fos = null;fos = new FileOutputStream(path);workbook.write(fos);fos.close();workbook.close();}public XSSFWorkbook getWorkbook() {return workbook;}
}

ExcelSheetGenerator

package com.jiuyisoft.utils.excelUtils;import java.util.List;import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.CellCopyPolicy;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTTwoCellAnchor;@SuppressWarnings(value = "all")
public class ExcelSheetGenerator {public static class PatternAction {public enum ActionEnum {Replace, ForEach, Unknown}public ActionEnum action;public String field;public PatternAction(ActionEnum action, String field) {this.action = action;this.field = field;}public static boolean isAction(String text) {return (text.indexOf("{{") != -1) && (text.indexOf("}}") != -1);}public static PatternAction generateAction(String text) {if (!isAction(text)) {return null;}ActionEnum actionEnum = ActionEnum.Unknown;String[] items = text.replace("{{", "").replace("}}", "").split("#");if (items.length < 2) {return null;}if (items[0].equals("replace")) {actionEnum = ActionEnum.Replace;} else if (items[0].equals("foreach")) {actionEnum = ActionEnum.ForEach;}
//            else if (items[0].equals("SpecialStyle")) actionEnum = ActionEnum.SpecialStyle;return new PatternAction(actionEnum, items[1].trim());}}protected CellCopyPolicy cellCopyPolicy;protected XSSFSheet patternSheet = null;protected Object entity = null;protected int increaseRows = 0;public ExcelSheetGenerator(XSSFSheet sheet, Object entity) {patternSheet = sheet;this.entity = entity;initConfig();}protected void initConfig() {cellCopyPolicy = (new CellCopyPolicy.Builder()).copyHyperlink(true).cellFormula(true).cellStyle(true).cellValue(true).condenseRows(true).mergedRegions(true).mergeHyperlink(true).rowHeight(true).build();}public static void setCellValue(XSSFCell cell, Object obj) {if (obj instanceof Integer) {cell.setCellValue((Integer) obj);} else if (obj instanceof Double) {cell.setCellValue((Double) obj);} else {cell.setCellValue(String.valueOf(obj));}}public int processPattern(XSSFCell cell, PatternAction action) {try {if (action.action == PatternAction.ActionEnum.Replace) {//cell.setCellValue(entity.getStringByName(action.field));setCellValue(cell, ReflectUtils.getObjectByName(entity, action.field));return 0;
//            } else if(action.action == PatternAction.ActionEnum.SpecialStyle) {
//            	setCellValue(cell, ReflectUtils.getObjectByName(entity, action.field));
//            	XSSFCellStyle xssfCellStyle = new XSSFCellStyle(null);
//            	xssfCellStyle.setFillForegroundColor(IndexedColors.GREY_40_PERCENT.getIndex());
//            	cell.setCellStyle(xssfCellStyle);
//                return 0;} else if (action.action == PatternAction.ActionEnum.ForEach) {int startIndex = cell.getRowIndex();XSSFSheet sheet = cell.getSheet();XSSFRow patternRow = sheet.getRow(startIndex + 1);/*int startColIndex = -1, endColIndex = -1;for (int i = cell.getColumnIndex(); i < patternRow.getLastCellNum(); i++) {if (startColIndex == -1) {if (PatternAction.isAction(patternRow.getCell(i).toString())) startColIndex = i;} else {if (PatternAction.isAction(patternRow.getCell(i).toString())) endColIndex = i;else}}String[] fieldPattern = getFieldPattern(patternRow);*/List repeatItem = ReflectUtils.getListByName(entity, action.field);if (repeatItem.size() == 0) {return 0;}sheet.shiftRows(startIndex + 2, sheet.getLastRowNum(), repeatItem.size());int rowIndex = startIndex + 2;for (Object obj : repeatItem) {XSSFRow row = sheet.createRow(rowIndex++);row.copyRowFrom(patternRow, cellCopyPolicy);for (int i = cell.getColumnIndex(); i < patternRow.getLastCellNum(); i++) {String cellText = patternRow.getCell(i).toString().trim().replace("\n", "");if (!PatternAction.isAction(cellText)) {continue;}XSSFCell detailCell = row.getCell(i);String[] items = cellText.replace("{{", "").replace("}}", "").split("##");Object value = null;value = ReflectUtils.getObjectByName(obj, items[0]);if (items.length == 3) {XSSFCellStyle xssfCellStyle = sheet.getWorkbook().createCellStyle();xssfCellStyle.setBorderTop(detailCell.getCellStyle().getBorderTopEnum());xssfCellStyle.setBorderLeft(detailCell.getCellStyle().getBorderLeftEnum());xssfCellStyle.setBorderRight(detailCell.getCellStyle().getBorderRightEnum());xssfCellStyle.setBorderBottom(detailCell.getCellStyle().getBorderBottomEnum());xssfCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);if (value != null && !"".equals(String.valueOf(value).trim())) {//有值时if (items[1].startsWith("F")) {//配置前景色xssfCellStyle.setFillForegroundColor(Short.parseShort(items[1].substring(1)));} else if (items[1].startsWith("B")) {//配置背景色  遮蔽文字xssfCellStyle.setFillBackgroundColor(Short.parseShort(items[1].substring(1)));}} else {//无值时if (items[2].startsWith("F")) {//配置前景色xssfCellStyle.setFillForegroundColor(Short.parseShort(items[2].substring(1)));} else if (items[2].startsWith("B")) {//配置背景色  遮蔽文字xssfCellStyle.setFillBackgroundColor(Short.parseShort(items[2].substring(1)));}}row.getCell(i).setCellStyle(xssfCellStyle);}/*if (cellText.contains("unitPrice")) row.getCell(i).setCellValue(Double.valueOf(value));else row.getCell(i).setCellValue(value);*/setCellValue(row.getCell(i), value);}}sheet.removeRow(patternRow);sheet.removeRow(sheet.getRow(startIndex));sheet.shiftRows(startIndex + 2, sheet.getLastRowNum(), -2);return repeatItem.size() - 2;}} catch (NoSuchFieldException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}return 0;}private static String[] getFieldPattern(XSSFRow patternRow) {int count = patternRow.getLastCellNum() - patternRow.getFirstCellNum();String[] pattern = new String[count];for (int i = 0; i < count; i++) {pattern[i] = patternRow.getCell(i).toString();}return pattern;}public void replaceSheet(XSSFSheet sheet) {for (int i = 0; i < sheet.getLastRowNum(); i++) {//  print("get row:" + i);XSSFRow row = sheet.getRow(i);if (row == null) {continue;}for (int j = row.getFirstCellNum(); j <= row.getLastCellNum(); j++) {if (j < 0) {continue;}XSSFCell cell = row.getCell(j);if (cell == null) {continue;}PatternAction patternAction = PatternAction.generateAction(cell.toString());if (patternAction == null) {continue;}int incRows = processPattern(cell, patternAction);increaseRows += incRows;if (patternAction.action == PatternAction.ActionEnum.ForEach) {i += incRows + 1;}}}}public void processImages() {if (patternSheet.getDrawingPatriarch() == null|| patternSheet.getDrawingPatriarch().getCTDrawing().getTwoCellAnchorArray() == null) {return;}for (CTTwoCellAnchor cellAnchor : patternSheet.getDrawingPatriarch().getCTDrawing().getTwoCellAnchorArray()) {if (cellAnchor.getPic() == null) {continue;}CTNonVisualDrawingProps props = cellAnchor.getPic().getNvPicPr().getCNvPr();if (props == null || !props.getDescr().equals("{{relocal}}")) {continue;}CTMarker fromMark = cellAnchor.getFrom();CTMarker toMark = cellAnchor.getTo();fromMark.setRow(fromMark.getRow() + increaseRows);toMark.setRow(toMark.getRow() + increaseRows);cellAnchor.setFrom(fromMark);cellAnchor.setTo(toMark);}}public XSSFSheet generate() {return generate("");}public XSSFSheet generate(String newName) {return generate(newName, true);}public XSSFSheet generate(String newName, boolean processImage) {replaceSheet(patternSheet);if (processImage) {processImages();}patternSheet.setForceFormulaRecalculation(true);if (!newName.isEmpty()) {XSSFWorkbook workbook = patternSheet.getWorkbook();workbook.setSheetName(workbook.getSheetIndex(patternSheet), newName);}return patternSheet;}
}
 

因为在项目中使用的是基于SpringBoot JPA框架运作的,所以我们在Service层、实现层和Resource层中进行我们数据的替换

Service层

在这里插入图片描述

ServiceImpl层

 /*** @Description: 订单excel生成* @Author: YiZhiqiang* @Params: branchWarehouseOrderDto 页面传递的实体类* @Return:* @Date: 2019/11/8 3:54 下午*/@Overridepublic XSSFWorkbook exportExcel(BranchWarehouseOrderDto branchWarehouseOrderDto) {File path = null;String templatePath = "";Warehouse warehouseName = this.warehouseService.findOne(branchWarehouseOrderDto.getApplicationWarehouseId());Institution institution = this.institutionService.findOne(Long.parseLong(branchWarehouseOrderDto.getDeliveryInstitutionId()));try {//根据仓库id获取仓库名branchWarehouseOrderDto.setApplicationWarehouseId(warehouseName.getName());//根据组织id获取组织名branchWarehouseOrderDto.setDeliveryInstitutionId(institution.getOrganizationName());if(branchWarehouseOrderDto.getToolsType().equals("PackageTools")){path = new File(ResourceUtils.getURL("classpath").getPath());if (!path.exists()) {path = new File("");}templatePath = path.getAbsolutePath() + "\\target\\classes\\excelTemplate\\成套调拨申请单模板.xlsx";}else if(branchWarehouseOrderDto.getToolsType().equals("ScatteringTools")){path = new File(ResourceUtils.getURL("classpath").getPath());if (!path.exists()) {path = new File("");}templatePath = path.getAbsolutePath() + "\\target\\classes\\excelTemplate\\散件调拨申请单模板.xlsx";}//获取模板AutoExcel autoExcel = new AutoExcel(templatePath);//生成excelExcelSheetGenerator generator = autoExcel.getSheetGenerator(0, branchWarehouseOrderDto);generator.generate("Page 1");autoExcel.removeSheetRange(0, 1);//返回文件XSSFWorkbook workbook = autoExcel.getWorkbook();return workbook;} catch (Exception e) {e.printStackTrace();return null;}}/*** @Description: 发货订单excel生成* @Author: Yuanhl* @Params: branchWarehouseOrderDto 页面传递的实体类* @Return:* @Date: 2019-11-15 10:14:08*/@Overridepublic XSSFWorkbook deliveryExportExcel(BranchWarehouseOrderDto branchWarehouseOrderDto) {File path = null;String templatePath = "";Institution institution = this.institutionService.findOne(Long.parseLong(branchWarehouseOrderDto.getDeliveryInstitutionId()));try {
//            //发货方 根据组织id获取组织名branchWarehouseOrderDto.setDeliveryInstitutionId(institution.getOrganizationName());
//            //发货方 根据公司名称获取公司地址branchWarehouseOrderDto.setDeliveryCompanyAddress(institution.getAddress());System.out.println("institution.getAddress = " + institution.getAddress());
//            //发货方 根据公司名获取公司联系电话branchWarehouseOrderDto.setCompanyTel(institution.getPhoneNumber());System.out.println("公司联系电话 = " + institution.getPhoneNumber());path = new File(ResourceUtils.getURL("classpath").getPath());if (!path.exists()) {path = new File("");}templatePath = path.getAbsolutePath() + "\\target\\classes\\excelTemplate\\发货清单模板.xlsx";//获取模板AutoExcel autoExcel = new AutoExcel(templatePath);//生成excelExcelSheetGenerator generator = autoExcel.getSheetGenerator(0, branchWarehouseOrderDto);generator.generate("Page 1");autoExcel.removeSheetRange(0, 1);//返回文件XSSFWorkbook workbook = autoExcel.getWorkbook();return workbook;} catch (Exception e) {e.printStackTrace();return null;}}/*** @Description: 损坏工具excel导出* @Author: Yuanhl* @Params: branchWarehouseOrderDto 页面传递的实体类* @Return:* @Date: 2019-11-15 10:14:08*/@Overridepublic XSSFWorkbook badExportExcel(BranchWarehouseOrderDto branchWarehouseOrderDto) {File path = null;String templatePath = "";Institution institution = this.institutionService.findOne(Long.parseLong(branchWarehouseOrderDto.getDeliveryInstitutionId()));try {//发货方 根据组织id获取组织名branchWarehouseOrderDto.setDeliveryInstitutionId(institution.getOrganizationName());// 根据组织id获去组织架构简称path = new File(ResourceUtils.getURL("classpath").getPath());if (!path.exists()) {path = new File("");}templatePath = path.getAbsolutePath() + "\\target\\classes\\excelTemplate\\损坏工具评审模板.xlsx";//获取模板AutoExcel autoExcel = new AutoExcel(templatePath);//生成excelExcelSheetGenerator generator = autoExcel.getSheetGenerator(0, branchWarehouseOrderDto);generator.generate("Page 1");autoExcel.removeSheetRange(0, 1);//返回文件XSSFWorkbook workbook = autoExcel.getWorkbook();return workbook;} catch (Exception e) {e.printStackTrace();return null;}}

Resource层

 @PostMapping("/exportExcel")@ApiOperation("导出订单信息Excel")@Action(action = "exportExcel",description = "导出订单信息Excel",dataAccessType = "export")public void exportExcel(@RequestBody BranchWarehouseOrderDto branchWarehouseOrderDto, HttpServletResponse response) {try {XSSFWorkbook workbook = branchWarehouseOrderService.exportExcel(branchWarehouseOrderDto);// 导出数据 设置要导出的文件的名字String fileName = "调拨申请单.xlsx";response.setContentType("application/octet-stream");response.setHeader("Content-disposition", "attachment;filename=" + fileName);response.flushBuffer();workbook.write(response.getOutputStream());} catch (IOException e) {e.printStackTrace();}}@PostMapping("/deliveryExportExcel")@ApiOperation("导出订单信息Excel")@Action(action = "deliveryExportExcel",description = "导出发货清单信息Excel",dataAccessType = "export")public void deliveryExportExcel(@RequestBody BranchWarehouseOrderDto branchWarehouseOrderDto, HttpServletResponse response) {try {XSSFWorkbook workbook = branchWarehouseOrderService.deliveryExportExcel(branchWarehouseOrderDto);// 导出数据 设置要导出的文件的名字String fileName = "发货请单.xlsx";response.setContentType("application/octet-stream");response.setHeader("Content-disposition", "attachment;filename=" + fileName);response.flushBuffer();workbook.write(response.getOutputStream());} catch (IOException e) {e.printStackTrace();}}@PostMapping("/badExportExcel")@ApiOperation("损坏工具评审信息Excel")@Action(action = "badExportExcel",description = "损坏工具评审清单信息Excel",dataAccessType = "export")public void badExportExcel(@RequestBody BranchWarehouseOrderDto branchWarehouseOrderDto, HttpServletResponse response) {try {XSSFWorkbook workbook = branchWarehouseOrderService.badExportExcel(branchWarehouseOrderDto);// 导出数据 设置要导出的文件的名字String fileName = "损坏工具评审.xlsx";response.setContentType("application/octet-stream");response.setHeader("Content-disposition", "attachment;filename=" + fileName);response.flushBuffer();workbook.write(response.getOutputStream());} catch (IOException e) {e.printStackTrace();}}

前端按钮导出(基于Angular)

  /*** 导出订单*/output() {this.loading = true;this.service.exportExcel(this.branchWarehouseOrder).subscribe((result) => {const link = document.createElement("a");const blob = new Blob([result.body], {type: 'application/x-xls'});link.setAttribute("href", window.URL.createObjectURL(blob));link.setAttribute("download", new Date().getTime() + ".xlsx");link.style.visibility = "hidden";document.body.appendChild(link);link.click();document.body.removeChild(link);});this.loading = false;}

实现效果如下

excel模板

在这里插入图片描述

模板数据填充之后的效果

在这里插入图片描述
OK! 到了现在基本上已经完成了,但还存在一些小问题,比如明细表中的数据在使用foreach之后会对下面的表格形式进行打乱,查出问题可能是因为这个excel模板不支持上下合并,这就很头痛了。但木得办法,只能用最笨的方法,一行一行了;另外一个问题就是,因为是要根据不同的数据进行导入,然后不同的数据需要勾选不同的复选框,这个功能暂时还未能实现出来555555,等之后实现出来在更新了。仅以此文,记录少年的自己!


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章