Java使用poi獲取不到docx表格中書簽的問題及解決
更新時間:2024年06月17日 10:37:27 作者:編程經(jīng)驗分享
這篇文章主要介紹了Java使用poi獲取不到docx表格中書簽的問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
問題
實際項目中遇到個需求,需要替換 docx 中書簽的內(nèi)容。
使用 poi 讀取 docx 的書簽,直接獲取文檔中的段落(paragraph)的書簽然后進(jìn)行替換內(nèi)容,處理完后發(fā)現(xiàn)文檔中表格里的書簽并沒有被替換
如何解決
文檔中每個單元格里的內(nèi)容也是段落(paragraph),將表格中的書簽做單獨處理,先獲取所有表格(table)所有單元格(cell),再獲取段落進(jìn)行書簽替換即可
代碼
替換書簽方法
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) { //找不到結(jié)束標(biāo)識,在書簽前面加 ctp.getDomNode().insertBefore(xwpfRun.getCTR().getDomNode(), firstNode); } else { //找到結(jié)束符,將新內(nèi)容添加到結(jié)束符之前,即內(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); } } }
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringMVC結(jié)合天氣api實現(xiàn)天氣查詢
這篇文章主要為大家詳細(xì)介紹了SpringMVC結(jié)合天氣api實現(xiàn)天氣查詢,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-05-05