Основная проблема заключается в том, что XWPFDocument.createParagraph всегда добавляет новый абзац к этому документу. Поэтому после установки этого абзаца в качестве замены абзаца для замены с помощью XWPFDocument.setParagraph нам нужно удалить ранее созданный новый абзац из документа. Для этого может использоваться XWPFDocument.removeBodyElement- .
Кстати: вам не нужен int i
в качестве маркера положения. Существует XWPFDocument.getPosOfParagraph .
Поскольку нам нужно удалить абзац из документа, это нельзя сделать в l oop над абзацами. Поэтому нам нужно сначала определить paragraphToReplace
в l oop, а затем заменить этот абзац на новый созданный абзац, а затем удалить новый созданный абзац из документа.
Так что addUserCompany
должно выглядеть так: :
public XWPFDocument addUserCompany(XWPFDocument doc, String imagePath,String userCompanyAddressInfo,String
userCompanyContactInfo,String keyword) throws Exception {
XWPFParagraph paragraphToReplace = null;
for(XWPFParagraph existingPara : doc.getParagraphs()) {
if(existingPara.getText().contains(keyword)) {
paragraphToReplace = existingPara;
}
}
if (paragraphToReplace != null) {
XWPFParagraph newPara = getNewPara(doc, imagePath, userCompanyAddressInfo, userCompanyContactInfo);
doc.setParagraph(newPara, doc.getPosOfParagraph(paragraphToReplace));
doc.removeBodyElement(doc.getPosOfParagraph(newPara));
}
return doc;
}
Обратите внимание, что я не пытаюсь получить заполнитель из текстовых прогонов. Word
иногда использует странные правила для создания текстовых прогонов. Таким образом, в нашем примере $
и {
и USERCONTACTINFO
и }
могут быть каждый в своем собственном текстовом прогоне. Тогда existingRun.getText(0).contains(keyword)
никогда не будет правдой. Однако, поскольку мы все равно заменяем весь абзац, мы также можем проверить, содержит ли абзац ключевое слово, используя existingPara.getText().contains(keyword)
. Это верно, даже если части keyword
находятся в отдельных текстовых прогонах.
Полный пример:
import java.io.*;
import org.apache.poi.xwpf.usermodel.*;
public class WordReplaceParagraphContainingKeyword {
static XWPFDocument addUserCompany(XWPFDocument doc, String imagePath,String userCompanyAddressInfo,String
userCompanyContactInfo,String keyword) throws Exception {
XWPFParagraph paragraphToReplace = null;
for(XWPFParagraph existingPara : doc.getParagraphs()) {
if(existingPara.getText().contains(keyword)) {
paragraphToReplace = existingPara;
}
}
if (paragraphToReplace != null) {
XWPFParagraph newPara = getNewPara(doc, imagePath, userCompanyAddressInfo, userCompanyContactInfo);
doc.setParagraph(newPara, doc.getPosOfParagraph(paragraphToReplace));
doc.removeBodyElement(doc.getPosOfParagraph(newPara));
}
return doc;
}
static XWPFParagraph getNewPara(XWPFDocument doc, String imagePath, String userCompanyAddressInfo, String
userCompanyContactInfo) throws Exception {
XWPFParagraph newPara = doc.createParagraph();
XWPFRun newRun = newPara.createRun();
File imageFile1 = new File(imagePath);
if (imageFile1.exists()) {
//int imgFormat1 = getImageFormat(imageFile1.getName());
int imgFormat1 = Document.PICTURE_TYPE_PNG;
newRun.addPicture(new FileInputStream(imageFile1), imgFormat1, imageFile1.getName(), 491066, 491066);
newRun.addBreak();
}
newRun.setText(userCompanyAddressInfo);
newRun.addBreak();
newRun.setText(userCompanyContactInfo);
newRun.addBreak();
return newPara;
}
public static void main(String[] args) throws Exception {
XWPFDocument doc = new XWPFDocument(new FileInputStream("source.docx"));
String userCompanyImage = "logo.png";
String userCompanyAddressInfo = "111 E.Jefferson Avenue Naperville, Illinois 60540";
String userCompanyContactInfo = "Phone: 312-100-7387";
addUserCompany(doc, userCompanyImage, userCompanyAddressInfo, userCompanyContactInfo, "${USERCONTACTINFO}");
FileOutputStream out = new FileOutputStream("result.docx");
doc.write(out);
out.close();
doc.close();
}
}