使用場景:基於.docx模板進行內容寫入,內容替換
一、pom導入
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.0.0</version>
</dependency>
二、直接上代碼
word模板中${content} 注意只有在.docx用XWPFDocument才有效
2.1 內容替換
/**
* 獲取document
*
*/
XWPFDocument document = null;
try {
document = new XWPFDocument(inputStream);
} catch (IOException ioException) {
ioException.printStackTrace();
}
2.1.1
/**
* 替換段落里面的變量
*
* @param doc 要替換的文檔
* @param params 參數
*/
private void replaceInPara(XWPFDocument doc, Map<String, String> params) {
for (XWPFParagraph para : doc.getParagraphs()) {
replaceInPara(para, params);
}
}
2.1.2
/**
* 替換段落里面的變量
*
* @param para 要替換的段落
* @param params 參數
*/
private void replaceInPara(XWPFParagraph para, Map<String, String> params) {
List<XWPFRun> runs;
Matcher matcher;
replaceText(para);//如果para拆分的不對,則用這個方法修改成正確的
if (matcher(para.getParagraphText()).find()) {
runs = para.getRuns();
for (int i = 0; i < runs.size(); i++) {
XWPFRun run = runs.get(i);
String runText = run.toString();
matcher = matcher(runText);
if (matcher.find()) {
while ((matcher = matcher(runText)).find()) {
runText = matcher.replaceFirst(String.valueOf(params.get(matcher.group(1))));
}
//直接調用XWPFRun的setText()方法設置文本時,在底層會重新創建一個XWPFRun,把文本附加在當前文本后面,
para.removeRun(i);
para.insertNewRun(i).setText(runText);
}
}
}
}
2.1.3
/**
* 替換文本內容
* @param para
* @return
*/
private List<XWPFRun> replaceText(XWPFParagraph para) {
List<XWPFRun> runs = para.getRuns();
String str = "";
boolean flag = false;
for (int i = 0; i < runs.size(); i++) {
XWPFRun run = runs.get(i);
String runText = run.toString();
if (flag || runText.equals("${")) {
str = str + runText;
flag = true;
para.removeRun(i);
if (runText.equals("}")) {
flag = false;
para.insertNewRun(i).setText(str);
str = "";
}
i--;
}
}
return runs;
}
2.2 表格操作
2.2.1 將特定格式字體顏色寫入表格
XWPFTable table = document.getTableArray(0);//獲取當前表格
XWPFTableRow twoRow = table.getRow(2);//獲取某一行
XWPFTableRow nextRow = table.insertNewTableRow(3);//插入一行
XWPFTableCell firstRowCellOne = firstRow.getCell(0);
firstRowCellOne.removeParagraph(0);//刪除默認段落,要不然表格內第一條為空行
XWPFParagraph pIO2 =firstRowCellOne.addParagraph();
XWPFRun rIO2 = pIO2.createRun();
rIO2.setFontFamily("宋體");//字體
rIO2.setFontSize(8);//字體大小
rIO2.setBold(true);//是否加粗
rIO2.setColor("FF0000");//字體顏色
rIO2.setText("這是寫入的內容");//
rIO2.addBreak(BreakType.TEXT_WRAPPING);//軟換行,親測有效
2.2.2
/**
* 復制單元格和樣式
*
* @param targetRow 要復制的行
* @param sourceRow 被復制的行
*/
public void createCellsAndCopyStyles(XWPFTableRow targetRow, XWPFTableRow sourceRow) {
targetRow.getCtRow().setTrPr(sourceRow.getCtRow().getTrPr());
List<XWPFTableCell> tableCells = sourceRow.getTableCells();
if (CollectionUtils.isEmpty(tableCells)) {
return;
}
for (XWPFTableCell sourceCell : tableCells) {
XWPFTableCell newCell = targetRow.addNewTableCell();
newCell.getCTTc().setTcPr(sourceCell.getCTTc().getTcPr());
List sourceParagraphs = sourceCell.getParagraphs();
if (CollectionUtils.isEmpty(sourceParagraphs)) {
continue;
}
XWPFParagraph sourceParagraph = (XWPFParagraph) sourceParagraphs.get(0);
List targetParagraphs = newCell.getParagraphs();
if (CollectionUtils.isEmpty(targetParagraphs)) {
XWPFParagraph p = newCell.addParagraph();
p.getCTP().setPPr(sourceParagraph.getCTP().getPPr());
XWPFRun run = p.getRuns().isEmpty() ? p.createRun() : p.getRuns().get(0);
run.setFontFamily(sourceParagraph.getRuns().get(0).getFontFamily());
} else {
XWPFParagraph p = (XWPFParagraph) targetParagraphs.get(0);
p.getCTP().setPPr(sourceParagraph.getCTP().getPPr());
XWPFRun run = p.getRuns().isEmpty() ? p.createRun() : p.getRuns().get(0);
if (sourceParagraph.getRuns().size() > 0) {
run.setFontFamily(sourceParagraph.getRuns().get(0).getFontFamily());
}
}
}
}
#### 2.2.3
/**
* 合並單元格
*
* @param table 表格對象
* @param beginRowIndex 開始行索引
* @param endRowIndex 結束行索引
* @param colIndex 合並列索引
*/
public void mergeCell(XWPFTable table, int beginRowIndex, int endRowIndex, int colIndex) {
if (beginRowIndex == endRowIndex || beginRowIndex > endRowIndex) {
return;
}
//合並行單元格的第一個單元格
CTVMerge startMerge = CTVMerge.Factory.newInstance();
startMerge.setVal(STMerge.RESTART);
//合並行單元格的第一個單元格之后的單元格
CTVMerge endMerge = CTVMerge.Factory.newInstance();
endMerge.setVal(STMerge.CONTINUE);
table.getRow(beginRowIndex).getCell(colIndex).getCTTc().getTcPr().setVMerge(startMerge);
for (int i = beginRowIndex + 1; i <= endRowIndex; i++) {
table.getRow(i).getCell(colIndex).getCTTc().getTcPr().setVMerge(endMerge);
}
}
2.2.4
/**
* insertRow 在word表格中指定位置插入一行,並將某一行的樣式復制到新增行
* @param copyrowIndex 需要復制的行位置
* @param newrowIndex 需要新增一行的位置
* */
public static void insertRow(XWPFTable table, int copyrowIndex, int newrowIndex) {
// 在表格中指定的位置新增一行
XWPFTableRow targetRow = table.insertNewTableRow(newrowIndex);
// 獲取需要復制行對象
XWPFTableRow copyRow = table.getRow(copyrowIndex);
//復制行對象
targetRow.getCtRow().setTrPr(copyRow.getCtRow().getTrPr());
//或許需要復制的行的列
List<XWPFTableCell> copyCells = copyRow.getTableCells();
//復制列對象
XWPFTableCell targetCell = null;
for (int i = 0; i < copyCells.size(); i++) {
XWPFTableCell copyCell = copyCells.get(i);
targetCell = targetRow.addNewTableCell();
targetCell.getCTTc().setTcPr(copyCell.getCTTc().getTcPr());
if (copyCell.getParagraphs() != null && copyCell.getParagraphs().size() > 0) {
targetCell.getParagraphs().get(0).getCTP().setPPr(copyCell.getParagraphs().get(0).getCTP().getPPr());
if (copyCell.getParagraphs().get(0).getRuns() != null
&& copyCell.getParagraphs().get(0).getRuns().size() > 0) {
XWPFRun cellR = targetCell.getParagraphs().get(0).createRun();
cellR.setBold(copyCell.getParagraphs().get(0).getRuns().get(0).isBold());
}
}
}
}
/**
* 正則匹配字符串
*
* @param str
* @return
*/
private Matcher matcher(String str) {
Pattern pattern = Pattern.compile("\\$\\{(.+?)\\}", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(str);
return matcher;
}