|
|
@@ -613,33 +613,69 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
String sheetName = System.currentTimeMillis() + "_成本调查表";
|
|
|
Sheet sheet = workbook.createSheet(sheetName);
|
|
|
|
|
|
- Row headerRow = sheet.createRow(0);
|
|
|
+ // 创建样式
|
|
|
+ CellStyle titleStyle = createTitleStyle(workbook);
|
|
|
+ CellStyle headerStyle = createHeaderStyle(workbook);
|
|
|
+ CellStyle dataStyle = createDataStyle(workbook);
|
|
|
+
|
|
|
+ // 第一行:大标题
|
|
|
+ Row titleRow = sheet.createRow(0);
|
|
|
+ Cell titleCell = titleRow.createCell(0);
|
|
|
+ titleCell.setCellValue(templateName);
|
|
|
+ titleCell.setCellStyle(titleStyle);
|
|
|
+
|
|
|
+ // 计算总列数(包括隐藏列)
|
|
|
+ int totalColumns = headersList.size();
|
|
|
+ boolean needExtraColumns = "2".equals(templateType) || "3".equals(templateType);
|
|
|
+ if (needExtraColumns) {
|
|
|
+ totalColumns += 2; // rowId + parentId
|
|
|
+ }
|
|
|
+ if ("2".equals(templateType) && auditPeriods != null && auditPeriods.length > 0) {
|
|
|
+ totalColumns += auditPeriods.length + 1; // 年限列 + 备注列
|
|
|
+ }
|
|
|
+
|
|
|
+ // 合并标题行单元格
|
|
|
+ if (totalColumns > 1) {
|
|
|
+ sheet.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(0, 0, 0, totalColumns - 1));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 第二行:列表头
|
|
|
+ Row headerRow = sheet.createRow(1);
|
|
|
int colIndex = 0;
|
|
|
|
|
|
// 添加原有表头
|
|
|
for (int i = 0; i < headersList.size(); i++) {
|
|
|
- headerRow.createCell(colIndex++).setCellValue(headersList.get(i).getFieldName());
|
|
|
+ Cell headerCell = headerRow.createCell(colIndex++);
|
|
|
+ headerCell.setCellValue(headersList.get(i).getFieldName());
|
|
|
+ headerCell.setCellStyle(headerStyle);
|
|
|
}
|
|
|
|
|
|
// 如果是固定表或动态表,在最后添加特殊列
|
|
|
int rowIdColIndex = -1;
|
|
|
int parentIdColIndex = -1;
|
|
|
- boolean needExtraColumns = "2".equals(templateType) || "3".equals(templateType);
|
|
|
if (needExtraColumns) {
|
|
|
// 添加 rowId 列(用于标识行)
|
|
|
rowIdColIndex = colIndex;
|
|
|
- headerRow.createCell(colIndex++).setCellValue("行ID");
|
|
|
+ Cell rowIdCell = headerRow.createCell(colIndex++);
|
|
|
+ rowIdCell.setCellValue("行ID");
|
|
|
+ rowIdCell.setCellStyle(headerStyle);
|
|
|
// 添加 parentId 列(用于标识父子关系)
|
|
|
parentIdColIndex = colIndex;
|
|
|
- headerRow.createCell(colIndex++).setCellValue("父行ID");
|
|
|
+ Cell parentIdCell = headerRow.createCell(colIndex++);
|
|
|
+ parentIdCell.setCellValue("父行ID");
|
|
|
+ parentIdCell.setCellStyle(headerStyle);
|
|
|
}
|
|
|
|
|
|
// 只有固定表需要添加年限列和备注列
|
|
|
if ("2".equals(templateType) && auditPeriods != null && auditPeriods.length > 0) {
|
|
|
for (String period : auditPeriods) {
|
|
|
- headerRow.createCell(colIndex++).setCellValue(period.trim());
|
|
|
+ Cell periodCell = headerRow.createCell(colIndex++);
|
|
|
+ periodCell.setCellValue(period.trim());
|
|
|
+ periodCell.setCellStyle(headerStyle);
|
|
|
}
|
|
|
- headerRow.createCell(colIndex++).setCellValue("备注");
|
|
|
+ Cell remarkCell = headerRow.createCell(colIndex++);
|
|
|
+ remarkCell.setCellValue("备注");
|
|
|
+ remarkCell.setCellStyle(headerStyle);
|
|
|
}
|
|
|
|
|
|
if (itemsList != null && !itemsList.isEmpty()) {
|
|
|
@@ -647,7 +683,7 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
for (int i = 0; i < headersList.size(); i++) {
|
|
|
headerIndexMap.put(headersList.get(i).getId(), i);
|
|
|
}
|
|
|
- fillExcelData(sheet, itemsList, headerIndexMap, templateType, type, rowIdColIndex, parentIdColIndex);
|
|
|
+ fillExcelData(sheet, itemsList, headerIndexMap, templateType, type, rowIdColIndex, parentIdColIndex, dataStyle);
|
|
|
}
|
|
|
|
|
|
for (int i = 0; i < headersList.size(); i++) {
|
|
|
@@ -734,33 +770,69 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
String sheetName = System.currentTimeMillis() + "_财务数据表";
|
|
|
Sheet sheet = workbook.createSheet(sheetName);
|
|
|
|
|
|
- Row headerRow = sheet.createRow(0);
|
|
|
+ // 创建样式
|
|
|
+ CellStyle titleStyle = createTitleStyle(workbook);
|
|
|
+ CellStyle headerStyle = createHeaderStyle(workbook);
|
|
|
+ CellStyle dataStyle = createDataStyle(workbook);
|
|
|
+
|
|
|
+ // 第一行:大标题
|
|
|
+ Row titleRow = sheet.createRow(0);
|
|
|
+ Cell titleCell = titleRow.createCell(0);
|
|
|
+ titleCell.setCellValue(templateName);
|
|
|
+ titleCell.setCellStyle(titleStyle);
|
|
|
+
|
|
|
+ // 计算总列数(包括隐藏列)
|
|
|
+ int totalColumns = headersList.size();
|
|
|
+ boolean needExtraColumns = "2".equals(templateType) || "3".equals(templateType);
|
|
|
+ if (needExtraColumns) {
|
|
|
+ totalColumns += 2; // rowId + parentId
|
|
|
+ }
|
|
|
+ if ("2".equals(templateType) && auditPeriods != null && auditPeriods.length > 0) {
|
|
|
+ totalColumns += auditPeriods.length + 1; // 年限列 + 备注列
|
|
|
+ }
|
|
|
+
|
|
|
+ // 合并标题行单元格
|
|
|
+ if (totalColumns > 1) {
|
|
|
+ sheet.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(0, 0, 0, totalColumns - 1));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 第二行:列表头
|
|
|
+ Row headerRow = sheet.createRow(1);
|
|
|
int colIndex = 0;
|
|
|
|
|
|
// 添加原有表头
|
|
|
for (int i = 0; i < headersList.size(); i++) {
|
|
|
- headerRow.createCell(colIndex++).setCellValue(headersList.get(i).getFieldName());
|
|
|
+ Cell headerCell = headerRow.createCell(colIndex++);
|
|
|
+ headerCell.setCellValue(headersList.get(i).getFieldName());
|
|
|
+ headerCell.setCellStyle(headerStyle);
|
|
|
}
|
|
|
|
|
|
// 如果是固定表或动态表,在最后添加特殊列
|
|
|
int rowIdColIndex = -1;
|
|
|
int parentIdColIndex = -1;
|
|
|
- boolean needExtraColumns = "2".equals(templateType) || "3".equals(templateType);
|
|
|
if (needExtraColumns) {
|
|
|
// 添加 rowId 列(用于标识行)
|
|
|
rowIdColIndex = colIndex;
|
|
|
- headerRow.createCell(colIndex++).setCellValue("行ID");
|
|
|
+ Cell rowIdCell = headerRow.createCell(colIndex++);
|
|
|
+ rowIdCell.setCellValue("行ID");
|
|
|
+ rowIdCell.setCellStyle(headerStyle);
|
|
|
// 添加 parentId 列(用于标识父子关系)
|
|
|
parentIdColIndex = colIndex;
|
|
|
- headerRow.createCell(colIndex++).setCellValue("父行ID");
|
|
|
+ Cell parentIdCell = headerRow.createCell(colIndex++);
|
|
|
+ parentIdCell.setCellValue("父行ID");
|
|
|
+ parentIdCell.setCellStyle(headerStyle);
|
|
|
}
|
|
|
|
|
|
// 只有固定表需要添加年限列和备注列
|
|
|
if ("2".equals(templateType) && auditPeriods != null && auditPeriods.length > 0) {
|
|
|
for (String period : auditPeriods) {
|
|
|
- headerRow.createCell(colIndex++).setCellValue(period.trim());
|
|
|
+ Cell periodCell = headerRow.createCell(colIndex++);
|
|
|
+ periodCell.setCellValue(period.trim());
|
|
|
+ periodCell.setCellStyle(headerStyle);
|
|
|
}
|
|
|
- headerRow.createCell(colIndex++).setCellValue("备注");
|
|
|
+ Cell remarkCell = headerRow.createCell(colIndex++);
|
|
|
+ remarkCell.setCellValue("备注");
|
|
|
+ remarkCell.setCellStyle(headerStyle);
|
|
|
}
|
|
|
|
|
|
if (itemsList != null && !itemsList.isEmpty()) {
|
|
|
@@ -768,7 +840,7 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
for (int i = 0; i < headersList.size(); i++) {
|
|
|
headerIndexMap.put(headersList.get(i).getId(), i);
|
|
|
}
|
|
|
- fillExcelDataFd(sheet, itemsList, headerIndexMap, templateType, rowIdColIndex, parentIdColIndex);
|
|
|
+ fillExcelDataFd(sheet, itemsList, headerIndexMap, templateType, rowIdColIndex, parentIdColIndex, dataStyle);
|
|
|
}
|
|
|
|
|
|
for (int i = 0; i < headersList.size(); i++) {
|
|
|
@@ -841,24 +913,50 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
String sheetName = System.currentTimeMillis() + "_核定表";
|
|
|
Sheet sheet = workbook.createSheet(sheetName);
|
|
|
|
|
|
- Row headerRow = sheet.createRow(0);
|
|
|
+ // 创建样式
|
|
|
+ CellStyle titleStyle = createTitleStyle(workbook);
|
|
|
+ CellStyle headerStyle = createHeaderStyle(workbook);
|
|
|
+ CellStyle dataStyle = createDataStyle(workbook);
|
|
|
+
|
|
|
+ // 第一行:大标题
|
|
|
+ Row titleRow = sheet.createRow(0);
|
|
|
+ Cell titleCell = titleRow.createCell(0);
|
|
|
+ titleCell.setCellValue(template.getSurveyTemplateName());
|
|
|
+ titleCell.setCellStyle(titleStyle);
|
|
|
+
|
|
|
+ // 计算总列数(包括隐藏列)
|
|
|
+ int totalColumns = headersList.size() + 2; // 包括行ID和父行ID
|
|
|
+
|
|
|
+ // 合并标题行单元格
|
|
|
+ if (totalColumns > 1) {
|
|
|
+ sheet.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(0, 0, 0, totalColumns - 1));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 第二行:列表头
|
|
|
+ Row headerRow = sheet.createRow(1);
|
|
|
int colIndex = 0;
|
|
|
|
|
|
for (int i = 0; i < headersList.size(); i++) {
|
|
|
- headerRow.createCell(colIndex++).setCellValue(headersList.get(i).getFieldName());
|
|
|
+ Cell headerCell = headerRow.createCell(colIndex++);
|
|
|
+ headerCell.setCellValue(headersList.get(i).getFieldName());
|
|
|
+ headerCell.setCellStyle(headerStyle);
|
|
|
}
|
|
|
|
|
|
int rowIdColIndex = colIndex;
|
|
|
- headerRow.createCell(colIndex++).setCellValue("行ID");
|
|
|
+ Cell rowIdCell = headerRow.createCell(colIndex++);
|
|
|
+ rowIdCell.setCellValue("行ID");
|
|
|
+ rowIdCell.setCellStyle(headerStyle);
|
|
|
int parentIdColIndex = colIndex;
|
|
|
- headerRow.createCell(colIndex++).setCellValue("父行ID");
|
|
|
+ Cell parentIdCell = headerRow.createCell(colIndex++);
|
|
|
+ parentIdCell.setCellValue("父行ID");
|
|
|
+ parentIdCell.setCellStyle(headerStyle);
|
|
|
|
|
|
if (itemsList != null && !itemsList.isEmpty()) {
|
|
|
Map<String, Integer> headerIndexMap = new HashMap<>();
|
|
|
for (int i = 0; i < headersList.size(); i++) {
|
|
|
headerIndexMap.put(headersList.get(i).getId(), i);
|
|
|
}
|
|
|
- fillExcelDataVerify(sheet, itemsList, headerIndexMap, rowIdColIndex, parentIdColIndex);
|
|
|
+ fillExcelDataVerify(sheet, itemsList, headerIndexMap, rowIdColIndex, parentIdColIndex, dataStyle);
|
|
|
}
|
|
|
|
|
|
for (int i = 0; i < headersList.size(); i++) {
|
|
|
@@ -979,7 +1077,8 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
return CommonResult.<String>error().message("Excel文件没有数据");
|
|
|
}
|
|
|
|
|
|
- Row headerRow = sheet.getRow(0);
|
|
|
+ // 第0行是标题,第1行是表头
|
|
|
+ Row headerRow = sheet.getRow(1);
|
|
|
if (headerRow == null) {
|
|
|
return CommonResult.<String>error().message("Excel文件第一行为空");
|
|
|
}
|
|
|
@@ -1029,11 +1128,21 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// // 校验表头是否与导出时一致
|
|
|
+// List<String> headerValidationErrors = validateExcelHeaders(
|
|
|
+// headerRow, headersList, taskId, templateType, type,
|
|
|
+// rowIdColumnIndex, parentIdColumnIndex, auditPeriodColumnMap, remarkColumnIndex);
|
|
|
+// if (!headerValidationErrors.isEmpty()) {
|
|
|
+// return CommonResult.<String>error().message(
|
|
|
+// "导入失败,表头校验不通过:<br>" + String.join("<br>", headerValidationErrors));
|
|
|
+// }
|
|
|
+
|
|
|
List<CostSurveyTemplateUploadData> dataList = new ArrayList<>();
|
|
|
Map<String, Integer> rowIdToExcelRowMap = new HashMap<>();
|
|
|
int dataRowCount = 0;
|
|
|
|
|
|
- for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
|
|
|
+ // 从第2行开始读取数据(第0行是标题,第1行是表头)
|
|
|
+ for (int rowIndex = 2; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
|
|
|
Row dataRow = sheet.getRow(rowIndex);
|
|
|
if (dataRow == null || isEmptyRow(dataRow)) continue;
|
|
|
|
|
|
@@ -1047,7 +1156,9 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
currentRowId = excelRowId.trim();
|
|
|
} else {
|
|
|
// 固定表和动态表都不支持新增行,行ID不能为空
|
|
|
- return CommonResult.<String>error().message(String.format("第%d行 行ID不能为空,请使用系统导出的模板文件", rowIndex + 1));
|
|
|
+ CommonResult<String> result = CommonResult.<String>error().message(String.format("第%d行 行ID不能为空,请使用系统导出的模板文件", rowIndex + 1));
|
|
|
+ result.setCode(250);
|
|
|
+ return result;
|
|
|
}
|
|
|
} else {
|
|
|
return CommonResult.<String>error().message("固定表/动态表导入失败:Excel文件缺少【行ID】列。请使用系统导出的模板,不要删除隐藏列。");
|
|
|
@@ -1196,7 +1307,8 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
return CommonResult.<String>error().message("Excel文件没有数据");
|
|
|
}
|
|
|
|
|
|
- Row headerRow = sheet.getRow(0);
|
|
|
+ // 第0行是标题,第1行是表头
|
|
|
+ Row headerRow = sheet.getRow(1);
|
|
|
if (headerRow == null) {
|
|
|
return CommonResult.<String>error().message("Excel文件第一行为空");
|
|
|
}
|
|
|
@@ -1236,11 +1348,21 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
return CommonResult.<String>error().message("Excel表头与模板表头不匹配");
|
|
|
}
|
|
|
|
|
|
+ // 校验表头是否与导出时一致
|
|
|
+// List<String> headerValidationErrors = validateExcelHeadersFd(
|
|
|
+// headerRow, headersList, taskId, templateType, type,
|
|
|
+// rowIdColumnIndex, parentIdColumnIndex, auditPeriodColumnMap, remarkColumnIndex);
|
|
|
+// if (!headerValidationErrors.isEmpty()) {
|
|
|
+// return CommonResult.<String>error().message(
|
|
|
+// "导入失败,表头校验不通过:<br>" + String.join("<br>", headerValidationErrors));
|
|
|
+// }
|
|
|
+
|
|
|
List<CostSurveyTemplateUploadData> dataList = new ArrayList<>();
|
|
|
Map<String, Integer> rowIdToExcelRowMap = new HashMap<>();
|
|
|
int dataRowCount = 0;
|
|
|
|
|
|
- for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
|
|
|
+ // 从第2行开始读取数据(第0行是标题,第1行是表头)
|
|
|
+ for (int rowIndex = 2; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
|
|
|
Row dataRow = sheet.getRow(rowIndex);
|
|
|
if (dataRow == null || isEmptyRow(dataRow)) continue;
|
|
|
|
|
|
@@ -1254,7 +1376,9 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
currentRowId = excelRowId.trim();
|
|
|
} else {
|
|
|
// 固定表和动态表都不支持新增行,行ID不能为空
|
|
|
- return CommonResult.<String>error().message(String.format("第%d行 行ID不能为空,请使用系统导出的模板文件", rowIndex + 1));
|
|
|
+ CommonResult<String> result = CommonResult.<String>error().message(String.format("第%d行 行ID不能为空,请使用系统导出的模板文件", rowIndex + 1));
|
|
|
+ result.setCode(250);
|
|
|
+ return result;
|
|
|
}
|
|
|
} else {
|
|
|
return CommonResult.<String>error().message("固定表/动态表导入失败:Excel文件缺少【行ID】列。请使用系统导出的模板,不要删除隐藏列。");
|
|
|
@@ -1396,7 +1520,8 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
return CommonResult.<String>error().message("Excel文件没有数据");
|
|
|
}
|
|
|
|
|
|
- Row headerRow = sheet.getRow(0);
|
|
|
+ // 第0行是标题,第1行是表头
|
|
|
+ Row headerRow = sheet.getRow(1);
|
|
|
if (headerRow == null) {
|
|
|
return CommonResult.<String>error().message("Excel表头行为空");
|
|
|
}
|
|
|
@@ -1434,7 +1559,8 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
Map<String, Integer> rowIdToExcelRowMap = new HashMap<>();
|
|
|
int importRowCount = 0;
|
|
|
|
|
|
- for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
|
|
|
+ // 从第2行开始读取数据(第0行是标题,第1行是表头)
|
|
|
+ for (int rowIndex = 2; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
|
|
|
Row dataRow = sheet.getRow(rowIndex);
|
|
|
if (dataRow == null || isEmptyRow(dataRow)) continue;
|
|
|
|
|
|
@@ -1448,7 +1574,9 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
currentRowId = excelRowId.trim();
|
|
|
} else {
|
|
|
// 核定表不支持新增行,行ID不能为空
|
|
|
- return CommonResult.<String>error().message(String.format("第%d行 行ID不能为空,请使用系统导出的模板文件", rowIndex + 1));
|
|
|
+ CommonResult<String> result = CommonResult.<String>error().message(String.format("第%d行 行ID不能为空,请使用系统导出的模板文件", rowIndex + 1));
|
|
|
+ result.setCode(250);
|
|
|
+ return result;
|
|
|
}
|
|
|
} else {
|
|
|
// 核定表必须有行ID列
|
|
|
@@ -1493,7 +1621,9 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
return CommonResult.<String>ok().message("导入成功,共导入 " + importRowCount + " 行数据");
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
- return CommonResult.<String>error().message("导入失败:" + e.getMessage());
|
|
|
+ CommonResult<String> result = CommonResult.<String>error().message("导入失败:" + e.getMessage());
|
|
|
+ result.setCode(250);
|
|
|
+ return result;
|
|
|
} finally {
|
|
|
if (workbook != null) workbook.close();
|
|
|
}
|
|
|
@@ -1589,7 +1719,12 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
|
|
|
if (StringUtil.isEmpty(cellCode)) {
|
|
|
// rowid 不匹配说明导入的Excel不是从当前模板导出的,添加到错误列表
|
|
|
- errors.add(String.format("行[%s] 的行ID在模板中不存在,请使用系统导出的最新模板文件", rowid));
|
|
|
+ Integer excelRowNum = rowIdToExcelRowMap.get(rowid);
|
|
|
+ if (excelRowNum != null) {
|
|
|
+ errors.add(String.format("第%d行的数据在当前模板中不存在,请使用系统导出的最新模板文件", excelRowNum));
|
|
|
+ } else {
|
|
|
+ errors.add("存在无法识别的数据行,请使用系统导出的最新模板文件");
|
|
|
+ }
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
@@ -1865,8 +2000,11 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
}
|
|
|
|
|
|
if (!invalidValues.isEmpty()) {
|
|
|
- throw new IllegalArgumentException(String.format("%s [%s]的值[%s]不在允许的选项范围内",
|
|
|
- rowDisplay, fieldName, String.join(", ", invalidValues)));
|
|
|
+ // 构建详细的错误信息,包含允许的选项范围
|
|
|
+ String validOptionsStr = String.join("、", validValues);
|
|
|
+ throw new IllegalArgumentException(String.format(
|
|
|
+ "%s [%s]的值[%s]不在允许的选项范围内。允许的选项有:%s",
|
|
|
+ rowDisplay, fieldName, String.join("、", invalidValues), validOptionsStr));
|
|
|
}
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
throw e;
|
|
|
@@ -2252,11 +2390,18 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("[A-Z]+\\d+");
|
|
|
java.util.regex.Matcher matcher = pattern.matcher(calculationFormula);
|
|
|
List<String> referencedCellsDebug = new ArrayList<>();
|
|
|
+ Map<String, String> cellCodeToItemNameMap = new HashMap<>(); // 存储cellCode到项目名称的映射
|
|
|
+
|
|
|
while (matcher.find()) {
|
|
|
String referencedCell = matcher.group();
|
|
|
String mapKey = referencedCell + "_" + period;
|
|
|
String value = globalCellCodeMap.get(mapKey);
|
|
|
String displayValue = StringUtil.isNotEmpty(value) ? value : "0";
|
|
|
+
|
|
|
+ // 获取该cellCode对应的项目名称
|
|
|
+ String itemName = getCellCodeItemName(referencedCell, type);
|
|
|
+ cellCodeToItemNameMap.put(referencedCell, itemName);
|
|
|
+
|
|
|
referencedCellsDebug.add(referencedCell + "=" + displayValue);
|
|
|
if (StringUtil.isNotEmpty(value)) {
|
|
|
hasAnyReferencedValue = true;
|
|
|
@@ -2305,8 +2450,12 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
// 获取友好的行号显示
|
|
|
Integer excelRow = rowIdToExcelRowMap.get(rowid);
|
|
|
String rowDisplay = excelRow != null ? "第" + excelRow + "行" : "行[" + rowid + "]";
|
|
|
- errors.add(String.format("%s %s年列数据错误:计算结果应为%.2f,实际填写%.2f",
|
|
|
- rowDisplay, period, calculatedValue, inputValue));
|
|
|
+
|
|
|
+ // 构建详细的计算过程(包含项目名称)
|
|
|
+ String calculationProcess = buildCalculationProcessWithNames(calculationFormula, referencedCellsDebug, cellCodeToItemNameMap);
|
|
|
+
|
|
|
+ errors.add(String.format("%s %s年列数据错误:<br>计算公式:%s<br>计算过程:%s<br>计算结果:%.2f<br>实际填写:%.2f",
|
|
|
+ rowDisplay, period, calculationFormula, calculationProcess, calculatedValue, inputValue));
|
|
|
} else {
|
|
|
System.out.println("校验结果: ✓ 通过");
|
|
|
System.out.println("========================================");
|
|
|
@@ -2585,13 +2734,15 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
|
|
|
private void fillExcelData(Sheet sheet, List<CostSurveyTemplateItems> itemsList,
|
|
|
Map<String, Integer> headerIndexMap, String templateType, String dataType,
|
|
|
- int rowIdColIndex, int parentIdColIndex) {
|
|
|
+ int rowIdColIndex, int parentIdColIndex, CellStyle dataStyle) {
|
|
|
if ("1".equals(templateType)) {
|
|
|
- Row dataRow = sheet.createRow(1);
|
|
|
+ Row dataRow = sheet.createRow(2);
|
|
|
for (CostSurveyTemplateItems item : itemsList) {
|
|
|
Integer colIndex = headerIndexMap.get(item.getHeadersId());
|
|
|
if (colIndex != null) {
|
|
|
- dataRow.createCell(colIndex).setCellValue(item.getRvalue());
|
|
|
+ Cell cell = dataRow.createCell(colIndex);
|
|
|
+ cell.setCellValue(item.getRvalue());
|
|
|
+ cell.setCellStyle(dataStyle);
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
@@ -2603,7 +2754,11 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
// 固定表和动态表都需要按父子关系排序
|
|
|
List<String> sortedRowIds = sortRowIdsByParentChild(itemsByRowId);
|
|
|
|
|
|
- int rowNum = 1;
|
|
|
+ // 获取表头行,计算总列数
|
|
|
+ Row headerRow = sheet.getRow(1);
|
|
|
+ int totalColumns = headerRow != null ? headerRow.getLastCellNum() : 0;
|
|
|
+
|
|
|
+ int rowNum = 2;
|
|
|
for (String rowId : sortedRowIds) {
|
|
|
List<CostSurveyTemplateItems> rowItems = itemsByRowId.get(rowId);
|
|
|
if (rowItems != null && !rowItems.isEmpty()) {
|
|
|
@@ -2613,18 +2768,38 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
for (CostSurveyTemplateItems item : rowItems) {
|
|
|
Integer colIndex = headerIndexMap.get(item.getHeadersId());
|
|
|
if (colIndex != null) {
|
|
|
- dataRow.createCell(colIndex).setCellValue(item.getRvalue());
|
|
|
+ Cell cell = dataRow.createCell(colIndex);
|
|
|
+ cell.setCellValue(item.getRvalue());
|
|
|
+ cell.setCellStyle(dataStyle);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 填充 rowId 和 parentId 列
|
|
|
if (rowIdColIndex >= 0) {
|
|
|
- dataRow.createCell(rowIdColIndex).setCellValue(rowId);
|
|
|
+ Cell cell = dataRow.createCell(rowIdColIndex);
|
|
|
+ cell.setCellValue(rowId);
|
|
|
+ cell.setCellStyle(dataStyle);
|
|
|
}
|
|
|
if (parentIdColIndex >= 0) {
|
|
|
String parentId = rowItems.get(0).getParentid();
|
|
|
if (StringUtil.isNotEmpty(parentId)) {
|
|
|
- dataRow.createCell(parentIdColIndex).setCellValue(parentId);
|
|
|
+ Cell cell = dataRow.createCell(parentIdColIndex);
|
|
|
+ cell.setCellValue(parentId);
|
|
|
+ cell.setCellStyle(dataStyle);
|
|
|
+ } else {
|
|
|
+ // 即使没有值,也要创建单元格并应用样式
|
|
|
+ Cell cell = dataRow.createCell(parentIdColIndex);
|
|
|
+ cell.setCellValue("");
|
|
|
+ cell.setCellStyle(dataStyle);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 为所有剩余列(年限列和备注列)创建空单元格并应用样式
|
|
|
+ for (int colIndex = 0; colIndex < totalColumns; colIndex++) {
|
|
|
+ if (dataRow.getCell(colIndex) == null) {
|
|
|
+ Cell cell = dataRow.createCell(colIndex);
|
|
|
+ cell.setCellValue("");
|
|
|
+ cell.setCellStyle(dataStyle);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -2708,14 +2883,16 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
|
|
|
private void fillExcelDataFd(Sheet sheet, List<CostSurveyFdTemplateItems> itemsList,
|
|
|
Map<String, Integer> headerIndexMap, String templateType,
|
|
|
- int rowIdColIndex, int parentIdColIndex) {
|
|
|
+ int rowIdColIndex, int parentIdColIndex, CellStyle dataStyle) {
|
|
|
if ("1".equals(templateType)) {
|
|
|
// 单表:所有数据在一行
|
|
|
- Row dataRow = sheet.createRow(1);
|
|
|
+ Row dataRow = sheet.createRow(2);
|
|
|
for (CostSurveyFdTemplateItems item : itemsList) {
|
|
|
Integer colIndex = headerIndexMap.get(item.getHeadersId());
|
|
|
if (colIndex != null) {
|
|
|
- dataRow.createCell(colIndex).setCellValue(item.getRvalue());
|
|
|
+ Cell cell = dataRow.createCell(colIndex);
|
|
|
+ cell.setCellValue(item.getRvalue());
|
|
|
+ cell.setCellStyle(dataStyle);
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
@@ -2727,7 +2904,11 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
// 固定表和动态表都需要按父子关系排序
|
|
|
List<String> sortedRowIds = sortRowIdsByParentChildFd(itemsByRowId);
|
|
|
|
|
|
- int rowNum = 1;
|
|
|
+ // 获取表头行,计算总列数
|
|
|
+ Row headerRow = sheet.getRow(1);
|
|
|
+ int totalColumns = headerRow != null ? headerRow.getLastCellNum() : 0;
|
|
|
+
|
|
|
+ int rowNum = 2;
|
|
|
for (String rowId : sortedRowIds) {
|
|
|
List<CostSurveyFdTemplateItems> rowItems = itemsByRowId.get(rowId);
|
|
|
if (rowItems != null && !rowItems.isEmpty()) {
|
|
|
@@ -2737,18 +2918,38 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
for (CostSurveyFdTemplateItems item : rowItems) {
|
|
|
Integer colIndex = headerIndexMap.get(item.getHeadersId());
|
|
|
if (colIndex != null) {
|
|
|
- dataRow.createCell(colIndex).setCellValue(item.getRvalue());
|
|
|
+ Cell cell = dataRow.createCell(colIndex);
|
|
|
+ cell.setCellValue(item.getRvalue());
|
|
|
+ cell.setCellStyle(dataStyle);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 填充 rowId 和 parentId 列
|
|
|
if (rowIdColIndex >= 0) {
|
|
|
- dataRow.createCell(rowIdColIndex).setCellValue(rowId);
|
|
|
+ Cell cell = dataRow.createCell(rowIdColIndex);
|
|
|
+ cell.setCellValue(rowId);
|
|
|
+ cell.setCellStyle(dataStyle);
|
|
|
}
|
|
|
if (parentIdColIndex >= 0) {
|
|
|
String parentId = rowItems.get(0).getParentid();
|
|
|
if (StringUtil.isNotEmpty(parentId)) {
|
|
|
- dataRow.createCell(parentIdColIndex).setCellValue(parentId);
|
|
|
+ Cell cell = dataRow.createCell(parentIdColIndex);
|
|
|
+ cell.setCellValue(parentId);
|
|
|
+ cell.setCellStyle(dataStyle);
|
|
|
+ } else {
|
|
|
+ // 即使没有值,也要创建单元格并应用样式
|
|
|
+ Cell cell = dataRow.createCell(parentIdColIndex);
|
|
|
+ cell.setCellValue("");
|
|
|
+ cell.setCellStyle(dataStyle);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 为所有剩余列(年限列和备注列)创建空单元格并应用样式
|
|
|
+ for (int colIndex = 0; colIndex < totalColumns; colIndex++) {
|
|
|
+ if (dataRow.getCell(colIndex) == null) {
|
|
|
+ Cell cell = dataRow.createCell(colIndex);
|
|
|
+ cell.setCellValue("");
|
|
|
+ cell.setCellStyle(dataStyle);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -2885,7 +3086,7 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
}
|
|
|
|
|
|
private void fillExcelDataVerify(Sheet sheet, List<CostVerifyTemplateItems> itemsList,
|
|
|
- Map<String, Integer> headerIndexMap, int rowIdColIndex, int parentIdColIndex) {
|
|
|
+ Map<String, Integer> headerIndexMap, int rowIdColIndex, int parentIdColIndex, CellStyle dataStyle) {
|
|
|
|
|
|
if (itemsList == null || itemsList.isEmpty()) {
|
|
|
return;
|
|
|
@@ -2899,7 +3100,11 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
// 按父子关系排序
|
|
|
List<String> sortedRowIds = sortRowIdsByParentChildVerify(itemsByRowId);
|
|
|
|
|
|
- int rowNum = 1;
|
|
|
+ // 获取表头行,计算总列数
|
|
|
+ Row headerRow = sheet.getRow(1);
|
|
|
+ int totalColumns = headerRow != null ? headerRow.getLastCellNum() : 0;
|
|
|
+
|
|
|
+ int rowNum = 2;
|
|
|
int totalCellsWritten = 0;
|
|
|
int cellsSkippedNoMapping = 0;
|
|
|
|
|
|
@@ -2914,7 +3119,9 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
if (colIndex != null) {
|
|
|
String cellValue = item.getRvalue();
|
|
|
if (StringUtil.isNotEmpty(cellValue)) {
|
|
|
- dataRow.createCell(colIndex).setCellValue(cellValue);
|
|
|
+ Cell cell = dataRow.createCell(colIndex);
|
|
|
+ cell.setCellValue(cellValue);
|
|
|
+ cell.setCellStyle(dataStyle);
|
|
|
totalCellsWritten++;
|
|
|
}
|
|
|
} else {
|
|
|
@@ -2924,18 +3131,36 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
|
|
|
// 填充 rowId 和 parentId 列
|
|
|
if (rowIdColIndex >= 0) {
|
|
|
- dataRow.createCell(rowIdColIndex).setCellValue(rowId);
|
|
|
+ Cell cell = dataRow.createCell(rowIdColIndex);
|
|
|
+ cell.setCellValue(rowId);
|
|
|
+ cell.setCellStyle(dataStyle);
|
|
|
}
|
|
|
if (parentIdColIndex >= 0) {
|
|
|
String parentId = rowItems.get(0).getParentid();
|
|
|
if (StringUtil.isNotEmpty(parentId)) {
|
|
|
- dataRow.createCell(parentIdColIndex).setCellValue(parentId);
|
|
|
+ Cell cell = dataRow.createCell(parentIdColIndex);
|
|
|
+ cell.setCellValue(parentId);
|
|
|
+ cell.setCellStyle(dataStyle);
|
|
|
+ } else {
|
|
|
+ // 即使没有值,也要创建单元格并应用样式
|
|
|
+ Cell cell = dataRow.createCell(parentIdColIndex);
|
|
|
+ cell.setCellValue("");
|
|
|
+ cell.setCellStyle(dataStyle);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 为所有剩余列创建空单元格并应用样式
|
|
|
+ for (int colIndex = 0; colIndex < totalColumns; colIndex++) {
|
|
|
+ if (dataRow.getCell(colIndex) == null) {
|
|
|
+ Cell cell = dataRow.createCell(colIndex);
|
|
|
+ cell.setCellValue("");
|
|
|
+ cell.setCellStyle(dataStyle);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- System.out.println("数据填充完成 - 行数: " + (rowNum - 1) + ", 单元格: " + totalCellsWritten + ", 跳过: " + cellsSkippedNoMapping);
|
|
|
+ System.out.println("数据填充完成 - 行数: " + (rowNum - 2) + ", 单元格: " + totalCellsWritten + ", 跳过: " + cellsSkippedNoMapping);
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -3066,4 +3291,311 @@ public class CostProjectTaskSurveyGenericController {
|
|
|
uploadData.setIsDeleted("0");
|
|
|
return uploadData;
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 校验Excel表头是否与导出时一致(成本调查表)
|
|
|
+ */
|
|
|
+ private List<String> validateExcelHeaders(Row headerRow, List<CostSurveyTemplateHeaders> headersList,
|
|
|
+ String taskId, String templateType, String type,
|
|
|
+ Integer rowIdColumnIndex, Integer parentIdColumnIndex,
|
|
|
+ Map<String, Integer> auditPeriodColumnMap, Integer remarkColumnIndex) {
|
|
|
+ List<String> errors = new ArrayList<>();
|
|
|
+
|
|
|
+ // 1. 构建期望的表头列表
|
|
|
+ Set<String> expectedHeaders = new HashSet<>();
|
|
|
+ for (CostSurveyTemplateHeaders header : headersList) {
|
|
|
+ if (StringUtil.isEmpty(header.getShowVisible()) || "1".equals(header.getShowVisible())) {
|
|
|
+ expectedHeaders.add(header.getFieldName().trim());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 如果是固定表,添加年限列和备注列
|
|
|
+ if ("2".equals(templateType)) {
|
|
|
+ CostProjectTask task = costProjectTaskManager.getById(taskId);
|
|
|
+ if (task != null) {
|
|
|
+ CostProjectApproval approval = costProjectApprovalManager.getById(task.getProjectId());
|
|
|
+ if (approval != null && StringUtil.isNotEmpty(approval.getAuditPeriod())) {
|
|
|
+ String[] periods = approval.getAuditPeriod().split(",");
|
|
|
+ for (String period : periods) {
|
|
|
+ expectedHeaders.add(period.trim());
|
|
|
+ }
|
|
|
+ expectedHeaders.add("备注");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 如果是固定表或动态表,添加行ID和父行ID
|
|
|
+ if ("2".equals(templateType) || "3".equals(templateType)) {
|
|
|
+ expectedHeaders.add("行ID");
|
|
|
+ expectedHeaders.add("父行ID");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 读取Excel中的实际表头
|
|
|
+ Set<String> actualHeaders = new HashSet<>();
|
|
|
+ for (int i = 0; i < headerRow.getLastCellNum(); i++) {
|
|
|
+ Cell cell = headerRow.getCell(i);
|
|
|
+ if (cell != null) {
|
|
|
+ String cellValue = getCellStringValue(cell);
|
|
|
+ if (StringUtil.isNotEmpty(cellValue)) {
|
|
|
+ actualHeaders.add(cellValue.trim());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 5. 检查是否有多余的表头
|
|
|
+ Set<String> extraHeaders = new HashSet<>(actualHeaders);
|
|
|
+ extraHeaders.removeAll(expectedHeaders);
|
|
|
+ if (!extraHeaders.isEmpty()) {
|
|
|
+ errors.add(String.format("Excel文件包含多余的表头列:%s", String.join("、", extraHeaders)));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 6. 检查是否缺少必需的表头
|
|
|
+ Set<String> missingHeaders = new HashSet<>(expectedHeaders);
|
|
|
+ missingHeaders.removeAll(actualHeaders);
|
|
|
+ if (!missingHeaders.isEmpty()) {
|
|
|
+ errors.add(String.format("Excel文件缺少必需的表头列:%s", String.join("、", missingHeaders)));
|
|
|
+ }
|
|
|
+
|
|
|
+ return errors;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 校验Excel表头是否与导出时一致(财务数据表)
|
|
|
+ */
|
|
|
+ private List<String> validateExcelHeadersFd(Row headerRow, List<CostSurveyFdTemplateHeaders> headersList,
|
|
|
+ String taskId, String templateType, String type,
|
|
|
+ Integer rowIdColumnIndex, Integer parentIdColumnIndex,
|
|
|
+ Map<String, Integer> auditPeriodColumnMap, Integer remarkColumnIndex) {
|
|
|
+ List<String> errors = new ArrayList<>();
|
|
|
+
|
|
|
+ // 1. 构建期望的表头列表
|
|
|
+ Set<String> expectedHeaders = new HashSet<>();
|
|
|
+ for (CostSurveyFdTemplateHeaders header : headersList) {
|
|
|
+ if (StringUtil.isEmpty(header.getShowVisible()) || "1".equals(header.getShowVisible())) {
|
|
|
+ expectedHeaders.add(header.getFieldName().trim());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 如果是固定表,添加年限列和备注列
|
|
|
+ if ("2".equals(templateType)) {
|
|
|
+ CostProjectTask task = costProjectTaskManager.getById(taskId);
|
|
|
+ if (task != null) {
|
|
|
+ CostProjectApproval approval = costProjectApprovalManager.getById(task.getProjectId());
|
|
|
+ if (approval != null && StringUtil.isNotEmpty(approval.getAuditPeriod())) {
|
|
|
+ String[] periods = approval.getAuditPeriod().split(",");
|
|
|
+ for (String period : periods) {
|
|
|
+ expectedHeaders.add(period.trim());
|
|
|
+ }
|
|
|
+ expectedHeaders.add("备注");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 如果是固定表或动态表,添加行ID和父行ID
|
|
|
+ if ("2".equals(templateType) || "3".equals(templateType)) {
|
|
|
+ expectedHeaders.add("行ID");
|
|
|
+ expectedHeaders.add("父行ID");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 读取Excel中的实际表头
|
|
|
+ Set<String> actualHeaders = new HashSet<>();
|
|
|
+ for (int i = 0; i < headerRow.getLastCellNum(); i++) {
|
|
|
+ Cell cell = headerRow.getCell(i);
|
|
|
+ if (cell != null) {
|
|
|
+ String cellValue = getCellStringValue(cell);
|
|
|
+ if (StringUtil.isNotEmpty(cellValue)) {
|
|
|
+ actualHeaders.add(cellValue.trim());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 5. 检查是否有多余的表头
|
|
|
+ Set<String> extraHeaders = new HashSet<>(actualHeaders);
|
|
|
+ extraHeaders.removeAll(expectedHeaders);
|
|
|
+ if (!extraHeaders.isEmpty()) {
|
|
|
+ errors.add(String.format("Excel文件包含多余的表头列:%s", String.join("、", extraHeaders)));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 6. 检查是否缺少必需的表头
|
|
|
+ Set<String> missingHeaders = new HashSet<>(expectedHeaders);
|
|
|
+ missingHeaders.removeAll(actualHeaders);
|
|
|
+ if (!missingHeaders.isEmpty()) {
|
|
|
+ errors.add(String.format("Excel文件缺少必需的表头列:%s", String.join("、", missingHeaders)));
|
|
|
+ }
|
|
|
+
|
|
|
+ return errors;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据cellCode获取对应的项目名称
|
|
|
+ * @param cellCode 单元格编码,如 "A1"
|
|
|
+ * @param type 类型:1-成本调查表 2-财务数据表 3-核定表
|
|
|
+ * @return 项目名称,如 "基本工资"
|
|
|
+ */
|
|
|
+ private String getCellCodeItemName(String cellCode, String type) {
|
|
|
+ try {
|
|
|
+ List<? extends Object> allItems = null;
|
|
|
+
|
|
|
+ // 根据type获取所有模板项
|
|
|
+ switch (type) {
|
|
|
+ case "1": {
|
|
|
+ // 成本调查表 - 需要获取所有模板的items
|
|
|
+ List<CostSurveyTemplate> templates = costSurveyTemplateManager.list();
|
|
|
+ for (CostSurveyTemplate template : templates) {
|
|
|
+ CostSurveyTemplateVersion version = costSurveyTemplateVersionManager.selectCurrentVersion(template.getSurveyTemplateId());
|
|
|
+ if (version != null) {
|
|
|
+ List<CostSurveyTemplateItems> items = costSurveyTemplateItemsDao.selectBySurveyTemplateIdAndVersion(
|
|
|
+ template.getSurveyTemplateId(), version.getId());
|
|
|
+ for (CostSurveyTemplateItems item : items) {
|
|
|
+ if (cellCode.equals(item.getCellCode())) {
|
|
|
+ return item.getRvalue(); // 返回项目名称
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case "2": {
|
|
|
+ // 财务数据表
|
|
|
+ List<CostSurveyFdTemplate> templates = costSurveyFdTemplateManager.list();
|
|
|
+ for (CostSurveyFdTemplate template : templates) {
|
|
|
+ CostSurveyFdTemplateVersion version = costSurveyFdTemplateVersionManager.selectCurrentVersion(template.getSurveyTemplateId());
|
|
|
+ if (version != null) {
|
|
|
+ List<CostSurveyFdTemplateItems> items = costSurveyFdTemplateItemsDao.selectBySurveyTemplateIdAndVersion(
|
|
|
+ template.getSurveyTemplateId(), version.getId());
|
|
|
+ for (CostSurveyFdTemplateItems item : items) {
|
|
|
+ if (cellCode.equals(item.getCellCode())) {
|
|
|
+ return item.getRvalue(); // 返回项目名称
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case "3": {
|
|
|
+ // 核定表
|
|
|
+ List<CostVerifyTemplate> templates = costVerifyTemplateManager.list();
|
|
|
+ for (CostVerifyTemplate template : templates) {
|
|
|
+ List<CostVerifyTemplateItems> items = costVerifyTemplateItemsDao.selectByVerifyTemplateId(
|
|
|
+ template.getSurveyTemplateId(), null);
|
|
|
+ for (CostVerifyTemplateItems item : items) {
|
|
|
+ if (cellCode.equals(item.getCellCode())) {
|
|
|
+ return item.getRvalue(); // 返回项目名称
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ System.err.println("获取cellCode[" + cellCode + "]对应的项目名称失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ return cellCode; // 如果找不到,返回cellCode本身
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建带项目名称的计算过程字符串
|
|
|
+ * @param formula 原始公式,如 "(A1+A2+A3)"
|
|
|
+ * @param referencedCellsDebug 引用单元格的值列表,如 ["A1=10", "A2=20", "A3=30"]
|
|
|
+ * @param cellCodeToItemNameMap cellCode到项目名称的映射
|
|
|
+ * @return 计算过程字符串,如 "基本工资(10) + 津贴(20) + 奖金(30)"
|
|
|
+ */
|
|
|
+ private String buildCalculationProcessWithNames(String formula, List<String> referencedCellsDebug,
|
|
|
+ Map<String, String> cellCodeToItemNameMap) {
|
|
|
+ String process = formula;
|
|
|
+
|
|
|
+ // 将引用单元格替换为 "项目名称(值)" 的格式
|
|
|
+ for (String cellDebug : referencedCellsDebug) {
|
|
|
+ String[] parts = cellDebug.split("=");
|
|
|
+ if (parts.length == 2) {
|
|
|
+ String cellCode = parts[0];
|
|
|
+ String value = parts[1];
|
|
|
+ String itemName = cellCodeToItemNameMap.getOrDefault(cellCode, cellCode);
|
|
|
+
|
|
|
+ // 构建替换字符串:基本工资(10)
|
|
|
+ String replacement = itemName + "(" + value + ")";
|
|
|
+
|
|
|
+ // 使用正则表达式替换,确保只替换完整的单元格引用
|
|
|
+ process = process.replaceAll("\\b" + cellCode + "\\b", replacement);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return process;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建标题样式
|
|
|
+ */
|
|
|
+ private CellStyle createTitleStyle(Workbook workbook) {
|
|
|
+ CellStyle style = workbook.createCellStyle();
|
|
|
+
|
|
|
+ // 字体设置
|
|
|
+ Font font = workbook.createFont();
|
|
|
+ font.setFontName("宋体");
|
|
|
+ font.setFontHeightInPoints((short) 16);
|
|
|
+ font.setBold(true);
|
|
|
+ style.setFont(font);
|
|
|
+
|
|
|
+ // 对齐方式
|
|
|
+ style.setAlignment(org.apache.poi.ss.usermodel.HorizontalAlignment.CENTER);
|
|
|
+ style.setVerticalAlignment(org.apache.poi.ss.usermodel.VerticalAlignment.CENTER);
|
|
|
+
|
|
|
+ return style;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建表头样式
|
|
|
+ */
|
|
|
+ private CellStyle createHeaderStyle(Workbook workbook) {
|
|
|
+ CellStyle style = workbook.createCellStyle();
|
|
|
+
|
|
|
+ // 字体设置
|
|
|
+ Font font = workbook.createFont();
|
|
|
+ font.setFontName("宋体");
|
|
|
+ font.setFontHeightInPoints((short) 11);
|
|
|
+ font.setBold(true);
|
|
|
+ style.setFont(font);
|
|
|
+
|
|
|
+ // 对齐方式
|
|
|
+ style.setAlignment(org.apache.poi.ss.usermodel.HorizontalAlignment.CENTER);
|
|
|
+ style.setVerticalAlignment(org.apache.poi.ss.usermodel.VerticalAlignment.CENTER);
|
|
|
+
|
|
|
+ // 边框
|
|
|
+ style.setBorderTop(org.apache.poi.ss.usermodel.BorderStyle.THIN);
|
|
|
+ style.setBorderBottom(org.apache.poi.ss.usermodel.BorderStyle.THIN);
|
|
|
+ style.setBorderLeft(org.apache.poi.ss.usermodel.BorderStyle.THIN);
|
|
|
+ style.setBorderRight(org.apache.poi.ss.usermodel.BorderStyle.THIN);
|
|
|
+
|
|
|
+ // 背景色(浅灰色)
|
|
|
+ style.setFillForegroundColor(org.apache.poi.ss.usermodel.IndexedColors.GREY_25_PERCENT.getIndex());
|
|
|
+ style.setFillPattern(org.apache.poi.ss.usermodel.FillPatternType.SOLID_FOREGROUND);
|
|
|
+
|
|
|
+ return style;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建数据样式
|
|
|
+ */
|
|
|
+ private CellStyle createDataStyle(Workbook workbook) {
|
|
|
+ CellStyle style = workbook.createCellStyle();
|
|
|
+
|
|
|
+ // 字体设置
|
|
|
+ Font font = workbook.createFont();
|
|
|
+ font.setFontName("宋体");
|
|
|
+ font.setFontHeightInPoints((short) 11);
|
|
|
+ style.setFont(font);
|
|
|
+
|
|
|
+ // 对齐方式
|
|
|
+ style.setAlignment(org.apache.poi.ss.usermodel.HorizontalAlignment.CENTER);
|
|
|
+ style.setVerticalAlignment(org.apache.poi.ss.usermodel.VerticalAlignment.CENTER);
|
|
|
+
|
|
|
+ // 边框
|
|
|
+ style.setBorderTop(org.apache.poi.ss.usermodel.BorderStyle.THIN);
|
|
|
+ style.setBorderBottom(org.apache.poi.ss.usermodel.BorderStyle.THIN);
|
|
|
+ style.setBorderLeft(org.apache.poi.ss.usermodel.BorderStyle.THIN);
|
|
|
+ style.setBorderRight(org.apache.poi.ss.usermodel.BorderStyle.THIN);
|
|
|
+
|
|
|
+ return style;
|
|
|
+ }
|
|
|
}
|