import org.apache.poi.xwpf.usermodel.;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.;
import java.math.BigInteger;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class WordExportUtil {
/**
* 替换 Word 文档中的占位符
*
* @param document Word文档对象
* @param placeholder 占位符名称 (例如 "{unitName}")
* @param value 占位符对应的值
*/
public static void replacePlaceholder(XWPFDocument document, String placeholder, String value) {
if (document == null || placeholder == null || value == null) {
return;
}
String regex = Pattern.quote(placeholder);
Pattern pattern = Pattern.compile(regex);
for (XWPFParagraph paragraph : document.getParagraphs()) {
Matcher matcher = pattern.matcher(paragraph.getText());
if (matcher.find()) {
// 为了安全起见,我们不直接修改paragraph的text,而是替换其run
for (XWPFRun run : paragraph.getRuns()) {
if (run.getText(0) != null && run.getText(0).contains(placeholder)) {
run.setText(run.getText(0).replace(placeholder, value), 0);
}
}
}
}
// 同时检查表格中的内容
for (XWPFTable table : document.getTables()) {
for (XWPFTableRow row : table.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
for (XWPFParagraph para : cell.getParagraphs()) {
for (XWPFRun run : para.getRuns()) {
if (run.getText(0) != null && run.getText(0).contains(placeholder)) {
run.setText(run.getText(0).replace(placeholder, value), 0);
}
}
}
}
}
}
}
/**
* 填充在线注册申请表中的账号信息表格
* 此方法会查找包含 "账号信息" 的单元格,并在该单元格内插入一个完整的表格。
* 该表格包含表头:"姓名", "手机号", "账号", "账号说明"
* 并根据 accountInfos 列表填充数据行。
*
* @param document Word文档对象
* @param accountInfos 账号信息列表
*/
public static void fillAccountTableForOnlineRegistration(XWPFDocument document, List<InternetAccountInfo> accountInfos) {
if (document == null || accountInfos == null || accountInfos.isEmpty()) {
return; // 如果文档或数据为空,则无需处理
}
// 遍历文档中的所有表格
for (XWPFTable table : document.getTables()) {
// 遍历表格中的每一行
for (XWPFTableRow row : table.getRows()) {
// 遍历该行中的每一个单元格
for (XWPFTableCell cell : row.getTableCells()) {
// 查找包含 "账号信息" 的单元格
if (cell.getText().contains("{applicationRows}")) {
// 找到了目标单元格,现在需要在其内部插入表格
insertAccountTableIntoCell(cell, accountInfos, document);
return; // 找到并处理完后退出循环
}
}
}
}
}
private static void insertAccountTableIntoCell(XWPFTableCell targetCell, List<InternetAccountInfo> accountInfos, XWPFDocument document) {
try {
// 1. 清空目标单元格内容
while (targetCell.getParagraphs().size() > 0) {
targetCell.removeParagraph(0);
}
// 2. 获取单元格对应的底层 CTTc 对象
CTTc ctTc = targetCell.getCTTc();
// 3. 创建一个新的表格 (CTTbl)
CTTbl ctTbl = ctTc.addNewTbl();
// 4. 设置表格网格(列宽可选,这里简单均分)
CTTblGrid tblGrid = ctTbl.addNewTblGrid();
int colCount = 4;
int totalWidth = 5000; // 总宽度(单位: twentieth-millimeter, 可调整)
int colWidth = totalWidth / colCount;
for (int i = 0; i < colCount; i++) {
CTTblGridCol gridCol = tblGrid.addNewGridCol();
gridCol.setW(BigInteger.valueOf(colWidth));
}
// 5. 添加表头行
CTRow headerRow = ctTbl.addNewTr();
String[] headers = {"姓名", "手机号", "账号", "账号说明"};
for (String header : headers) {
CTTc cell = headerRow.addNewTc();
cell.addNewP().addNewR().addNewT().setStringValue(header);
// 可选:设置边框或样式
}
// 6. 添加数据行
for (InternetAccountInfo info : accountInfos) {
CTRow dataRow = ctTbl.addNewTr();
addCell(dataRow, info.getName());
addCell(dataRow, info.getPhone());
addCell(dataRow, info.getAccount());
addCell(dataRow, info.getDescription());
}
// 7. (可选)设置表格边框
setTableBorders(ctTbl);
} catch (Exception e) {
e.printStackTrace();
}
}
// 辅助方法:向 CTRow 添加一个带文本的单元格
private static void addCell(CTRow row, String text) {
CTTc cell = row.addNewTc();
CTP p = cell.addNewP();
CTR r = p.addNewR();
CTText t = r.addNewT();
t.setStringValue(text != null ? text : "");
}
// 辅助方法:为 CTTbl 设置边框(单线、黑色)
private static void setTableBorders(CTTbl table) {
CTTblPr tblPr = table.getTblPr();
if (tblPr == null) {
tblPr = table.addNewTblPr();
}
CTTblBorders borders = tblPr.getTblBorders();
if (borders == null) {
borders = tblPr.addNewTblBorders();
}
setBorder(borders.addNewTop());
setBorder(borders.addNewBottom());
setBorder(borders.addNewLeft());
setBorder(borders.addNewRight());
setBorder(borders.addNewInsideH());
setBorder(borders.addNewInsideV());
}
private static void setBorder(CTBorder border) {
border.setVal(STBorder.SINGLE);
border.setSz(BigInteger.valueOf(4)); // 线宽
border.setColor("000000"); // 黑色
}
}