Проблема с обработкой текстового документа Java - PullRequest
1 голос
/ 01 июня 2019

Мне нужно заменить некоторые поля в файле Word Document на Java. Я использую библиотеку Apache Poi, я использую этот код для замены слов.

for (XWPFParagraph p : doc.getParagraphs()) {
                List<XWPFRun> runs = p.getRuns();
                if (runs != null) {
                    for (XWPFRun r : runs) {
                        String text = r.getText(0);
                        if (text != null)  {
                            System.out.println(text);
                            if (text.contains("[Title]")) {
                                text = text.replace("[Title]", wordBody.getTitle());//your content
                                r.setText(text, 0);
                            }if(text.contains("[Ref_no]")){
                                text=text.replace("[Ref_no]",wordBody.getRefNumber());
                                r.setText(text,0);
                            }
                            if(text.contains("[In_date]")){
                                text=text.replace("[In_date]",wordBody.getDate());
                                r.setText(text,0);
                            }if(text.contains("[FirstName]")){
                                text=text.replace("[FirstName]",wordBody.getFirstName());
                                r.setText(text,0);
                            }if(text.contains("[MiddleName]")){
                                text=text.replace("[MiddleName]",wordBody.getMiddleName());
                                r.setText(text,0);
                            }if(text.contains("[Vehicle_Type]")){
                                text=text.replace("[Vehicle_Type]",wordBody.getVehicleType());
                                r.setText(text,0);
                            }if(text.contains("[Reg_No]")){
                                text=text.replace("[Reg_No]",wordBody.getRegNumber());
                                r.setText(text,0);
                            }if(text.contains("[Location]")){
                                text=text.replace("[Location]",wordBody.getLocation());
                                r.setText(text,0);
                            }if(text.contains("[Issuer_Name]")){
                                text=text.replace("[Issuer_Name]",wordBody.getLocation());
                                r.setText(text,0);
                            }

                        }
                    }
                }
            }

Поэтому я упомянул, что не все слова замененыи я не знал, как это исправить, затем я распечатал весь текст, который я получил, и я получил что-то вроде этого

This is to certify that [Title] [FirstName] [
MiddleName
] [Surname] has purchased [
Vehicle_Type
] 
having registration [
Reg_No
] from our [Location] Showroom.
Issued By,
[
Issuer

Так что мне нужно заменить поля в [] скобках и некоторые из них как [Фамилия] напечатано хорошо, но некоторые из них, например [MIddleName], меняют строку, и я думаю, что это не работает.

Это - мое слово text

enter image description here

Я анализирую файл docx.Спасибо

1 Ответ

1 голос
/ 02 июня 2019

Если вы посмотрите на снимок экрана, вы увидите красную волнистую линию под MiddleName, Vehicle_Type и Reg_No.Это означает, что Word обнаружил здесь возможную орфографическую проблему.Это также сохраняется в файле, и поэтому тексты [MIddleName], [Vehicle_Type] и [Reg_No] не объединены в одном текстовом цикле с окружающими их скобками.Скобки имеют свои собственные текстовые прогоны, а также тексты вместе с отмеченной возможной проблемой правописания.

Это хорошо известная проблема, и некоторые библиотеки уже пытаются решить ее, обнаруживая текстовые переменные более сложным способом, чем толькопоиск их в текстовых прогонах.Например, templ4docx .

Но я предпочитаю другой путь.Word долгое время обеспечивает использование текстовых полей формы.См. Работа с полями формы .Обратите внимание, что подразумеваются устаревшие поля формы, а не поля ActiveX.

См. Замена текстовых шаблонов внутри .docx (Apache POI, Docx4j или др.) для примера.

Модифицированный пример для вашего случая:

WordTemplate.docx:

enter image description here

Все серые поля являются полями устаревшей текстовой формы, вставленными из вкладки разработчика.В именах Text Form Field Options Bookmark: указаны Text1, Text2, ... и тексты по умолчанию устанавливаются по необходимости.

Код:

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.apache.xmlbeans.SimpleValue;
import javax.xml.namespace.QName;

public class WordReplaceTextInFormFields {

 private static void replaceFormFieldText(XWPFDocument document, String ffname, String text) {
  boolean foundformfield = false;
  for (XWPFParagraph paragraph : document.getParagraphs()) {
   for (XWPFRun run : paragraph.getRuns()) {
    XmlCursor cursor = run.getCTR().newCursor();
    cursor.selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' .//w:fldChar/@w:fldCharType");
    while(cursor.hasNextSelection()) {
     cursor.toNextSelection();
     XmlObject obj = cursor.getObject();
     if ("begin".equals(((SimpleValue)obj).getStringValue())) {
      cursor.toParent();
      obj = cursor.getObject();
      obj = obj.selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' .//w:ffData/w:name/@w:val")[0];
      if (ffname.equals(((SimpleValue)obj).getStringValue())) {
       foundformfield = true;
      } else {
       foundformfield = false;
      }
     } else if ("end".equals(((SimpleValue)obj).getStringValue())) {
      if (foundformfield) return;
      foundformfield = false;
     }
    }
    if (foundformfield && run.getCTR().getTList().size() > 0) {
     run.getCTR().getTList().get(0).setStringValue(text);
//System.out.println(run.getCTR());
    }
   }
  }
 }

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

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

  replaceFormFieldText(document, "Text1", "Mrs.");
  replaceFormFieldText(document, "Text2", "Janis");
  replaceFormFieldText(document, "Text3", "Lyn");
  replaceFormFieldText(document, "Text4", "Joplin");
  replaceFormFieldText(document, "Text5", "Mercedes Benz");
  replaceFormFieldText(document, "Text6", "1234-56-789");
  replaceFormFieldText(document, "Text7", "Stuttgart");

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

Этот кодпротестировано с использованием apache poi 4.1.0 и нуждается в полной банке всех схем ooxml-schemas-1.4.jar, как указано в FAQ-N10025 .

Результат:

enter image description here

Обратите внимание, что серый фон текстовых полей виден только в GUI.Он не будет распечатан по умолчанию.

Преимущества:

Содержимое поля формы может быть отформатировано только как целое.Таким образом, содержимое поля формы никогда не разорвется.

Документ может быть защищен, поэтому возможно заполнение только полей формы.Тогда шаблон можно использовать как форму в Word GUI тоже.

...