<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.12.2</version>
</dependency>
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.17</version>
</dependency>
package com.example.demo.utils;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class MergeUtil {
/**
* @Description: 跨行合并
* table要合并单元格的表格
* col要合并哪一列的单元格
* fromRow从哪一行开始合并单元格
* toRow合并到哪一个行
*/
public void mergeCellsVertically(XWPFTable table, int col, int fromRow, int toRow) {
for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) {
XWPFTableCell cell = table.getRow(rowIndex).getCell(col);
if (rowIndex == fromRow) {
// The first merged cell is set with RESTART merge value
cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
} else {
// Cells which join (merge) the first one, are set with CONTINUE
cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
}
}
XWPFTableCell cell = table.getRow(fromRow).getCell(col);
CTTc cttc = cell.getCTTc();
CTTcPr ctPr = cttc.addNewTcPr();
ctPr.addNewVAlign().setVal(STVerticalJc.CENTER);
cttc.getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER);
}
/**
* 动态根据填充数据 合并单元格 指定列 行截止
*
* @param table 指定表格
* @param tbDatas 表格填充的数据 {a:[1,2,3,4....],[1,2,3,4....],[...]} 按行填充
* @param beginRowIndex 起始行
* @param endRowIndex 终止行
* @param beginColIndex 起始列
* @param endColIndex 终止列
*/
public static void mergeTable(XWPFTable table, Map<Integer,List<String>> tbDatas, int beginRowIndex,int endRowIndex, int beginColIndex,int endColIndex) {
// 创建一个二维数组来保存每个单元格填充的内容
String[][] cellContents = new String[endRowIndex-beginRowIndex][endColIndex-beginColIndex];
// 遍历每个单元格,保存内容到二维数组
for (int row = beginRowIndex; row < endRowIndex; row++) {
XWPFTableRow tableRow = table.getRow(row);
List<String> rslt = tbDatas.containsKey(row - beginColIndex) ? tbDatas.get(row - beginRowIndex) : new ArrayList<String>();
for (int col = beginColIndex; col < endColIndex; col++) {
if(rslt!=null &&rslt.size()>0) {
cellContents[row-beginRowIndex][col-beginColIndex] = rslt.get(col-beginColIndex) == null?"":rslt.get(col-beginColIndex);
}
}
}
// 合并相同内容的单元格
for (int row = beginRowIndex; row < endRowIndex; row++) {
for (int col = beginColIndex; col < endColIndex; col++) {
String cellContent = cellContents[row-beginRowIndex][col-beginColIndex];
if (cellContent != null && !cellContent.isEmpty()) {
int rowspan = 1;
int colspan = 1;
// 检查下一行是否有相同内容的单元格
for (int nextRow = row + 1; nextRow < endRowIndex; nextRow++) {
if (cellContent.equals(cellContents[nextRow-beginRowIndex][col-beginColIndex])) {
rowspan++;
// 清空下一行的内容
cellContents[nextRow-beginRowIndex][col-beginColIndex] = null;
} else {
break;
}
}
// 检查下一列是否有相同内容的单元格
for (int nextCol = col + 1; nextCol < endColIndex; nextCol++) {
if (cellContent.equals(cellContents[row-beginRowIndex][nextCol-beginColIndex])) {
colspan++;
// 清空下一列的内容
cellContents[row-beginRowIndex][nextCol-beginColIndex] = null;
} else {
break;
}
}
// 合并单元格
XWPFTableCell cell = table.getRow(row).getCell(col);
// 设置合并单元格的属性
CTTcPr tcPr = cell.getCTTc().getTcPr();
if (tcPr == null) {
tcPr = cell.getCTTc().addNewTcPr();
}
tcPr.addNewVMerge().setVal(STMerge.RESTART);
tcPr.addNewHMerge().setVal(STMerge.RESTART);
// 设置合并单元格的跨度
for (int i = 0; i < rowspan - 1; i++) {
table.getRow(row + i + 1).getCell(col).getCTTc().getTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
}
for (int i = 0; i < colspan - 1; i++) {
table.getRow(row).getCell(col + i + 1).getCTTc().getTcPr().addNewHMerge().setVal(STMerge.CONTINUE);
}
}
}
}
}
}

