Как вставить абзац, заменив строку в текстовом документе - PullRequest
1 голос
/ 07 марта 2020

Я использую org. apache .poi poi-OO XML 3.17 в моем java проекте. Мое требование состоит в том, чтобы заменить текст из текстового документа некоторым текстом (например, подписью).

Каким-то образом мой код добавляет этот абзац внизу страницы вместе с заменой моего ключевого слова, вот мой блок код

public XWPFDocument addUserCompany(XWPFDocument doc, String imagePath,String userCompanyAddressInfo,String userCompanyContactInfo,String keyword) throws IOException, InvalidFormatException {
    int i=0;
    XWPFParagraph newPara = getNewPara(doc, imagePath, userCompanyAddressInfo, userCompanyContactInfo);
    for(XWPFParagraph existingPara:doc.getParagraphs()){
        for(XWPFRun existingRun:existingPara.getRuns()){
            if(existingRun!=null && existingRun.getText(0)!=null  && existingRun.getText(0).contains(keyword)){
                doc.setParagraph(newPara, i);
            }
        }
        i++;
    }
    return doc;
}
private XWPFParagraph getNewPara(XWPFDocument doc, String imagePath, String userCompanyAddressInfo, String userCompanyContactInfo) throws IOException, InvalidFormatException {
    XWPFParagraph newPara = doc.createParagraph();
    XWPFRun newRun = newPara.createRun();
    File imageFile1 = new File(imagePath);
    if (imageFile1.exists()) {
        int imgFormat1 = getImageFormat(imageFile1.getName());
        newRun.addPicture(new FileInputStream(imageFile1), imgFormat1, imageFile1.getName(), 491066, 491066);
        newRun.addBreak();
    }
    newRun.setText(userCompanyAddressInfo);
    newRun.addBreak();
    newRun.setText(userCompanyContactInfo);
    newRun.addBreak();
    return newPara;
}

word.addUserCompany(doc, userCompanyImage, userCompanyAddressInfo, userCompanyContactInfo, "${USERCONTACTINFO}");

вот мой оригинальный документ

enter image description here

и снимок экрана с результирующим документом enter image description here

В итоговом документе вы можете увидеть подпись, добавленную на нижней странице, а также вверху страницы

Может кто-нибудь помочь мне решить эту проблему

1 Ответ

3 голосов
/ 07 марта 2020

Основная проблема заключается в том, что 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();
 }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...