weaver-hrm-salary/src/com/engine/salary/util/excel/ExcelFillUtils.java

205 lines
7.7 KiB
Java
Raw Normal View History

2025-02-06 16:11:39 +08:00
package com.engine.salary.util.excel;
import cn.hutool.core.util.StrUtil;
import com.engine.salary.util.FileUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellUtil;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Pattern;
public class ExcelFillUtils {
// public static final String FILL_EXPRESSION_REGEX = "\\{\\.\\w+\\}";
private static final String FILL_EXPRESSION_REGEX = "\\{\\.[\\p{L}\\p{M}\\S]+\\}";
/**
* 给定模板指定某个页签将数据填充到模板中的指定页签并将数据导入到指定文件上
*
* @param template 模板文件地址
* @param sheetIndex 页签下标
* @param data 待填充的数据,数据格式如下
* [
* {"colName1":v1 ,"colName2":v2...},
* {"colName1":v1 ,"colName2":v2...}
* ,...
* ]
* @return 新生成的副本文件
*/
public static XSSFWorkbook fillOneSheet(String template, Integer sheetIndex, List<Map<String, Object>> data) {
try {
XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(template));
fill(workbook, sheetIndex, data);//填充数据
return workbook;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 给定模板指定某个页签将数据填充到模板中的指定页签并将数据导入到指定文件上
*
* @param template 模板文件流
* @param sheetIndex 页签名称
* @param data 待填充的数据,数据格式如下
* [
* {"colName1":v1 ,"colName2":v2...},
* {"colName1":v1 ,"colName2":v2...}
* ,...
* ]
* @return 新生成的副本文件
*/
public static XSSFWorkbook fillOneSheet(InputStream template, Integer sheetIndex, List<Map<String, Object>> data) {
try{
XSSFWorkbook workbook = new XSSFWorkbook(template);
fill(workbook, sheetIndex, data);//填充数据
return workbook;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 给定模板,将数据填充到模板中的多个页签并在模板所在目录生成新的副本文件
*
* @param template 模板文件地址
* @param datas 待填充的数据集,数据格式如下
* {
* "SheetName1":[
* {"colName1":v1 ,"colName2":v2...},
* {"colName1":v1 ,"colName2":v2...}
* ,...
* ],
* "SheetName2":[
* {"colName1":v1 ,"colName2":v2...}
* {"colName1":v1 ,"colName2":v2...}
* ,...
* ],
* ...
* }
*/
public static String fillMultipleSheet(String template, Map<Integer, List<Map<String, Object>>> datas) {
return fillMultipleSheet(template, FileUtils.getAvailableFullName(template), datas);
}
/**
* 给定模板,将数据填充到模板中的多个页签并将数据导入到指定文件上
*
* @param template 模板文件地址
* @param datas 待填充的数据集,数据格式如下
* {
* "SheetName1":[
* {"colName1":v1 ,"colName2":v2...},
* {"colName1":v1 ,"colName2":v2...}
* ,...
* ],
* "SheetName2":[
* {"colName1":v1 ,"colName2":v2...}
* {"colName1":v1 ,"colName2":v2...}
* ,...
* ],
* ...
* }
*/
public static String fillMultipleSheet(String template, String outputFile, Map<Integer, List<Map<String, Object>>> datas) {
try (Workbook workbook = new XSSFWorkbook(new FileInputStream(template))) {
datas.forEach((sheetIndex, data) -> fill(workbook, sheetIndex, data));//填充数据
refreshFormula(workbook);//刷新公式
try (FileOutputStream outputStream = new FileOutputStream(outputFile)) {
workbook.write(outputStream);
} catch (Exception e) {
throw new RuntimeException(e);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return outputFile;
}
private static Workbook fill(Workbook workbook, int sheetIndex, List<Map<String, Object>> data) {
Sheet sheet = workbook.getSheetAt(sheetIndex);
if (sheet == null) {
throw new RuntimeException(String.format("sheet [%s] does not exist.", sheetIndex));
}
//找到所有的表达式单元格
Map<String, Cell> expressionCellMap = new HashMap<>();
for (int i = 0; i < sheet.getPhysicalNumberOfRows(); i++) {
Row row = sheet.getRow(i);
for (int j = 0; j < row.getPhysicalNumberOfCells(); j++) {
Cell cell = row.getCell(j);
if (!Objects.isNull(cell) && isFillExpression(cell.getStringCellValue())) {//判断该单元格是否是填充公式
expressionCellMap.put(getColNameFromEx(cell.getStringCellValue()), cell);
}
}
}
//填充数据
for (int i = 0; i < data.size(); i++) {
Map<String, Object> dataRow = data.get(i);
for (Map.Entry<String, Object> entry : dataRow.entrySet()) {
String colName = entry.getKey();
Object value = entry.getValue();
if (expressionCellMap.containsKey(colName)) {
Cell cell = expressionCellMap.get(colName);//公式所在的单元格
int rowID = cell.getRowIndex() + i;
int colId = cell.getColumnIndex();
Row fillRow = sheet.getRow(rowID);
fillRow = Objects.isNull(fillRow) ? sheet.createRow(rowID) : fillRow;
Cell fillCell = fillRow.getCell(colId);
//创建的新单元格需要复制公式单元格的格式
fillCell = Objects.isNull(fillCell) ? CellUtil.createCell(fillRow, colId, "", cell.getCellStyle()) : fillCell;
if (value instanceof String) {
fillCell.setCellValue(String.valueOf(value));
} else if (value instanceof Number) {
fillCell.setCellValue(((Number) value).doubleValue());
} else {
throw new RuntimeException(String.format("Unsupported data type [%s].", value.getClass().toString()));
}
}
}
}
return workbook;
}
private static void refreshFormula(Workbook workbook) {
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
evaluator.evaluateAll();
}
private static boolean isFillExpression(String ex) {
if (StrUtil.isBlank(ex)) {
return false;
}
;
return Pattern.matches(FILL_EXPRESSION_REGEX, ex);
}
private static String getColNameFromEx(String ex) {
if (!isFillExpression(ex)) throw new RuntimeException("Illegal expression " + ex);
return ex.substring(2, ex.length() - 1);
}
}