问题描述
我正在使用 Apache POI 来替换 docx 的单词.对于普通的段落,我成功地使用了 XWPFParagraph 和 XWPFRun 来替换单词.然后我尝试替换文本框中的单词.我参考了这个
import java.io.FileOutputStream;导入 java.io.FileInputStream;导入 org.apache.poi.xwpf.usermodel.*;导入 org.apache.xmlbeans.XmlObject;导入 org.apache.xmlbeans.XmlCursor;导入 org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;导入 java.util.List;导入 java.util.ArrayList;公共类 WordReplaceTextInTextBox {public static void main(String[] args) 抛出异常 {XWPFDocument 文档 = new XWPFDocument(new FileInputStream("WordReplaceTextInTextBox.docx"));String someWords = "TextBox";for (XWPFParagraph 段落: document.getParagraphs()) {XmlCursor 游标 = 段落.getCTP().newCursor();cursor.selectPath("声明命名空间 w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' .///*/w:txbxContent/w:p/w:r");列表ctrsintxtbx = new ArrayList();while(cursor.hasNextSelection()) {cursor.toNextSelection();XmlObject obj = cursor.getObject();ctrsintxtbx.add(obj);}对于(XmlObject 对象: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);关闭();文档.close();}}
I am using Apache POI to replace words of docx. For a normal paragraph, I success to use XWPFParagraph and XWPFRun to replace the words. Then I tried to replace words in text box. I referenced this https://stackoverflow.com/a/25877256 to get text in text box. I success to print the text in console. However, I failed to replace words in text box.Here are some of my codes:
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
}
}
}
I think the problem is that I created a new XWPFParagraph embeddedPara and it's replacing the words of embeddedPara but not the origin paragraph. So after I write in a file, the words still not change.
How can I read and replace the words in the text box without creating a new XWPFParagraph?
The problem occurs because the Word
text boxes may be contained in multiple different XmlObjects
dependent of the Word
version. Those XmlObjects
may also be in very different name spaces. So the selectChildren
cannot following the name space route and so it will return a XmlAnyTypeImpl
.
What all text box implementatrion have in common is that their runs are in the path .//*/w:txbxContent/w:p/w:r
. So we can using a XmlCursor
which selects that path. Then we collect all selected XmlObjects
in a List<XmlObject>
. Then we parse CTR
s from those objects, which are of course only CTR
s outside the document context. But we can creating XWPFRuns
from those, do the replacing there and then set
the XML content of those XWPFRuns
back to the objects. After this we have the objects containing the replaced content.
Example:
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();
}
}
这篇关于使用Apache POI替换docx文本框中的文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!