|
@@ -5,6 +5,7 @@ import com.alibaba.excel.EasyExcel;
|
|
|
import com.alibaba.excel.ExcelWriter;
|
|
|
import com.alibaba.excel.write.metadata.WriteSheet;
|
|
|
import org.apache.poi.ss.usermodel.*;
|
|
|
+import org.apache.poi.ss.util.CellRangeAddress;
|
|
|
import org.apache.poi.ss.util.CellRangeAddressList;
|
|
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
|
|
|
|
@@ -20,10 +21,11 @@ public class EasyExcelUtil {
|
|
|
|
|
|
/**
|
|
|
* 填充动态数据到Excel
|
|
|
- * @param inputFilePath 模板文件路径
|
|
|
+ *
|
|
|
+ * @param inputFilePath 模板文件路径
|
|
|
* @param outputFilePath 输出文件路径
|
|
|
- * @param dataMap 数据map
|
|
|
- * @param evaluate 是否计算公式(大文件慎用,可能会导致内存溢出)
|
|
|
+ * @param dataMap 数据map
|
|
|
+ * @param evaluate 是否计算公式(大文件慎用,可能会导致内存溢出)
|
|
|
*/
|
|
|
public static void fillExcelDataByMap(String inputFilePath, String outputFilePath, Map<String, Object> dataMap, boolean evaluate) {
|
|
|
// 使用EasyExcel填充数据
|
|
@@ -35,7 +37,7 @@ public class EasyExcelUtil {
|
|
|
excelWriter.fill(dataMap, writeSheet); // 填充数据
|
|
|
|
|
|
// 由于填充后不会自动更新公式值,所以需要手动更新
|
|
|
- if (evaluate){
|
|
|
+ if (evaluate) {
|
|
|
Workbook workbook = excelWriter.writeContext().writeWorkbookHolder().getWorkbook();
|
|
|
workbook.getCreationHelper().createFormulaEvaluator().evaluateAll(); // 强制计算公式
|
|
|
}
|
|
@@ -44,10 +46,11 @@ public class EasyExcelUtil {
|
|
|
|
|
|
/**
|
|
|
* 合并Excel文件
|
|
|
- * @param sourceExcelPath 源文件路径(段落模板)
|
|
|
- * @param targetExcelPath 目标文件路径(主模板)
|
|
|
+ *
|
|
|
+ * @param sourceExcelPath 源文件路径(段落模板)
|
|
|
+ * @param targetExcelPath 目标文件路径(主模板)
|
|
|
* @param targetSheetIndex 目标sheet索引(要插入的sheet)
|
|
|
- * @param targetRowNum 目标行索引(要插入的行)
|
|
|
+ * @param targetRowNum 目标行索引(要插入的行)
|
|
|
* @param sourceSheetIndex 源文件被引用的sheet
|
|
|
* @return Workbook 返回工作簿
|
|
|
* @throws IOException 抛出IO异常
|
|
@@ -63,7 +66,7 @@ public class EasyExcelUtil {
|
|
|
Sheet targetSheet = targetWorkbook.getSheetAt(targetSheetIndex); // 获取目标sheet
|
|
|
|
|
|
// 复制样式映射
|
|
|
- Map<Short, Short> styleMap = copyCellStyle(sourceWorkbook, targetWorkbook);
|
|
|
+ Map<Short, Short> styleMap = copyCellStyle(sourceWorkbook, targetWorkbook, targetSheetIndex, sourceSheetIndex);
|
|
|
|
|
|
// 复制行和单元格
|
|
|
for (Row sourceRow : sourceSheet) {
|
|
@@ -84,28 +87,103 @@ public class EasyExcelUtil {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
+ * 合并Excel文件-目标文件为WorkBook方式
|
|
|
+ *
|
|
|
+ * @param sourceExcelPath 源文件路径(段落模板)
|
|
|
+ * @param targetWorkbook 目标工作表(主模板)
|
|
|
+ * @param targetSheetIndex 目标sheet索引(要插入的sheet)
|
|
|
+ * @param targetRowNum 目标行索引(要插入的行)
|
|
|
+ * @param sourceSheetIndex 源文件被引用的sheet
|
|
|
+ * @throws IOException 抛出IO异常
|
|
|
+ */
|
|
|
+ public static void mergeExcel(String sourceExcelPath, Workbook targetWorkbook, int targetSheetIndex, int targetRowNum, int sourceSheetIndex) throws IOException {
|
|
|
+ // 获取源Excel
|
|
|
+ InputStream inputStream = Files.newInputStream(Paths.get(sourceExcelPath));
|
|
|
+ Workbook sourceWorkbook = new XSSFWorkbook(inputStream);
|
|
|
+ Sheet sourceSheet = sourceWorkbook.getSheetAt(sourceSheetIndex);
|
|
|
+
|
|
|
+ // 打开已存在的Excel工作簿
|
|
|
+ Sheet targetSheet = targetWorkbook.getSheetAt(targetSheetIndex); // 获取目标sheet
|
|
|
+
|
|
|
+ // 复制样式映射
|
|
|
+ Map<Short, Short> styleMap = copyCellStyle(sourceWorkbook, targetWorkbook, targetSheetIndex, sourceSheetIndex);
|
|
|
+
|
|
|
+ // 复制行和单元格
|
|
|
+ for (Row sourceRow : sourceSheet) {
|
|
|
+ Row targetRow = targetSheet.createRow(targetRowNum + sourceRow.getRowNum());
|
|
|
+ for (Cell sourceCell : sourceRow) {
|
|
|
+ Cell targetCell = targetRow.createCell(sourceCell.getColumnIndex());
|
|
|
+ copyCell(sourceCell, targetCell, targetWorkbook, styleMap);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 复制数据验证
|
|
|
+ copyDataValidations(sourceSheet, targetSheet);
|
|
|
+
|
|
|
+ sourceWorkbook.close();
|
|
|
+ inputStream.close();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
* 复制单元格样式
|
|
|
- * @param srcBook 源工作簿
|
|
|
- * @param desBook 目标工作簿
|
|
|
+ *
|
|
|
+ * @param srcBook 源工作簿
|
|
|
+ * @param desBook 目标工作簿
|
|
|
+ * @param targetSheetIndex 目标sheet索引
|
|
|
+ * @param sourceSheetIndex 源文件被引用的sheet
|
|
|
* @return Map<Short, Short> 样式
|
|
|
*/
|
|
|
- private static Map<Short, Short> copyCellStyle(Workbook srcBook, Workbook desBook) {
|
|
|
+ private static Map<Short, Short> copyCellStyle(Workbook srcBook, Workbook desBook, int targetSheetIndex, int sourceSheetIndex) {
|
|
|
Map<Short, Short> styleMap = new HashMap<>();
|
|
|
+ // 复制样式
|
|
|
for (short i = 0; i < srcBook.getNumCellStyles(); i++) {
|
|
|
CellStyle srcStyle = srcBook.getCellStyleAt(i);
|
|
|
CellStyle desStyle = desBook.createCellStyle();
|
|
|
desStyle.cloneStyleFrom(srcStyle);
|
|
|
styleMap.put(srcStyle.getIndex(), desStyle.getIndex());
|
|
|
}
|
|
|
+
|
|
|
+ // 复制合并单元格并应用样式
|
|
|
+ Sheet srcSheet = srcBook.getSheetAt(sourceSheetIndex);
|
|
|
+ Sheet destSheet = desBook.getSheetAt(targetSheetIndex);
|
|
|
+
|
|
|
+ // 合并单元格
|
|
|
+ for (int mergeIndex = 0; mergeIndex < srcSheet.getNumMergedRegions(); mergeIndex++) {
|
|
|
+ CellRangeAddress srcRange = srcSheet.getMergedRegion(mergeIndex);
|
|
|
+ // 创建新的合并单元格区域
|
|
|
+ CellRangeAddress newRange = new CellRangeAddress(
|
|
|
+ srcRange.getFirstRow(),
|
|
|
+ srcRange.getLastRow(),
|
|
|
+ srcRange.getFirstColumn(),
|
|
|
+ srcRange.getLastColumn()
|
|
|
+ );
|
|
|
+ destSheet.addMergedRegion(newRange);
|
|
|
+
|
|
|
+ // 获取原合并单元格的样式索引
|
|
|
+ short srcStyleIndex = srcSheet.getRow(srcRange.getFirstRow()).getCell(srcRange.getFirstColumn()).getCellStyle().getIndex();
|
|
|
+ // 应用样式到新合并单元格的左上角单元格
|
|
|
+ short destStyleIndex = styleMap.get(srcStyleIndex);
|
|
|
+ Row destRow = destSheet.getRow(srcRange.getFirstRow());
|
|
|
+ if (destRow == null) {
|
|
|
+ destRow = destSheet.createRow(srcRange.getFirstRow());
|
|
|
+ }
|
|
|
+ Cell destCell = destRow.getCell(srcRange.getFirstColumn());
|
|
|
+ if (destCell == null) {
|
|
|
+ destCell = destRow.createCell(srcRange.getFirstColumn());
|
|
|
+ }
|
|
|
+ destCell.setCellStyle(desBook.getCellStyleAt(destStyleIndex));
|
|
|
+ }
|
|
|
return styleMap;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 复制单元格
|
|
|
- * @param srcCell 源单元格
|
|
|
- * @param desCell 目标单元格
|
|
|
+ *
|
|
|
+ * @param srcCell 源单元格
|
|
|
+ * @param desCell 目标单元格
|
|
|
* @param targetWorkbook 目标工作簿
|
|
|
- * @param styleMap 样式
|
|
|
+ * @param styleMap 样式
|
|
|
*/
|
|
|
private static void copyCell(Cell srcCell, Cell desCell, Workbook targetWorkbook, Map<Short, Short> styleMap) {
|
|
|
// 判断单元格值类型
|
|
@@ -127,6 +205,7 @@ public class EasyExcelUtil {
|
|
|
|
|
|
/**
|
|
|
* 复制数据验证(下拉框)
|
|
|
+ *
|
|
|
* @param sourceSheet 源Sheet
|
|
|
* @param targetSheet 目标Sheet
|
|
|
*/
|
|
@@ -149,29 +228,30 @@ public class EasyExcelUtil {
|
|
|
|
|
|
/**
|
|
|
* 房地产基本信息sheet表单 固定解析函数
|
|
|
+ *
|
|
|
* @param wb
|
|
|
* @param sheetName
|
|
|
* @return
|
|
|
*/
|
|
|
- public static Map<String ,String> getExcelCellValue(Workbook wb, String sheetName) {
|
|
|
- Map<String,String> valueMap = new HashMap<>();
|
|
|
+ public static Map<String, String> getExcelCellValue(Workbook wb, String sheetName) {
|
|
|
+ Map<String, String> valueMap = new HashMap<>();
|
|
|
Sheet sheet = wb.getSheet(sheetName);// 获取指定名称Sheet的内容
|
|
|
int lastRowNum = sheet.getLastRowNum();
|
|
|
Row rowKey = null;
|
|
|
Row rowValue = null;
|
|
|
Cell cellKey = null;
|
|
|
Cell cellValue = null;
|
|
|
- for (int rowNum = sheet.getFirstRowNum(); rowNum <= lastRowNum/2; rowNum+=2) {
|
|
|
+ for (int rowNum = sheet.getFirstRowNum(); rowNum <= lastRowNum / 2; rowNum += 2) {
|
|
|
rowKey = sheet.getRow(rowNum);
|
|
|
- rowValue = sheet.getRow(rowNum+1);
|
|
|
+ rowValue = sheet.getRow(rowNum + 1);
|
|
|
int lastColNum = rowKey.getLastCellNum();
|
|
|
for (int colNum = 0; colNum <= lastColNum; colNum++) {
|
|
|
cellKey = rowKey.getCell(colNum);
|
|
|
cellValue = rowValue.getCell(colNum);
|
|
|
if (cellKey != null && StrUtil.isNotBlank(cellKey.toString())
|
|
|
- && cellValue != null) {
|
|
|
+ && cellValue != null) {
|
|
|
String attr = cellKey.getHyperlink().getAddress();
|
|
|
- valueMap.put(attr, cellValue.toString());
|
|
|
+ valueMap.put(attr, cellValue.toString());
|
|
|
}
|
|
|
}
|
|
|
}
|