zoukankan      html  css  js  c++  java
  • 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大量的操作。
  • 相关阅读:
    Sencha Touch 使用笔记
    区数据
    省市 数据
    js校验身份证
    js 邮政编码验证
    原生js添加class
    让IE6 IE7 IE8 IE9 IE10 IE11支持Bootstrap的解决方法
    js学习笔记 Function类型属性的理解
    js学习笔记 理解原型对象
    js学习笔记 chapter5 引用类型
  • 原文地址:https://www.cnblogs.com/xuebuhui/p/12036185.html
Copyright © 2011-2022 走看看