1. 程式人生 > >Java中常用到的文件操作那些事(一)——替換doc文檔模板,生成真實合同案例

Java中常用到的文件操作那些事(一)——替換doc文檔模板,生成真實合同案例

代碼 sta ring site hashmap i++ illegal puts except

  工作中,我們時常會遇到一些操作文件的操作,比如在線生成合同模板,上傳/下載/解析Excel,doc文檔轉為pdf等操作。本文就已工作中遇到的在線生成合同為例,簡要地介紹一種文檔替換寫法。

本文目的:給出源文件模板,通過程序操作後,替換模板中的指定內容,從而生成固定模板的文件。

使用場景:生成固定格式的合同信息。

原理:給一個文檔模板,需要替換的內容以 $$包含,然後,在代碼中給需要替換的字段賦值,生成新的文檔。

工具包:poi-ooxml-3.10.jar 自己網上下載

代碼:

 1 package word2pdf;
 2 
 3 import java.io.FileOutputStream;
4 import java.util.HashMap; 5 import java.util.Iterator; 6 import java.util.List; 7 import java.util.Map; 8 import java.util.Map.Entry; 9 import java.util.Set; 10 11 import org.apache.poi.POIXMLDocument; 12 import org.apache.poi.xwpf.usermodel.XWPFDocument; 13 import org.apache.poi.xwpf.usermodel.XWPFParagraph;
14 import org.apache.poi.xwpf.usermodel.XWPFRun; 15 import org.apache.poi.xwpf.usermodel.XWPFTable; 16 import org.apache.poi.xwpf.usermodel.XWPFTableCell; 17 import org.apache.poi.xwpf.usermodel.XWPFTableRow; 18 19 public class DocWriterTest { 20 21 public static void searchAndReplace(String srcPath, String destPath, Map<String, String> map) {
22 try { 23 XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(srcPath)); 24 /** 25 * 替換段落中的指定文字 26 */ 27 Iterator<XWPFParagraph> itPara = document.getParagraphsIterator(); 28 while (itPara.hasNext()) { 29 XWPFParagraph paragraph = (XWPFParagraph) itPara.next(); 30 Set<String> set = map.keySet(); 31 Iterator<String> iterator = set.iterator(); 32 while (iterator.hasNext()) { 33 String key = iterator.next().trim(); 34 List<XWPFRun> run = paragraph.getRuns(); 35 int runSize = run.size(); 36 for (int i = 0; i < runSize; i++) { 37 String text = run.get(i).getText(0); 38 System.out.println("++++++text++++++:" + text); 39 for (Entry<String, String> e : map.entrySet()) { 40 if (text != null && text.contains(e.getKey())) { 41 text = text.replace(e.getKey(), e.getValue()); 42 System.out.println("++++++text222222222++++++:" + text); 43 run.get(i).setText(text, 0); 44 } 45 } 46 } 47 } 48 } 49 50 /** 51 * 替換表格中的指定文字 52 */ 53 Iterator<XWPFTable> itTable = document.getTablesIterator(); 54 while (itTable.hasNext()) { 55 XWPFTable table = (XWPFTable) itTable.next(); 56 int count = table.getNumberOfRows(); 57 for (int i = 0; i < count; i++) { 58 XWPFTableRow row = table.getRow(i); 59 List<XWPFTableCell> cells = row.getTableCells(); 60 for (XWPFTableCell cell : cells) { 61 for (XWPFParagraph p : cell.getParagraphs()) { 62 for (XWPFRun r : p.getRuns()) { 63 String text = r.getText(0); 64 for (Entry<String, String> e : map.entrySet()) { 65 if (text != null && text.contains(e.getKey())) { 66 text = text.replace(e.getKey(), e.getValue()); 67 r.setText(text, 0); 68 } 69 } 70 } 71 } 72 73 } 74 } 75 } 76 FileOutputStream outStream = null; 77 outStream = new FileOutputStream(destPath); 78 document.write(outStream); 79 outStream.close(); 80 } catch (Exception e) { 81 e.printStackTrace(); 82 } 83 84 } 85 86 public static void main(String[] args) throws Exception { 87 Map<String, String> map = new HashMap<String, String>(); 88 map.put("$name$", "coco"); 89 map.put("$sex$", "女"); 90 map.put("work", "Java開發"); 91 String srcPath = "E:\\cocoxu\\test_mode\\sourcefile.docx"; 92 String destPath = "E:\\cocoxu\\test_mode\\destfile.docx"; 93 searchAndReplace(srcPath, destPath, map); 94 } 95 }

調試時遇到的報錯:

1.

java.lang.IllegalStateException: Zip File is closed
at org.apache.poi.openxml4j.util.ZipFileZipEntrySource.getEntries(ZipFileZipEntrySource.java:45)
at org.apache.poi.openxml4j.opc.ZipPackage.getPartsImpl(ZipPackage.java:182)
at org.apache.poi.openxml4j.opc.OPCPackage.getParts(OPCPackage.java:665)
at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:226)
at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:186)
at org.apache.poi.POIXMLDocument.openPackage(POIXMLDocument.java:67)
at word2pdf.DocWriterTest.searchAndReplace(DocWriterTest.java:23)
at word2pdf.DocWriterTest.main(DocWriterTest.java:93)

此類錯看似是zip文件被關閉,其實不然。其實是由於文檔路徑寫錯,找不到文件導致的。

String srcPath = "E:\\cocoxu\\\test_mode\\sourcefile.docx";

2、沒有生產想要的文件:

sourcefile.docx內容:技術分享圖片

目的是用代碼中的內容,替換文檔中的內容,但是我們第一次得到的確實這樣的:技術分享圖片

在代碼中打印日誌,可以看到,word文檔中的$name$被跨行分開了:技術分享圖片

本來是一行的東西,為什麽代碼執行操作的時候會被分成三行呢?這個就是doc文檔操作的問題啦 ,

方法一:操作源文檔,對文檔中所有拼寫語法不合規範的都忽略技術分享圖片

方法二:創建一個新文檔,在純英文格式下拼寫字段,然後復制帶源文件中,即可。

最終得到的目的問題內容:

技術分享圖片

至此,我們用java操作文檔的案例就結束了,實際工作中也可以模仿此類代碼去生成哦。

Java中常用到的文件操作那些事(一)——替換doc文檔模板,生成真實合同案例