簡體   English   中英

使用Apache POI替換docx文本框中的文本

[英]Replace text in text box of docx by using Apache POI

我正在使用 Apache POI 來替換 docx 的單詞。 對於普通的段落,我成功地使用了 XWPFParagraph 和 XWPFRun 來替換單詞。 然后我嘗試替換文本框中的單詞。 我參考了這個https://stackoverflow.com/a/25877256來獲取文本框中的文本。 我成功地在控制台中打印了文本。 但是,我未能替換文本框中的單詞。 這是我的一些代碼:

    for (XWPFParagraph paragraph : doc.getParagraphs()) {
        XmlObject[] textBoxObjects =  paragraph.getCTP().selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' declare namespace wps='http://schemas.microsoft.com/office/word/2010/wordprocessingShape' .//*/wps:txbx/w:txbxContent");
            for (int i =0; i < textBoxObjects.length; i++) {
                XWPFParagraph embeddedPara = null;
                try {
                XmlObject[] paraObjects = textBoxObjects[i].
                    selectChildren(
                    new QName("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "p"));

                for (int j=0; j<paraObjects.length; j++) {
                    embeddedPara = new XWPFParagraph(CTP.Factory.parse(paraObjects[j].xmlText()), paragraph.getBody());
                    List<XWPFRun> runs = embeddedPara.getRuns();
                    for (XWPFRun r : runs) {
                        String text = r.getText(0);
                        if (text != null && text.contains(someWords)) {
                            text = text.replace(someWords, "replaced");
                            r.setText(text, 0);
                        }
                    }
                } 
                } catch (XmlException e) {
                //handle
                }
            }
    }

我認為問題在於我創建了一個新的 XWPFParagraph embeddingPara 並且它替換了 embeddingPara 的單詞而不是原始段落。 所以在我寫入文件后,單詞仍然沒有改變。

如何在不創建新的 XWPFParagraph 的情況下讀取和替換文本框中的單詞?

出現此問題是因為Word文本框可能包含在依賴於Word版本的多個不同XmlObjects中。 這些XmlObjects也可能位於非常不同的名稱空間中。 因此selectChildren不能遵循名稱空間路由,因此它將返回XmlAnyTypeImpl

所有文本框實現的共同點是它們的運行都在路徑.//*/w:txbxContent/w:p/w:r 所以我們可以使用一個XmlCursor來選擇該路徑。 然后我們在List<XmlObject>收集所有選定的XmlObjects 然后我們從這些對象中解析CTR s,這些對象當然只是文檔上下文之外的CTR s。 但是我們可以從這些創建XWPFRuns ,在那里進行替換,然后set這些XWPFRuns的 XML 內容set回對象。 在此之后,我們有包含替換內容的對象。

示例:

在此處輸入圖片說明

import java.io.FileOutputStream;
import java.io.FileInputStream;

import org.apache.poi.xwpf.usermodel.*;

import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlCursor;

import  org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;

import java.util.List;
import java.util.ArrayList;

public class WordReplaceTextInTextBox {

 public static void main(String[] args) throws Exception {

  XWPFDocument document = new XWPFDocument(new FileInputStream("WordReplaceTextInTextBox.docx"));

  String someWords = "TextBox";

  for (XWPFParagraph paragraph : document.getParagraphs()) {
   XmlCursor cursor = paragraph.getCTP().newCursor();
   cursor.selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' .//*/w:txbxContent/w:p/w:r");

   List<XmlObject> ctrsintxtbx = new ArrayList<XmlObject>();

   while(cursor.hasNextSelection()) {
    cursor.toNextSelection();
    XmlObject obj = cursor.getObject();
    ctrsintxtbx.add(obj);
   }
   for (XmlObject obj : ctrsintxtbx) {
    CTR ctr = CTR.Factory.parse(obj.xmlText());
    //CTR ctr = CTR.Factory.parse(obj.newInputStream());
    XWPFRun bufferrun = new XWPFRun(ctr, (IRunBody)paragraph);
    String text = bufferrun.getText(0);
    if (text != null && text.contains(someWords)) {
     text = text.replace(someWords, "replaced");
     bufferrun.setText(text, 0);
    }
    obj.set(bufferrun.getCTR());
   }
  }

  FileOutputStream out = new FileOutputStream("WordReplaceTextInTextBoxNew.docx");
  document.write(out);
  out.close();
  document.close();
 }
}

在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM