Java使用poi獲取不到docx表格中書簽的問題及解決
更新時間:2024年06月17日 10:37:27 作者:編程經(jīng)驗分享
這篇文章主要介紹了Java使用poi獲取不到docx表格中書簽的問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
問題
實際項目中遇到個需求,需要替換 docx 中書簽的內(nèi)容。
使用 poi 讀取 docx 的書簽,直接獲取文檔中的段落(paragraph)的書簽然后進行替換內(nèi)容,處理完后發(fā)現(xiàn)文檔中表格里的書簽并沒有被替換
如何解決
文檔中每個單元格里的內(nèi)容也是段落(paragraph),將表格中的書簽做單獨處理,先獲取所有表格(table)所有單元格(cell),再獲取段落進行書簽替換即可
代碼
替換書簽方法
public class WordUtil {
/**
* 處理表格中的書簽 每個單元格里的內(nèi)容都可以看作一個段落
*
* @param xwpfDocument 文檔對象
* @param dataMap 書簽內(nèi)容
*/
public static void dealBookmarkOfDocx(XWPFDocument xwpfDocument, Map<String, String> dataMap) throws IOException {
//處理表格中的書簽
List<XWPFTable> tableList = xwpfDocument.getTables();
for (XWPFTable table : tableList) {
int rowCount = table.getNumberOfRows();//獲取table的行數(shù)
for (int i = 0; i < rowCount; i++) {
XWPFTableRow row = table.getRow(i);
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
dealParagraphBookmark(cell.getParagraphs(), dataMap);
}
}
}
//處理段落里的書簽
List<XWPFParagraph> paragraphs = xwpfDocument.getParagraphs();
dealParagraphBookmark(paragraphs, dataMap);
}
/**
* 替換每個段落中的書簽
*
* @param paragraphList 段落list
* @param dataMap 書簽內(nèi)容
*/
private static void dealParagraphBookmark(List<XWPFParagraph> paragraphList, Map<String, String> dataMap) {
for (XWPFParagraph paragraph : paragraphList) {
CTP ctp = paragraph.getCTP();
for (int i = 0; i < ctp.sizeOfBookmarkEndArray(); i++) {
CTBookmark bookmark = ctp.getBookmarkStartArray(i);
String bookmarkName = bookmark.getName();
if (dataMap.containsKey(bookmarkName)) {
XWPFRun xwpfRun = paragraph.createRun();
xwpfRun.setText(dataMap.get(bookmarkName));
Node firstNode = bookmark.getDomNode();
Node nextNode = firstNode.getNextSibling();
while (nextNode != null) {
String nodeName = nextNode.getNodeName();
if (nodeName.equalsIgnoreCase("w:bookmarkEnd")) {
break;
}
Node delNode = nextNode;
nextNode = nextNode.getNextSibling();
ctp.getDomNode().removeChild(delNode);
}
if (nextNode == null) {
//找不到結束標識,在書簽前面加
ctp.getDomNode().insertBefore(xwpfRun.getCTR().getDomNode(), firstNode);
} else {
//找到結束符,將新內(nèi)容添加到結束符之前,即內(nèi)容寫入bookmark中間
ctp.getDomNode().insertBefore(xwpfRun.getCTR().getDomNode(), nextNode);
}
}
}
}
}
}測試
class WordUtilTest {
@Test
void dealBookmarkOfDocx() {
String docxPath = "C:\\Users\\XXX\\Desktop\\myDoc.docx";
Map<String, String> dataMap = new HashMap<>();
dataMap.put("bookmark1", "1234567");
try (InputStream inputStream = Files.newInputStream(Paths.get(docxPath));
XWPFDocument xDoc = new XWPFDocument(inputStream)) {
WordUtil.dealBookmarkOfDocx(xDoc, dataMap);
xDoc.write(Files.newOutputStream(Paths.get(docxPath)));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

