在创建表格时,如何在满足 第二列 文字 等于 “合计” 时,单元格向右合并两个,实现以下效果:
我弄了很久,没有实现,麻烦指导下
下面是我的代码:
public class TestWord12 {
public static void main(String[] args) throws Exception {
String json=" [\n" +
" {\n" +
" \"MODAL_TYPE\": \"境内\",\n" +
" \"RMB_VALUE_BJ\": \"-6207115000.0000\",\n" +
" \"RMB_VALUE\": \"19379425000.0000\",\n" +
" \"TIME_LAG\": \"短期\",\n" +
" \"RMB_RATE_BJ\": \"-0.0359\",\n" +
" \"RMB_RATE\": \"2.0354\",\n" +
" \"COMPANY_CODE_CN\": \"A股份有限公司\"\n" +
" },\n" +
" {\n" +
" \"MODAL_TYPE\": \"境外\",\n" +
" \"RMB_VALUE_BJ\": \"-6207115000.0000\",\n" +
" \"RMB_VALUE\": \"19379425000.0000\",\n" +
" \"TIME_LAG\": \"短期\",\n" +
" \"RMB_RATE_BJ\": \"-0.0359\",\n" +
" \"RMB_RATE\": \"2.0354\",\n" +
" \"COMPANY_CODE_CN\": \"A股份有限公司\"\n" +
" },\n" +
" {\n" +
" \"MODAL_TYPE\": \"境内\",\n" +
" \"RMB_VALUE_BJ\": \"-109840001.5600\",\n" +
" \"RMB_VALUE\": \"2966914882.3300\",\n" +
" \"TIME_LAG\": \"中期\",\n" +
" \"RMB_RATE_BJ\": \"0.0659\",\n" +
" \"RMB_RATE\": \"2.9100\",\n" +
" \"COMPANY_CODE_CN\": \"B科技有限公司\"\n" +
" },\n" +
" {\n" +
" \"MODAL_TYPE\": \"境外\",\n" +
" \"RMB_VALUE_BJ\": \"-109840001.5600\",\n" +
" \"RMB_VALUE\": \"2966914882.3300\",\n" +
" \"TIME_LAG\": \"中期\",\n" +
" \"RMB_RATE_BJ\": \"0.0659\",\n" +
" \"RMB_RATE\": \"2.9100\",\n" +
" \"COMPANY_CODE_CN\": \"B科技有限公司\"\n" +
" },\n" +
" {\n" +
" \"MODAL_TYPE\": \"境内\",\n" +
" \"RMB_VALUE_BJ\": \"-7150000.0000\",\n" +
" \"RMB_VALUE\": \"20269800000.0000\",\n" +
" \"TIME_LAG\": \"中期\",\n" +
" \"RMB_RATE_BJ\": \"-0.0024\",\n" +
" \"RMB_RATE\": \"2.0384\",\n" +
" \"COMPANY_CODE_CN\": \"A股份有限公司\"\n" +
" },\n" +
" {\n" +
" \"MODAL_TYPE\": \"境外\",\n" +
" \"RMB_VALUE_BJ\": \"-7150000.0000\",\n" +
" \"RMB_VALUE\": \"20269800000.0000\",\n" +
" \"TIME_LAG\": \"中期\",\n" +
" \"RMB_RATE_BJ\": \"-0.0024\",\n" +
" \"RMB_RATE\": \"2.0384\",\n" +
" \"COMPANY_CODE_CN\": \"A股份有限公司\"\n" +
" },\n" +
" {\n" +
" \"MODAL_TYPE\": \"境内\",\n" +
" \"RMB_VALUE_BJ\": \"-3000000.0000\",\n" +
" \"RMB_VALUE\": \"27000000.0000\",\n" +
" \"TIME_LAG\": \"中期\",\n" +
" \"RMB_RATE_BJ\": \"0.0000\",\n" +
" \"RMB_RATE\": \"3.5500\",\n" +
" \"COMPANY_CODE_CN\": \"C技术有限公司\"\n" +
" },\n" +
" {\n" +
" \"MODAL_TYPE\": \"境外\",\n" +
" \"RMB_VALUE_BJ\": \"-3000000.0000\",\n" +
" \"RMB_VALUE\": \"27000000.0000\",\n" +
" \"TIME_LAG\": \"中期\",\n" +
" \"RMB_RATE_BJ\": \"0.0000\",\n" +
" \"RMB_RATE\": \"3.5500\",\n" +
" \"COMPANY_CODE_CN\": \"C技术有限公司\"\n" +
" },\n" +
" {\n" +
" \"MODAL_TYPE\": \"境内\",\n" +
" \"RMB_VALUE_BJ\": \"-2800000.0000\",\n" +
" \"RMB_VALUE\": \"2150000.0000\",\n" +
" \"TIME_LAG\": \"中期\",\n" +
" \"RMB_RATE_BJ\": \"0.0000\",\n" +
" \"RMB_RATE\": \"3.7000\",\n" +
" \"COMPANY_CODE_CN\": \"D有限公司\"\n" +
" },\n" +
" {\n" +
" \"MODAL_TYPE\": \"境外\",\n" +
" \"RMB_VALUE_BJ\": \"-2800000.0000\",\n" +
" \"RMB_VALUE\": \"2150000.0000\",\n" +
" \"TIME_LAG\": \"中期\",\n" +
" \"RMB_RATE_BJ\": \"0.0000\",\n" +
" \"RMB_RATE\": \"3.7000\",\n" +
" \"COMPANY_CODE_CN\": \"D有限公司\"\n" +
" },\n" +
" {\n" +
" \"MODAL_TYPE\": \"境内\",\n" +
" \"RMB_VALUE_BJ\": \"0.0000\",\n" +
" \"RMB_VALUE\": \"16500000.0000\",\n" +
" \"TIME_LAG\": \"中期\",\n" +
" \"RMB_RATE_BJ\": \"0.0000\",\n" +
" \"RMB_RATE\": \"3.5800\",\n" +
" \"COMPANY_CODE_CN\": \"E有限公司\"\n" +
" },\n" +
" {\n" +
" \"MODAL_TYPE\": \"境外\",\n" +
" \"RMB_VALUE_BJ\": \"0.0000\",\n" +
" \"RMB_VALUE\": \"16500000.0000\",\n" +
" \"TIME_LAG\": \"中期\",\n" +
" \"RMB_RATE_BJ\": \"0.0000\",\n" +
" \"RMB_RATE\": \"3.5800\",\n" +
" \"COMPANY_CODE_CN\": \"E有限公司\"\n" +
" },\n" +
" {\n" +
" \"MODAL_TYPE\": \"境内\",\n" +
" \"RMB_VALUE_BJ\": \"0.0000\",\n" +
" \"RMB_VALUE\": \"30384511.2100\",\n" +
" \"TIME_LAG\": \"中期\",\n" +
" \"RMB_RATE_BJ\": \"0.0000\",\n" +
" \"RMB_RATE\": \"3.5434\",\n" +
" \"COMPANY_CODE_CN\": \"F科技有限公司\"\n" +
" },\n" +
" {\n" +
" \"MODAL_TYPE\": \"境外\",\n" +
" \"RMB_VALUE_BJ\": \"0.0000\",\n" +
" \"RMB_VALUE\": \"30384511.2100\",\n" +
" \"TIME_LAG\": \"中期\",\n" +
" \"RMB_RATE_BJ\": \"0.0000\",\n" +
" \"RMB_RATE\": \"3.5434\",\n" +
" \"COMPANY_CODE_CN\": \"F科技有限公司\"\n" +
" },\n" +
" {\n" +
" \"MODAL_TYPE\": \"境内\",\n" +
" \"RMB_VALUE_BJ\": \"0.0000\",\n" +
" \"RMB_VALUE\": \"1330000000.0000\",\n" +
" \"TIME_LAG\": \"短期\",\n" +
" \"RMB_RATE_BJ\": \"-0.1690\",\n" +
" \"RMB_RATE\": \"2.3445\",\n" +
" \"COMPANY_CODE_CN\": \"G城发展有限公司(委托)\"\n" +
" },\n" +
" {\n" +
" \"MODAL_TYPE\": \"境外\",\n" +
" \"RMB_VALUE_BJ\": \"0.0000\",\n" +
" \"RMB_VALUE\": \"1330000000.0000\",\n" +
" \"TIME_LAG\": \"短期\",\n" +
" \"RMB_RATE_BJ\": \"-0.1690\",\n" +
" \"RMB_RATE\": \"2.3445\",\n" +
" \"COMPANY_CODE_CN\": \"G城发展有限公司(委托)\"\n" +
" },\n" +
" {\n" +
" \"MODAL_TYPE\": \"ALL\",\n" +
" \"RMB_VALUE_BJ\": \"0.0000\",\n" +
" \"RMB_VALUE\": \"46708423237.1900\",\n" +
" \"TIME_LAG\": \"ALL\",\n" +
" \"RMB_RATE_BJ\": \"0.0000\",\n" +
" \"RMB_RATE\": \"2.1836\",\n" +
" \"COMPANY_CODE_CN\": \"ALL\"\n" +
" },\n" +
" {\n" +
" \"MODAL_TYPE\": \"境内\",\n" +
" \"RMB_VALUE_BJ\": \"196000000.0000\",\n" +
" \"RMB_VALUE\": \"651693198.1300\",\n" +
" \"TIME_LAG\": \"短期\",\n" +
" \"RMB_RATE_BJ\": \"-0.0003\",\n" +
" \"RMB_RATE\": \"2.5007\",\n" +
" \"COMPANY_CODE_CN\": \"B科技有限公司\"\n" +
" },\n" +
" {\n" +
" \"MODAL_TYPE\": \"境外\",\n" +
" \"RMB_VALUE_BJ\": \"196000000.0000\",\n" +
" \"RMB_VALUE\": \"651693198.1300\",\n" +
" \"TIME_LAG\": \"短期\",\n" +
" \"RMB_RATE_BJ\": \"-0.0003\",\n" +
" \"RMB_RATE\": \"2.5007\",\n" +
" \"COMPANY_CODE_CN\": \"B科技有限公司\"\n" +
" },\n" +
" {\n" +
" \"MODAL_TYPE\": \"境内\",\n" +
" \"RMB_VALUE_BJ\": \"325000000.0000\",\n" +
" \"RMB_VALUE\": \"325000000.0000\",\n" +
" \"TIME_LAG\": \"短期\",\n" +
" \"RMB_RATE_BJ\": \"3.5500\",\n" +
" \"RMB_RATE\": \"3.5500\",\n" +
" \"COMPANY_CODE_CN\": \"湛江宝航置业有限公司\"\n" +
" },\n" +
" {\n" +
" \"MODAL_TYPE\": \"境外\",\n" +
" \"RMB_VALUE_BJ\": \"325000000.0000\",\n" +
" \"RMB_VALUE\": \"325000000.0000\",\n" +
" \"TIME_LAG\": \"短期\",\n" +
" \"RMB_RATE_BJ\": \"3.5500\",\n" +
" \"RMB_RATE\": \"3.5500\",\n" +
" \"COMPANY_CODE_CN\": \"E有限公司\"\n" +
" },\n" +
" {\n" +
" \"MODAL_TYPE\": \"境外\",\n" +
" \"RMB_VALUE_BJ\": \"1709555645.5200\",\n" +
" \"RMB_VALUE\": \"1709555645.5200\",\n" +
" \"TIME_LAG\": \"ALL\",\n" +
" \"RMB_RATE_BJ\": \"-0.1868\",\n" +
" \"RMB_RATE\": \"3.7566\",\n" +
" \"COMPANY_CODE_CN\": \"ALL\"\n" +
" },\n" +
" {\n" +
" \"MODAL_TYPE\": \"境内\",\n" +
" \"RMB_VALUE_BJ\": \"44998867591.6700\",\n" +
" \"RMB_VALUE\": \"44998867591.6700\",\n" +
" \"TIME_LAG\": \"ALL\",\n" +
" \"RMB_RATE_BJ\": \"0.1504\",\n" +
" \"RMB_RATE\": \"1.5862\",\n" +
" \"COMPANY_CODE_CN\": \"ALL\"\n" +
" }\n" +
" ]";
// 1. 加载模板
Document doc = new Document("/Users/WorkSpace/file/testTemplate.docx");
String COMPANY_CODE="";
//融资种类文本描述+表格
List<Map<String,Object>> rz_financialInstitutionInfo = JSON.parseObject(json,List.class);
EiInfo eiInfo = new EiInfo();
EiInfo resultEiInfo = new EiInfo();
eiInfo.set("financingTermInfo", rz_financialInstitutionInfo);
//表格
FINANCING_TERM_INFO_TABLE(eiInfo, resultEiInfo);
// 3. 执行表格占位符替换
ReplaceWithCustomTableHandlerFM04 processor = new ReplaceWithCustomTableHandlerFM04();
System.out.println(JSON.toJSONString((Map<String, Object>) resultEiInfo.get("FINANCING_TERM_INFO_TABLE")));
processor.process(doc, "{tb2}", (Map<String, Object>) resultEiInfo.get("FINANCING_TERM_INFO_TABLE"));
// 4. 保存文档
doc.save("output.docx");
}
public static void FINANCING_TERM_INFO_TABLE(EiInfo inInfo, EiInfo resultEiInfo) {
Map<String, Object> FINANCING_TERM_INFO_TABLE = new HashMap<>();
FINANCING_TERM_INFO_TABLE.put("hide", true);
System.err.println();
List<Map<String, Object>> financingTermInfoList = (List<Map<String, Object>>) inInfo.get("financingTermInfo");
if (CollectionUtils.isNotEmpty(financingTermInfoList)) {
List<Map<String, Object>> jn_list = financingTermInfoList.stream()
.filter(p -> "境内".equals(MapUtils.getString(p, "MODAL_TYPE"))
&& !"ALL".equals(MapUtils.getString(p, "TIME_LAG")))
.sorted(Comparator.comparing(p -> MapUtils.getString(p, "COMPANY_CODE_CN")))
.collect(Collectors.toList());
//筛选境外
List<Map<String, Object>> jw_list = financingTermInfoList.stream()
.filter(p -> "境外".equals(MapUtils.getString(p, "MODAL_TYPE"))
&& !"ALL".equals(MapUtils.getString(p, "TIME_LAG")))
.sorted(Comparator.comparing(p -> MapUtils.getString(p, "COMPANY_CODE_CN")))
.collect(Collectors.toList());
List<String> header = new ArrayList<>();
if (CollectionUtils.isNotEmpty(jn_list) && CollectionUtils.isNotEmpty(jw_list)) {
header = Arrays.asList("融资单位地区", "融资单位", "合同期限", "融资规模-本期", "融资规模-较上期", "融资成本率-本期", "融资成本率-较上期");
} else {
header = Arrays.asList("融资单位", "合同期限", "融资规模-本期", "融资规模-较上期", "融资成本率-本期", "融资成本率-较上期");
}
List<Object> tableDtaList = new ArrayList<>();
if (CollectionUtils.isNotEmpty(jn_list)) {
for (Map<String, Object> dataItemMap : jn_list) {
List<Object> rowData = new ArrayList<>();
String companyCodeCn = MapUtils.getString(dataItemMap, "COMPANY_CODE_CN");
String timeLag = MapUtils.getString(dataItemMap, "TIME_LAG");
String rmbValue = MapUtils.getString(dataItemMap, "RMB_VALUE");
String rmbValueBj = MapUtils.getString(dataItemMap, "RMB_VALUE_BJ");
String rmbRate = MapUtils.getString(dataItemMap, "RMB_RATE");
String rmbRateBj = MapUtils.getString(dataItemMap, "RMB_RATE_BJ");
rowData.add("境内");
rowData.add(companyCodeCn);
rowData.add(timeLag);
rowData.add(NumberFormatter.formatNumber(rmbValue, 2, "亿元"));
rowData.add(NumberFormatter.formatNumber(rmbValueBj, 2, "亿元"));
rowData.add(NumberFormatter.formatNumber(rmbRate, 2, ""));
rowData.add(NumberFormatter.formatNumber(rmbRateBj, 2, ""));
tableDtaList.add(rowData);
}
}
//找出境内的合计数据
Optional<Map<String, Object>> jn_totalOptional = financingTermInfoList.stream().filter(p -> "ALL".equals(MapUtils.getString(p, "TIME_LAG")) && MapUtils.getString(p, "MODAL_TYPE").equals("境内")).findFirst();
if (jn_totalOptional.isPresent()) {
Map<String, Object> jn_total = jn_totalOptional.get();
List<Object> jnTotalRow = new ArrayList<>();
String rmbValue = MapUtils.getString(jn_total, "RMB_VALUE");
String rmbValueBj = MapUtils.getString(jn_total, "RMB_VALUE_BJ");
String rmbRate = MapUtils.getString(jn_total, "RMB_RATE");
String rmbRateBj = MapUtils.getString(jn_total, "RMB_RATE_BJ");
jnTotalRow.add("境内");
jnTotalRow.add("合计");
jnTotalRow.add("");
jnTotalRow.add(NumberFormatter.formatNumber(rmbValue, 2, "亿元"));
jnTotalRow.add(NumberFormatter.formatNumber(rmbValueBj, 2, "亿元"));
jnTotalRow.add(NumberFormatter.formatNumber(rmbRate, 2, ""));
jnTotalRow.add(NumberFormatter.formatNumber(rmbRateBj, 2, ""));
tableDtaList.add(jnTotalRow);
}
if (CollectionUtils.isNotEmpty(jw_list)) {
for (Map<String, Object> dataItemMap : jw_list) {
List<Object> rowData = new ArrayList<>();
String companyCodeCn = MapUtils.getString(dataItemMap, "COMPANY_CODE_CN");
String timeLag = MapUtils.getString(dataItemMap, "TIME_LAG");
String rmbValue = MapUtils.getString(dataItemMap, "RMB_VALUE");
String rmbValueBj = MapUtils.getString(dataItemMap, "RMB_VALUE_BJ");
String rmbRate = MapUtils.getString(dataItemMap, "RMB_RATE");
String rmbRateBj = MapUtils.getString(dataItemMap, "RMB_RATE_BJ");
rowData.add("境外");
rowData.add(companyCodeCn);
rowData.add(timeLag);
rowData.add(NumberFormatter.formatNumber(rmbValue, 2, "亿元"));
rowData.add(NumberFormatter.formatNumber(rmbValueBj, 2, "亿元"));
rowData.add(NumberFormatter.formatNumber(rmbRate, 2, ""));
rowData.add(NumberFormatter.formatNumber(rmbRateBj, 2, ""));
tableDtaList.add(rowData);
}
}
//境外合计
Optional<Map<String, Object>> jw_totalOptional = financingTermInfoList.stream().filter(p -> "ALL".equals(MapUtils.getString(p, "TIME_LAG")) && MapUtils.getString(p, "MODAL_TYPE").equals("境外")).findFirst();
if (jw_totalOptional.isPresent()) {
Map<String, Object> jw_total = jw_totalOptional.get();
List<Object> jwTotalRow = new ArrayList<>();
String rmbValue = MapUtils.getString(jw_total, "RMB_VALUE");
String rmbValueBj = MapUtils.getString(jw_total, "RMB_VALUE_BJ");
String rmbRate = MapUtils.getString(jw_total, "RMB_RATE");
String rmbRateBj = MapUtils.getString(jw_total, "RMB_RATE_BJ");
jwTotalRow.add("境外");
jwTotalRow.add("合计");
jwTotalRow.add("");
jwTotalRow.add(NumberFormatter.formatNumber(rmbValue, 2, "亿元"));
jwTotalRow.add(NumberFormatter.formatNumber(rmbValueBj, 2, "亿元"));
jwTotalRow.add(NumberFormatter.formatNumber(rmbRate, 2, ""));
jwTotalRow.add(NumberFormatter.formatNumber(rmbRateBj, 2, ""));
tableDtaList.add(jwTotalRow);
}
//找出总计数据
Optional<Map<String, Object>> totalOptional = financingTermInfoList.stream().filter(p -> "ALL".equals(MapUtils.getString(p, "TIME_LAG")) && MapUtils.getString(p, "MODAL_TYPE").equals("ALL")).findFirst();
if (totalOptional.isPresent()) {
Map<String, Object> sumMap = new HashMap<>();
Map<String, Object> total = totalOptional.get();
List<Object> totalRow = new ArrayList<>();
String rmbValue = MapUtils.getString(total, "RMB_VALUE");
String rmbValueBj = MapUtils.getString(total, "RMB_VALUE_BJ");
String rmbRate = MapUtils.getString(total, "RMB_RATE");
String rmbRateBj = MapUtils.getString(total, "RMB_RATE_BJ");
totalRow.add("总计");
totalRow.add("总计");
totalRow.add("总计");
totalRow.add(NumberFormatter.formatNumber(rmbValue, 2, "亿元"));
totalRow.add(NumberFormatter.formatNumber(rmbValueBj, 2, "亿元"));
totalRow.add(NumberFormatter.formatNumber(rmbRate, 2, ""));
totalRow.add(NumberFormatter.formatNumber(rmbRateBj, 2, ""));
sumMap.put("dataList", totalRow);
sumMap.put("endMergeIndex", 3);
FINANCING_TERM_INFO_TABLE.put("summaryRowMap", sumMap);
}
FINANCING_TERM_INFO_TABLE.remove("hide");
FINANCING_TERM_INFO_TABLE.put("tableDataList", tableDtaList);
FINANCING_TERM_INFO_TABLE.put("header", header);
}
resultEiInfo.set("FINANCING_TERM_INFO_TABLE", FINANCING_TERM_INFO_TABLE);
}
}
public class ReplaceWithCustomTableHandlerFM04 implements CustomDocumentTableProcessor {
private Map<String, Object> tableData;
@Override
public void process(Document document, String placeholderName, Map<String, Object> tableData) throws Exception {
this.tableData = tableData;
DocumentBuilder builder = new DocumentBuilder(document);
// 1️⃣ 查找占位符
FindReplaceOptions options = new FindReplaceOptions();
options.setReplacingCallback(args -> {
List<String> header = (List<String>) tableData.get("header");
List<Double> colWidths = null;
int startIndex = 0;
int endIndex = 0;
if (header.size() == 7) {
startIndex = 0;
colWidths = Arrays.asList(10.0, 20.0, 14.0, 14.0, 14.0, 14.0, 14.0);
} else {
startIndex = 1;
colWidths = Arrays.asList(0.0, 30.0, 14.0, 14.0, 14.0, 14.0, 14.0);
}
// 定义各列的百分比宽度
// 打印捕获的内容
// 定位到占位符
builder.moveTo(args.getMatchNode());
DocumentTableUtil.resetBuilderTableFormat(builder);
addHeaderRow(builder, colWidths);
addDataRows(builder, colWidths, startIndex, endIndex);
//合并单元格
//删除占位符
args.getMatchNode().remove();
return ReplaceAction.SKIP; // 跳过默认替换
});
// 5️⃣ 执行替换
document.getRange().replace(Pattern.compile(Pattern.quote(placeholderName)), "", options);
}
private void addHeaderRow(DocumentBuilder builder, List<Double> colWidths) throws Exception {
int size = colWidths.size();
if (size == 7) {
// 🔵 第一行表头(3列版本)
insertMergedCell(builder, "融资单位地区", colWidths.get(0), CellMerge.FIRST, CellMerge.NONE);
insertMergedCell(builder, "融资单位", colWidths.get(1), CellMerge.FIRST, CellMerge.NONE);
insertMergedCell(builder, "合同期限", colWidths.get(2), CellMerge.FIRST, CellMerge.NONE);
insertMergedCell(builder, "外部融资规模/亿元", colWidths.get(3) + colWidths.get(4), CellMerge.NONE, CellMerge.FIRST);
builder.insertCell(); // 插入一个空单元格,继续横向合并
builder.getCellFormat().setHorizontalMerge(CellMerge.PREVIOUS);
insertMergedCell(builder, "外部融资成本率", colWidths.get(5) + colWidths.get(6), CellMerge.NONE, CellMerge.FIRST);
builder.insertCell();
builder.getCellFormat().setHorizontalMerge(CellMerge.PREVIOUS);
builder.endRow();
// 🔵 第二行表头(子标题)
insertMergedCell(builder, "", colWidths.get(0), CellMerge.PREVIOUS, CellMerge.NONE);
insertMergedCell(builder, "", colWidths.get(1), CellMerge.PREVIOUS, CellMerge.NONE);
insertMergedCell(builder, "", colWidths.get(2), CellMerge.PREVIOUS, CellMerge.NONE);
insertCell(builder, "当期", colWidths.get(3));
insertCell(builder, "较上期", colWidths.get(4));
insertCell(builder, "当期", colWidths.get(5));
insertCell(builder, "较上期", colWidths.get(6));
builder.endRow();
}
if (size == 6) {
// 🔵 第一行表头(3列版本)
insertMergedCell(builder, "融资单位", colWidths.get(1), CellMerge.FIRST, CellMerge.NONE);
insertMergedCell(builder, "合同期限", colWidths.get(2), CellMerge.FIRST, CellMerge.NONE);
insertMergedCell(builder, "外部融资规模/亿元", colWidths.get(3) + colWidths.get(4), CellMerge.NONE, CellMerge.FIRST);
builder.insertCell(); // 插入一个空单元格,继续横向合并
builder.getCellFormat().setHorizontalMerge(CellMerge.PREVIOUS);
insertMergedCell(builder, "外部融资成本率", colWidths.get(5) + colWidths.get(6), CellMerge.NONE, CellMerge.FIRST);
builder.insertCell();
builder.getCellFormat().setHorizontalMerge(CellMerge.PREVIOUS);
builder.endRow();
// 🔵 第二行表头(子标题)
insertMergedCell(builder, "", colWidths.get(1), CellMerge.PREVIOUS, CellMerge.NONE);
insertMergedCell(builder, "", colWidths.get(2), CellMerge.PREVIOUS, CellMerge.NONE);
insertCell(builder, "当期", colWidths.get(3));
insertCell(builder, "较上期", colWidths.get(4));
insertCell(builder, "当期", colWidths.get(5));
insertCell(builder, "较上期", colWidths.get(6));
builder.endRow();
}
}
// 工具方法:插入合并单元格(支持纵向和横向合并)
private void insertMergedCell(DocumentBuilder builder, String text, double width, int verticalMerge, int horizontalMerge) throws Exception {
builder.insertCell();
builder.getCellFormat().setPreferredWidth(PreferredWidth.fromPercent(width));
builder.getCellFormat().setVerticalMerge(verticalMerge);
builder.getCellFormat().setHorizontalMerge(horizontalMerge);
setCellStyle(builder, text);
}
// 工具方法:插入普通单元格
private void insertCell(DocumentBuilder builder, String text, double width) throws Exception {
builder.insertCell();
builder.getCellFormat().setPreferredWidth(PreferredWidth.fromPercent(width));
builder.getCellFormat().setVerticalMerge(CellMerge.NONE);
builder.getCellFormat().setHorizontalMerge(CellMerge.NONE);
setCellStyle(builder, text);
}
// 工具方法:设置单元格样式
private void setCellStyle(DocumentBuilder builder, String text) throws Exception {
//单元格背景色
builder.getCellFormat().getShading().setBackgroundPatternColor(new Color(128, 128, 128));
//字体颜色
builder.getFont().setColor(Color.BLACK);
//加粗
builder.getFont().setBold(true);
//字号
builder.getFont().setSize(10);
builder.getParagraphFormat().setAlignment(ParagraphAlignment.CENTER);
builder.getCellFormat().setVerticalAlignment(CellVerticalAlignment.CENTER);
builder.getRowFormat().getBorders().setLineWidth(1.0); // 1磅
builder.getRowFormat().getBorders().setColor(Color.BLACK); // 直接用黑色
builder.getRowFormat().getBorders().setLineStyle(LineStyle.SINGLE); // 单实线
if (!text.isEmpty()) {
builder.write(text);
}
}
private void addDataRows(DocumentBuilder builder, List<Double> colWidths, int startIndex, int endIndex) throws Exception {
//字体颜色
builder.getFont().setColor(Color.BLACK);
//拒绝字体加粗
builder.getFont().setBold(false);
//这行代码禁用单元格中的文本自动换行功能
builder.getCellFormat().setWrapText(false);
builder.getRowFormat().setHeadingFormat(false); // 确保内容行不设置为表头
//字号
builder.getFont().setSize(10);
//默认背景色
builder.getCellFormat().getShading().setBackgroundPatternColor(new Color(255, 255, 255));
List<List<Object>> tableDataList = (List<List<Object>>) tableData.get("tableDataList");// 数据集
Map summaryRowMap = (Map) tableData.get("summaryRowMap");
String previousFirstColumnValue = null; // 用于记录上一个单元格第一列的值
String previousSecondColumnValue = null; // 新增变量用于第二列合并
if (startIndex == 0) {
if (CollectionUtils.isNotEmpty(tableDataList)) {
for (int i = 0; i < tableDataList.size(); i++) {
List<Object> list = tableDataList.get(i);
DocumentTableUtil.setTableBodyFormat(builder);
int rowIndex = 0;
if (CollectionUtils.isNotEmpty(list)) {
for (int j = 0; j < list.size(); j++) {
builder.insertCell();
builder.getCellFormat().setPreferredWidth(PreferredWidth.fromPercent(colWidths.get(j)));
Object object = list.get(j);
String value = object != null ? object.toString() : "";
//第二列也要合并
if (j == 0) {
// 只处理第一列的合并逻辑
if (i > 0 && value.equals(previousFirstColumnValue)) {
// 当前行、第一列,跟上一行一样
builder.getCellFormat().setVerticalMerge(CellMerge.PREVIOUS);
// 不需要写内容了,跳过写入
continue;
} else {
// 不一样,新的合并开始
builder.getCellFormat().setVerticalMerge(CellMerge.FIRST);
}
previousFirstColumnValue = value; // 更新记录
} else if (j == 1) {
if(value.equals("合计")){
//加粗
builder.getFont().setBold(true);
}
// 正常垂直合并逻辑
if (i > 0 && value.equals(previousSecondColumnValue)) {
builder.getCellFormat().setVerticalMerge(CellMerge.PREVIOUS);
continue;
} else {
builder.getCellFormat().setVerticalMerge(CellMerge.FIRST);
}
builder.getCellFormat().setHorizontalMerge(CellMerge.NONE);
previousSecondColumnValue = value;
/*
if (i > 0 && value.equals(previousSecondColumnValue)) {
builder.getCellFormat().setVerticalMerge(CellMerge.PREVIOUS);
continue; // 合并格子不需要写入文字
} else {
builder.getCellFormat().setVerticalMerge(CellMerge.FIRST);
}
previousSecondColumnValue = value; // 记录当前第二列内容*/
} else {
// 其他列不做合并
builder.getCellFormat().setVerticalMerge(CellMerge.NONE);
}
builder.write(value);
}
builder.endRow();
}
}
if (summaryRowMap != null) {
List<Object> dataList = (List<Object>) MapUtils.getObject(summaryRowMap, "dataList", new ArrayList<>());
//addSummaryRow(builder, endMergeIndex, label, dataList, null);
DocumentTableUtil.addSummaryRowCustomize(builder, 1, 3, "合计", dataList, null, colWidths);
}
}
}
}
}