Java使用poi獲取不到docx表格中書簽的問題及解決
問題
實(shí)際項(xiàng)目中遇到個(gè)需求,需要替換 docx 中書簽的內(nèi)容。
使用 poi 讀取 docx 的書簽,直接獲取文檔中的段落(paragraph)的書簽然后進(jìn)行替換內(nèi)容,處理完后發(fā)現(xiàn)文檔中表格里的書簽并沒有被替換
如何解決
文檔中每個(gè)單元格里的內(nèi)容也是段落(paragraph),將表格中的書簽做單獨(dú)處理,先獲取所有表格(table)所有單元格(cell),再獲取段落進(jìn)行書簽替換即可
代碼
替換書簽方法
public class WordUtil {
/**
* 處理表格中的書簽 每個(gè)單元格里的內(nèi)容都可以看作一個(gè)段落
*
* @param xwpfDocument 文檔對(duì)象
* @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);
}
/**
* 替換每個(gè)段落中的書簽
*
* @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) {
//找不到結(jié)束標(biāo)識(shí),在書簽前面加
ctp.getDomNode().insertBefore(xwpfRun.getCTR().getDomNode(), firstNode);
} else {
//找到結(jié)束符,將新內(nèi)容添加到結(jié)束符之前,即內(nèi)容寫入bookmark中間
ctp.getDomNode().insertBefore(xwpfRun.getCTR().getDomNode(), nextNode);
}
}
}
}
}
}測(cè)試
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);
}
}
}總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringMVC結(jié)合天氣api實(shí)現(xiàn)天氣查詢
這篇文章主要為大家詳細(xì)介紹了SpringMVC結(jié)合天氣api實(shí)現(xiàn)天氣查詢,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05
java基于servlet實(shí)現(xiàn)文件上傳功能解析
這篇文章主要為大家詳細(xì)介紹了java基于servlet實(shí)現(xiàn)上傳功能,后臺(tái)使用java實(shí)現(xiàn),前端主要是js的ajax實(shí)現(xiàn),感興趣的小伙伴們可以參考一下2016-05-05
Mybatis模糊查詢及自動(dòng)映射實(shí)現(xiàn)詳解
這篇文章主要介紹了Mybatis模糊查詢及自動(dòng)映射實(shí)現(xiàn)詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02

