|
|
@@ -19,7 +19,6 @@ import com.alibaba.fastjson2.JSONArray;
|
|
|
import com.alibaba.fastjson2.JSONObject;
|
|
|
import com.grapecity.documents.excel.*;
|
|
|
import com.grapecity.documents.excel.drawing.ImageType;
|
|
|
-import com.grapecity.documents.excel.template.DataSource.JsonDataSource;
|
|
|
import jakarta.annotation.Resource;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
@@ -142,23 +141,13 @@ public class ExcelServiceImpl implements ExcelService {
|
|
|
workbookOptions.setPixelBasedColumnWidth(true);
|
|
|
|
|
|
Workbook workbook = new Workbook(workbookOptions);
|
|
|
- // SJS 格式不使用 XlsxOpenOptions,直接以 SJS 方式打开
|
|
|
workbook.open(new ByteArrayInputStream(templateBytes), OpenFileFormat.Sjs);
|
|
|
|
|
|
for (int i = 0; i < workbook.getWorksheets().getCount(); i++) {
|
|
|
IWorksheet worksheet = workbook.getWorksheets().get(i);
|
|
|
|
|
|
- // -- 设置数据源前收集表格合并规则 --
|
|
|
- Map<ITable, List<int[]>> tableMergeInfo = collectTableMergeInfo(worksheet);
|
|
|
-
|
|
|
- // -- 设置数据源 --
|
|
|
- worksheet.setDataSource(new JsonDataSource(JSON.toJSONString(dataMap)));
|
|
|
-
|
|
|
- // -- 表格行样式同步 --
|
|
|
- copyTableRowStyles(worksheet, tableMergeInfo);
|
|
|
-
|
|
|
- // -- 处理单元格图片 --
|
|
|
- handleCellImages(worksheet);
|
|
|
+ // -- 处理单元格图片(用 dataMap 而非 cell value,因为不 setDataSource) --
|
|
|
+ handleCellImages(worksheet, dataMap);
|
|
|
|
|
|
// -- 处理图片字段 (colValType == 4) --
|
|
|
handleImageCols(worksheet, imgCols, dataMap);
|
|
|
@@ -173,26 +162,28 @@ public class ExcelServiceImpl implements ExcelService {
|
|
|
highlightEditableCells(worksheet, editCols);
|
|
|
}
|
|
|
|
|
|
- // 保存为 SJS 格式返回
|
|
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
|
|
workbook.save(outputStream, SaveFileFormat.Sjs);
|
|
|
return outputStream.toByteArray();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 处理单元格中的图片:将以 .jpg/.png 结尾的值替换为图片
|
|
|
- * 参考 PdfServiceImpl.fullPdf() 中的图片处理逻辑
|
|
|
+ * 处理单元格中的图片:以 bindingPath 从 dataMap 取值,将以 .jpg/.png 结尾的值替换为图片
|
|
|
*/
|
|
|
- private void handleCellImages(IWorksheet worksheet) {
|
|
|
+ private void handleCellImages(IWorksheet worksheet, Map<String, Object> dataMap) {
|
|
|
+ if (dataMap == null || dataMap.isEmpty()) return;
|
|
|
IRange usedRange = worksheet.getUsedRange();
|
|
|
if (usedRange == null) return;
|
|
|
|
|
|
for (int row = 0; row < usedRange.getRowCount(); row++) {
|
|
|
for (int col = 0; col < usedRange.getColumnCount(); col++) {
|
|
|
IRange cell = worksheet.getRange(row, col);
|
|
|
- if (cell.getBindingPath() == null || cell.getValue() == null) continue;
|
|
|
+ String bindingPath = cell.getBindingPath();
|
|
|
+ if (bindingPath == null) continue;
|
|
|
|
|
|
- Object valueObj = cell.getValue();
|
|
|
+ // 从 dataMap 取值而非 cell.getValue()(因为后端不 setDataSource)
|
|
|
+ Object valueObj = dataMap.get(bindingPath);
|
|
|
+ if (valueObj == null) continue;
|
|
|
String value = valueObj instanceof String ? (String) valueObj : String.valueOf(valueObj);
|
|
|
|
|
|
if (!value.endsWith(".png") && !value.endsWith(".jpg")) continue;
|
|
|
@@ -386,84 +377,6 @@ public class ExcelServiceImpl implements ExcelService {
|
|
|
.getFormatConditions().add(FormatConditionType.Expression, FormatConditionOperator.None, "=TRUE", null);
|
|
|
// #FFF895 = RGB(255, 248, 149)
|
|
|
condition.getInterior().setColor(Color.FromArgb(255, 255, 248, 149));
|
|
|
- System.out.println(condition.getFormula1());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // ==================== 表格行样式同步 ====================
|
|
|
-
|
|
|
- /**
|
|
|
- * 在 setDataSource 前收集所有表格第一行数据行的合并单元格规则
|
|
|
- * 参考 PdfServiceImpl.collectTableMergeInfo()
|
|
|
- */
|
|
|
- private Map<ITable, List<int[]>> collectTableMergeInfo(IWorksheet worksheet) {
|
|
|
- Map<ITable, List<int[]>> result = new HashMap<>();
|
|
|
- if (worksheet.getTables() == null) return result;
|
|
|
-
|
|
|
- for (int t = 0; t < worksheet.getTables().getCount(); t++) {
|
|
|
- ITable table = worksheet.getTables().get(t);
|
|
|
- IRange tableRange = table.getRange();
|
|
|
- int firstDataRow = tableRange.getRow() + 1;
|
|
|
- int firstDataCol = tableRange.getColumn();
|
|
|
- int colCount = tableRange.getColumnCount();
|
|
|
-
|
|
|
- List<int[]> mergeRanges = new ArrayList<>();
|
|
|
- try {
|
|
|
- for (int c = firstDataCol; c < firstDataCol + colCount; c++) {
|
|
|
- IRange cell = worksheet.getRange(firstDataRow, c);
|
|
|
- IRange mergeArea = cell.getMergeArea();
|
|
|
- if (mergeArea != null && mergeArea.getColumnCount() > 1) {
|
|
|
- mergeRanges.add(new int[]{mergeArea.getColumn(), mergeArea.getColumnCount()});
|
|
|
- c = mergeArea.getColumn() + mergeArea.getColumnCount() - 1;
|
|
|
- }
|
|
|
- }
|
|
|
- } catch (Exception ignored) {
|
|
|
- }
|
|
|
- result.put(table, mergeRanges);
|
|
|
- }
|
|
|
- return result;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 将第一行数据行的样式、行高、合并规则复制到所有自动扩展的数据行
|
|
|
- * 参考 PdfServiceImpl.copyTableRowStyles()
|
|
|
- */
|
|
|
- private void copyTableRowStyles(IWorksheet worksheet, Map<ITable, List<int[]>> tableMergeInfo) {
|
|
|
- if (worksheet.getTables() == null) return;
|
|
|
-
|
|
|
- for (int t = 0; t < worksheet.getTables().getCount(); t++) {
|
|
|
- ITable table = worksheet.getTables().get(t);
|
|
|
- IRange tableRange = table.getRange();
|
|
|
- int rowCount = tableRange.getRowCount();
|
|
|
- int colCount = tableRange.getColumnCount();
|
|
|
- if (rowCount <= 1) continue;
|
|
|
-
|
|
|
- int firstDataRow = tableRange.getRow();
|
|
|
- int firstDataCol = tableRange.getColumn();
|
|
|
-
|
|
|
- List<int[]> mergeColRanges = tableMergeInfo.getOrDefault(table, new ArrayList<>());
|
|
|
-
|
|
|
- double firstRowHeight = worksheet.getRange(firstDataRow, firstDataCol).getRowHeight();
|
|
|
- IRange sourceRow = worksheet.getRange(firstDataRow, firstDataCol, 1, colCount);
|
|
|
-
|
|
|
- for (int r = 1; r < rowCount; r++) {
|
|
|
- int targetRow = tableRange.getRow() + r;
|
|
|
- IRange targetRowRange = worksheet.getRange(targetRow, firstDataCol, 1, colCount);
|
|
|
- PasteOption pasteOption = new PasteOption();
|
|
|
- pasteOption.setPasteType(EnumSet.of(PasteType.Formats));
|
|
|
- sourceRow.copy(targetRowRange, pasteOption);
|
|
|
- worksheet.getRange(targetRow, firstDataCol).setRowHeight(firstRowHeight);
|
|
|
-
|
|
|
- for (int[] mergeRange : mergeColRanges) {
|
|
|
- try {
|
|
|
- worksheet.getRange(targetRow, mergeRange[0], 1, mergeRange[1]).merge();
|
|
|
- } catch (Exception ignored) {
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 设置表格范围自动换行
|
|
|
- tableRange.setWrapText(true);
|
|
|
}
|
|
|
}
|
|
|
|