我需要替换java.Word文档文件中的某些字段。我正在使用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


因此,我需要替换[]括号中的字段,其中一些字段作为[Surname]可以打印,但是其中一些字段为[MIddleName]正在更改行,并且我认为这样不起作用。

这是我的文字

java - 处理Word文档Java的问题-LMLPHP

我解析docx文件。
谢谢

最佳答案

如果您查看屏幕截图,将会在MiddleName,Vehicle_Type和Reg_No下看到红色的波浪线。这意味着Word在这里检测到可能的拼写问题。这也存储在文件中,这就是为什么文本[MIddleName],[Vehicle_Type]和[Reg_No]不在一起包含在方括号中的文本中的原因。括号在其自己的文本行中,并且还在文本中标记了可能的拼写问题。

这是一个众所周知的问题,有些库已经尝试通过比仅在文本运行中搜索它们更复杂的方式来检测文本变量来解决此问题。例如,有templ4docx

但是我的首选方式是另一种方式。 Word很长时间以来都提供使用文本表单字段的功能。请参见Working with Form Fields。请注意,旧表单字段是要提供的,而不是ActiveX字段。

有关示例,请参见Replace text templates inside .docx (Apache POI, Docx4j or other)

针对您的案例的修改示例:

WordTemplate.docx:

java - 处理Word文档Java的问题-LMLPHP

所有灰色字段都是从“开发人员”标签插入的旧文本表单字段。在其Text Form Field Options中,Bookmark:名称为Text1Text2,...,并根据需要设置默认文本。

码:

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进行了测试,并且需要FAQ-N10025中提到的所有架构ooxml-schemas-1.4.jar的完整jar。

结果:

java - 处理Word文档Java的问题-LMLPHP

请注意,文本字段的灰色背景仅在GUI中可见。默认情况下不会打印出来。

优点:

表单字段内容只能全部格式化。因此表单字段的内容永远不会撕裂。

可以保护文档,因此只能填写表格字段。然后,模板也可以在Word GUI中用作表单。

07-25 22:32
查看更多