package com.chinaztt.mes.common.util.easyexcel; import cn.hutool.core.date.DateUtil; import com.alibaba.excel.EasyExcelFactory; import com.alibaba.excel.ExcelReader; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.metadata.Font; import com.alibaba.excel.metadata.Sheet; import com.alibaba.excel.metadata.Table; import com.alibaba.excel.metadata.TableStyle; import com.alibaba.excel.metadata.*; import com.alibaba.excel.support.ExcelTypeEnum; import com.alibaba.excel.write.metadata.style.WriteCellStyle; import com.alibaba.excel.write.metadata.style.WriteFont; import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; import com.chinaztt.mes.common.util.easyexcel.exception.ExcelException; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.Calendar; import java.util.List; import java.util.Map; /** *@author: Zou, Yu *@description: *@date: 2023/9/24 0024 13:18 **/ public class EasyExcelUtils { public static HorizontalCellStyleStrategy getStyleStrategy() { // 头的策略 WriteCellStyle headWriteCellStyle = new WriteCellStyle(); // 背景设置为灰色 headWriteCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); WriteFont headWriteFont = new WriteFont(); headWriteFont.setFontHeightInPoints((short) 12); // 字体样式 headWriteFont.setFontName("宋体"); headWriteCellStyle.setWriteFont(headWriteFont); // 自动换行 headWriteCellStyle.setWrapped(false); // 水平对齐方式 headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); // 垂直对齐方式 headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 内容的策略 WriteCellStyle contentWriteCellStyle = new WriteCellStyle(); // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定 // contentWriteCellStyle.setFillPatternType(FillPatternType.SQUARES); // 背景白色 contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex()); WriteFont contentWriteFont = new WriteFont(); // 字体大小 contentWriteFont.setFontHeightInPoints((short) 11); // 字体样式 contentWriteFont.setFontName("宋体"); contentWriteCellStyle.setWriteFont(contentWriteFont); // 内容居中对齐 contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); //内容垂直居中 contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); //边框设置 contentWriteCellStyle.setBorderTop(BorderStyle.THIN); contentWriteCellStyle.setBorderRight(BorderStyle.THIN); contentWriteCellStyle.setBorderBottom(BorderStyle.THIN); contentWriteCellStyle.setBorderLeft(BorderStyle.THIN); // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现 return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle); } public static HorizontalCellStyleStrategy getStyleFixedStrategy() { // 头的策略 WriteCellStyle headWriteCellStyle = new WriteCellStyle(); // 背景设置为灰色 headWriteCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); WriteFont headWriteFont = new WriteFont(); headWriteFont.setFontHeightInPoints((short) 12); // 字体样式 headWriteFont.setFontName("Calibri"); headWriteCellStyle.setWriteFont(headWriteFont); // 自动换行 headWriteCellStyle.setWrapped(false); // 水平对齐方式 headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); // 垂直对齐方式 headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 内容的策略 WriteCellStyle contentWriteCellStyle = new WriteCellStyle(); // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定 // contentWriteCellStyle.setFillPatternType(FillPatternType.SQUARES); // 背景白色 contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex()); WriteFont contentWriteFont = new WriteFont(); // 字体大小 contentWriteFont.setFontHeightInPoints((short) 10); // 字体样式 contentWriteFont.setFontName("Calibri"); contentWriteCellStyle.setWriteFont(contentWriteFont); // 内容左对齐 contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT); // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现 return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle); } public static HorizontalCellStyleStrategy getArveStyleStrategy() { // 头的策略 WriteCellStyle headWriteCellStyle = new WriteCellStyle(); // 背景设置为 headWriteCellStyle.setFillForegroundColor(IndexedColors.BLACK.getIndex()); WriteFont headWriteFont = new WriteFont(); headWriteFont.setFontHeightInPoints((short) 12); // 字体样式 headWriteFont.setFontName("Calibri"); headWriteFont.setColor(IndexedColors.WHITE.getIndex()); headWriteCellStyle.setWriteFont(headWriteFont); headWriteCellStyle.setBorderBottom(BorderStyle.MEDIUM); headWriteCellStyle.setLeftBorderColor(IndexedColors.WHITE.getIndex()); headWriteCellStyle.setRightBorderColor(IndexedColors.WHITE.getIndex()); // 自动换行 headWriteCellStyle.setWrapped(true); // 水平对齐方式 headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT); // 垂直对齐方式 headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 内容的策略 WriteCellStyle contentWriteCellStyle = new WriteCellStyle(); // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定 // contentWriteCellStyle.setFillPatternType(FillPatternType.SQUARES); // 背景白色 contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex()); WriteFont contentWriteFont = new WriteFont(); // 字体大小 contentWriteFont.setFontHeightInPoints((short) 10); // 字体样式 contentWriteFont.setFontName("Calibri"); contentWriteCellStyle.setWriteFont(contentWriteFont); // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现 return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle); } /** * 设置response * @param response * @param targetName * @return */ public static HttpServletResponse getResponse(HttpServletResponse response, String targetName){ String fileName; try { fileName = String.valueOf(new StringBuilder() .append(targetName) .append("_") .append(DateUtil.today()) .append(ExcelTypeEnum.XLS.getValue())); fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()); response.setContentType("application/vnd.ms-excel"); response.setHeader("Cache-Control", "no-cache"); response.setHeader("Content-Disposition", "attachment;filename=" + fileName); response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); return response; } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } /** * excel文件读取 * * @param clazz model类型Class对象 * @param excel excel文件对象 * @param model类型泛型 * @return model类型数据集合 * @throws IOException IO异常 */ public static List readModelExcel(Class clazz, MultipartFile excel) throws IOException { ExcelListener excelListener = new ExcelListener<>(); ExcelReader reader = getReader(excel, excelListener); try { reader.getSheets().forEach(sheet -> { sheet.setClazz(clazz); reader.read(sheet); }); } catch (Exception e) { e.printStackTrace(); throw new IOException("请检查导入模板!"); } return excelListener.getDataList(); } /** * * @param clazz model类型Class对象 * @param excel excel文件对象 * @param sheetNumber 指定sheet页 * @param model类型泛型 * @return model类型数据集合 * @throws IOException */ public static List readModelSheetExcel(Class clazz, MultipartFile excel, int sheetNumber) throws IOException { ExcelListener excelListener = new ExcelListener<>(); ExcelReader reader = getReader(excel, excelListener); try { Sheet sheet = reader.getSheets().get(sheetNumber); sheet.setClazz(clazz); reader.read(sheet); } catch (Exception e) { throw new IOException("请检查导入模板!"); } return excelListener.getDataList(); } /** * 获取excel文件读取对象 * * @param excel excel文件对象 * @param excelListener excel事件处理 * @return excel 读取对象 * @throws IOException IO异常 */ private static ExcelReader getReader(MultipartFile excel, ExcelListener excelListener) throws IOException { String filename = excel.getOriginalFilename(); if (filename == null || (!filename.toLowerCase().endsWith(".xls") && !filename.toLowerCase().endsWith(".xlsx") && !filename.toLowerCase().endsWith(".xltm") && !filename.toLowerCase().endsWith(".xlsm"))) { throw new ExcelException(ResponseResultEnum.EXCEL_FILE_EXT_ERROR); } InputStream inputStream = new BufferedInputStream(excel.getInputStream()); return new ExcelReader(inputStream, null, excelListener, false); } /** * 写入数据到导出文件 * * @param clazz model类型Class对象 * @param sheetNo sheet序号 * @param headLineMun head行数 * @param startRow 开始写入行数 * @param tableNo table序号 * @param modelList model数据集合 * @param temp 临时文件对象 * @param export 导出文件对象 * @param model泛型 */ public static void writeModelExport(Class clazz, Integer sheetNo, Integer headLineMun, Integer startRow, Integer tableNo, List modelList, File temp, File export) { try { InputStream inputStream = new FileInputStream(temp); FileOutputStream OutputStream = new FileOutputStream(export); ExcelWriter writer = EasyExcelFactory.getWriterWithTemp(inputStream, OutputStream, ExcelTypeEnum.XLSX, false); writer.write(modelList, initSheet(sheetNo, headLineMun, startRow), initTable(tableNo, clazz)); writer.finish(); OutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } /** * Sheet初始化 * * @param sheetNo sheet序号 * @param headLineMun head行数 * @param startRow 开始写入行数 * @return Sheet对象 */ public static Sheet initSheet(Integer sheetNo, Integer headLineMun, Integer startRow) { Sheet sheet = new Sheet(sheetNo, headLineMun); sheet.setStartRow(startRow); return sheet; } /** * Table初始化 * * @param tableNo table序号 * @param clazz model类型Class对象 * @param model泛型 * @return Table对象 */ public static Table initTable(Integer tableNo, Class clazz) { Table table = new Table(tableNo); table.setClazz(clazz); TableStyle tableStyle = new TableStyle(); tableStyle.setTableContentBackGroundColor(IndexedColors.WHITE); tableStyle.setTableHeadBackGroundColor(IndexedColors.WHITE); Font font = new Font(); font.setBold(false); font.setFontName("宋体"); font.setFontHeightInPoints((short) 11); tableStyle.setTableContentFont(font); table.setTableStyle(tableStyle); return table; } /** * 替换模板标记 * * @param export 导出文件对象 * @param index sheet序号 * @param rows 单元格行序 * @param columns 单元格列序 * @param replaceMap 多个标记集合 */ public static void editModelWorkBook(File export, Integer index, Integer rows, Integer columns, Map replaceMap) { try { XSSFWorkbook workBook = new XSSFWorkbook(export); // editModelWorkBook(workBook,index,0,0,replaceMap); editModelWorkBook(workBook, index, rows, columns, replaceMap); workBook.close(); } catch (IOException | InvalidFormatException e) { e.printStackTrace(); } } /** * 替换模板标记 * * @param workBook excel工作册对象 * @param index sheet序号 * @param rows 单元格行序 * @param columns 单元格列序 * @param replaceMap 多个标记集合 */ public static void editModelWorkBook(XSSFWorkbook workBook, Integer index, Integer rows, Integer columns, Map replaceMap) { XSSFSheet sheet = workBook.getSheetAt(index); Row row = sheet.getRow(rows); Cell cell = row.getCell(columns); String replaceString = cell.toString(); for (Map.Entry entry : replaceMap.entrySet()) { replaceString = replaceString.replace(entry.getKey(), entry.getValue()); } cell.setCellValue(replaceString); workBook.setSheetName(index, replaceString.replace(":", "")); } /** * 模板sheet克隆及命名 * * @param temp 临时文件对象 * @param export 导出文件对象 * @param cloneSheetNo 克隆sheet序列 * @param rows 单元格行序 * @param columns 单元格列序 * @param replaceMapList 多个标记集合 */ public static void writeModelCloneSheet(File temp, File export, Integer cloneSheetNo, Integer rows, Integer columns, List> replaceMapList) { try { XSSFWorkbook workBook = new XSSFWorkbook(temp); OutputStream outputStream = new FileOutputStream(export); /** 如果你需要6份相同模板的sheet 那么你只需要克隆5份即可*/ for (int index = 0; index < replaceMapList.size() - 1; index++) { /** 克隆模板文件 */ XSSFSheet sheet = workBook.cloneSheet(cloneSheetNo); } for (int index = 0; index < replaceMapList.size(); index++) { editModelWorkBook(workBook, index, rows, columns, replaceMapList.get(index)); } workBook.write(outputStream); outputStream.flush(); outputStream.close(); workBook.close(); } catch (IOException | InvalidFormatException e) { e.printStackTrace(); } } /** * 临时文件写入导出文件 * * @param temp 临时文件对象 * @param export 导出文件对象 * @param index sheet序号 * @param rows 单元格行序 * @param columns 单元格列序 * @param isTime 是否有时间标记 */ public static void writeModelWorkBook(File temp, File export, Integer index, Integer rows, Integer columns, Boolean isTime) { try { XSSFWorkbook workBook = new XSSFWorkbook(temp); OutputStream outputStream = new FileOutputStream(export); if (isTime) { writeModelWorkBook(workBook, index, rows, columns); } workBook.write(outputStream); outputStream.flush(); outputStream.close(); workBook.close(); } catch (IOException | InvalidFormatException e) { e.printStackTrace(); } } /** * 替换时间标记(year,month,day) * * @param workBook excel工作册对象 * @param index sheet序号 * @param rows 单元格行序 * @param columns 单元格列序 */ public static void writeModelWorkBook(XSSFWorkbook workBook, Integer index, Integer rows, Integer columns) { XSSFSheet xssfSheet = workBook.getSheetAt(index); Row row = xssfSheet.getRow(rows); Cell cell = row.getCell(columns); String cellString = cell.toString(); Calendar calendar = Calendar.getInstance(); int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH) + 1; int day = calendar.get(Calendar.DAY_OF_MONTH); String yearString = cellString.replace("year", String.valueOf(year)); String monthString = yearString.replace("month", String.valueOf(month)); String dayString = monthString.replace("day", String.valueOf(day)); cell.setCellValue(dayString); } /** * 针对UserModel导出方法 * * @param temp * @param export * @param isTime */ public static void writeModelWorkBook(File temp, File export, Boolean isTime) { writeModelWorkBook(temp, export, 0, 1, 9, isTime); } public static void writeModelCloneSheet(File temp, File export, List> replaceMapList) { writeModelCloneSheet(temp, export, 0, 0, 0, replaceMapList); } }