簡體   English   中英

處理word文檔java的問題

[英]Problem with processing word document java

我需要替換 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] 正在更改行,我認為這不起作用。

這是我的文字

在此處輸入圖像描述

我解析 docx 文件。 謝謝

如果您查看屏幕截圖,您將在 MiddleName、Vehicle_Type 和 Reg_No 下看到紅色波浪線。 這意味着, Word已在此處檢測到可能的拼寫問題。 這也存儲在文件中,這就是為什么文本 [MIddleName]、[Vehicle_Type] 和 [Reg_No] 不在一個文本中與它們的括號一起運行的原因。 括號在它們自己的文本運行中,並且文本與可能的拼寫問題一起標記。

這是一個眾所周知的問題,一些庫已經嘗試通過檢測文本變量來解決這個問題,這種方法比僅在文本運行中搜索它們更復雜。 例如有templ4docx

但我首選的方式是另一種方式。 Word長期以來提供使用文本的表單域。 請參閱使用表單域 請注意,舊表單字段是指舊表單字段,而不是 ActiveX 字段。

有關示例,請參閱替換 .docx(Apache POI、Docx4j 或其他)中的文本模板

針對您的案例的修改示例:

WordTemplate.docx:

在此處輸入圖像描述

所有灰色字段都是從開發人員選項卡插入的舊文本表單字段。 在他們的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);
     foundformfield = false;
//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。

結果:

在此處輸入圖像描述

請注意,文本字段的灰色背景僅在GUI中可見。 默認情況下不會打印出來。

優點:

表單域內容只能整體格式化。 所以表單域內容永遠不會被撕裂。

可以保護文檔,因此只能填寫表單字段。 然后該模板也可用作Word GUI中的表單。

我喜歡上面接受的答案,但如果您正在尋找一個超級快速的修復程序來防止將文本拆分為多個運行,以便 java 程序可以識別/讀取它,請執行以下操作:

  1. 在一次運行中復制您想要的文本
  2. 將其粘貼到記事本中(刪除所有 docx 格式)
  3. 將該文本復制並粘貼到word文檔中,點擊保存。

現在它將作為一次運行插入。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM