java導出word格式的文件


 

  1. 使用POI技術生成word格式的月報,實現功能根據日期進行預覽,導出。
  2. 使用template.docx作為word模板,參數使用特殊符號標識,封裝數據(Map<String,String>); 通過IO讀取模板替換參數,從而動態獲取數據。
  3. 預覽的實現,由於web頁面展示通過html或pdf來進行。將word轉為pdf后基本都會出現樣式的不兼容問題,所以放棄。 最終我根據word的模板又手寫了一個html對應的模板,參數使用的jsp的el表達式動態替換參數,從而動態獲取數據。暫時沒有考慮word模板過多的情況。
  4. 由於我做的系統的前端是easyui的框架,預覽時的翻頁使用了panel插件功能,批量導出使用的ZipEntry。

 

相關代碼

  

  1 package com.bocsh.base.util;
  2 
  3 import java.io.ByteArrayOutputStream;
  4 import java.io.FileInputStream;
  5 import java.io.IOException;
  6 import java.util.List;
  7 import java.util.Map;
  8 import java.util.Map.Entry;
  9 import java.util.Set;
 10 
 11 
 12 //import org.apache.poi.POIXMLDocument;
 13 import org.apache.poi.xwpf.usermodel.*;
 14 
 15 /**
 16  * 通過word模板生成新的word工具類
 17  *
 18  * @author zhiheng
 19  *
 20  *
 21  * XWPFDocument代表一個docx文檔,其可以用來讀docx文檔,也可以用來寫docx文檔
 22  * XWPFParagraph代表文檔、表格、標題等種的段落,由多個XWPFRun組成
 23  * XWPFRun代表具有同樣風格的一段文本
 24  * XWPFTable代表一個表格
 25  * XWPFTableRow代表表格的一行
 26  * XWPFTableCell代表表格的一個單元格
 27  * XWPFChar 表示.docx文件中的圖表
 28  * XWPFHyperlink 表示超鏈接
 29  * XWPFPicture 代表圖片
 30  *
 31  *
 32  *
 33  */
 34 public class WorderToNewWordUtils {
 35 
 36     /**
 37      * 判斷表格是需要替換還是需要插入,判斷邏輯有$為替換,表格無$為插入
 38      * @param inputUrl 模板存放地址
 39      * @param textMap 需要替換的信息集合
 40      * @param excelDataBytes 生成了新的數據流  word格式, 存放容器
 41      * @return 成功返回true,失敗返回false
 42      */
 43     public static boolean changWord(String inputUrl,
 44                                     Map<String, String> textMap, Map<String,byte[]> excelDataBytes) {
 45 
 46         //模板轉換默認成功
 47         boolean changeFlag = true;
 48         ByteArrayOutputStream writeToBytes = null;
 49         try {
 50             //獲取docx解析對象
 51             XWPFDocument document = new XWPFDocument(new FileInputStream(inputUrl));
 52             //解析替換文本段落對象
 53             WorderToNewWordUtils.changeText(document, textMap);
 54             //解析替換表格對象
 55             WorderToNewWordUtils.changeTable(document, textMap);
 56 
 57             //生成了新的數據流  word 格式
 58             writeToBytes = new ByteArrayOutputStream();
 59             document.write(writeToBytes);
 60             excelDataBytes.put(textMap.get("year") + textMap.get("month"), writeToBytes.toByteArray());
 61 
 62         } catch (IOException e) {
 63             e.printStackTrace();
 64             changeFlag = false;
 65         }finally{
 66             try {
 67                 if(writeToBytes!=null)
 68                 writeToBytes.close();
 69             } catch (IOException e) {
 70                 e.printStackTrace();
 71             }
 72         }
 73 
 74         return changeFlag;
 75 
 76     }
 77 
 78 
 79     /**
 80      * 替換段落文本
 81      * @param document docx解析對象
 82      * @param textMap 需要替換的信息集合
 83      */
 84     public static void changeText(XWPFDocument document, Map<String, String> textMap){
 85         //獲取段落集合
 86         List<XWPFParagraph> paragraphs = document.getParagraphs();
 87 
 88         for (XWPFParagraph paragraph : paragraphs) {
 89             //判斷此段落時候需要進行替換
 90             String text = paragraph.getText();
 91             if(checkText(text)){
 92                 List<XWPFRun> runs = paragraph.getRuns();
 93                 for (XWPFRun run : runs) {
 94                     //替換模板原來位置
 95                     run.setText(changeValue(run.toString(), textMap),0);
 96                 }
 97             }
 98         }
 99 
100     }
101 
102     /**
103      * 替換表格對象方法
104      * @param document docx解析對象
105      * @param textMap 需要替換的信息集合
106      */
107     private static void changeTable(XWPFDocument document, Map<String, String> textMap){
108         //獲取表格對象集合
109         List<XWPFTable> tables = document.getTables();
110         for (int i = 0; i < tables.size(); i++) {
111             //只處理行數大於等於2的表格,且不循環表頭
112             XWPFTable table = tables.get(i);
113             if(table.getRows().size()>1){
114                 //判斷表格是需要替換還是需要插入,判斷邏輯有$為替換,表格無$為插入
115                 if(checkText(table.getText())){
116                     List<XWPFTableRow> rows = table.getRows();
117                     //遍歷表格,並替換模板
118                     eachTable(rows, textMap);
119                 }
120             }
121         }
122 
123 
124     }
125 
126 
127     /**
128      * 遍歷表格
129      * @param rows 表格行對象
130      * @param textMap 需要替換的信息集合
131      */
132     private static void eachTable(List<XWPFTableRow> rows ,Map<String, String> textMap){
133         for (XWPFTableRow row : rows) {
134             List<XWPFTableCell> cells = row.getTableCells();
135             for (XWPFTableCell cell : cells) {
136                 //判斷單元格是否需要替換
137                 if(checkText(cell.getText())){
138                     List<XWPFParagraph> paragraphs = cell.getParagraphs();
139                     for (XWPFParagraph paragraph : paragraphs) {
140                         List<XWPFRun> runs = paragraph.getRuns();
141                         for (XWPFRun run : runs) {
142                             run.setText(changeValue(run.toString(), textMap),0);
143                         }
144                     }
145                 }
146             }
147         }
148     }
149 
150 
151     /**
152      * 判斷文本中時候包含$
153      * @param text 文本
154      * @return 包含返回true,不包含返回false
155      */
156     private static boolean checkText(String text){
157         boolean check  =  false;
158         if(text.indexOf("$")!= -1){
159             check = true;
160         }
161         return check;
162 
163     }
164 
165     /**
166      * 匹配傳入信息集合與模板
167      * @param value 模板需要替換的區域
168      * @param textMap 傳入信息集合
169      * @return 模板需要替換區域信息集合對應值
170      */
171     private static String changeValue(String value, Map<String, String> textMap){
172         Set<Entry<String, String>> textSets = textMap.entrySet();
173         for (Entry<String, String> textSet : textSets) {
174             //匹配模板與替換值 格式${key}
175             String key = "${"+textSet.getKey()+"}";
176             if(value.indexOf(key)!= -1){
177                 value = textSet.getValue();
178             }
179         }
180         //模板未匹配到區域替換為空
181         if(checkText(value)){
182             value = "0";
183         }
184         return value;
185     }
186 
187 
188 }

注意:

  1. html模板和word模板共用的數據模型
  2. 寫這個功能前翻閱了大量的關於java導出word的博客,有大量的將word轉為ftl格式再去操作,感覺不是很方便和直觀。
  3. 上面的代碼參考了 https://www.cnblogs.com/sun-flower1314/p/10128796.html,這里有使用POI對word大量的操作。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM