首先准备maven依赖

 1 <dependency>
 2    <groupId>org.jxls</groupId>
 3    <artifactId>jxls</artifactId>
 4    <version>2.2.8</version>
 5 </dependency>
 6 <dependency>
 7    <groupId>org.jxls</groupId>
 8    <artifactId>jxls-poi</artifactId>
 9    <version>1.0.6</version>
10 </dependency>
11 <dependency>
12    <groupId>org.jxls</groupId>
13    <artifactId>jxls-jexcel</artifactId>
14    <version>1.0.6</version>
15 </dependency>
16 <dependency>
17    <groupId>org.jxls</groupId>
18    <artifactId>jxls-reader</artifactId>
19    <version>2.0.1</version>
20 </dependency>
View Code

然后制作模板,制作模板有一些注意事项,也是必须做到符合jxls语法命令的,否则无法动态生成

Excel模板样例

 

Excel模板标记在jxls中的作用分为三部分:

1、bean属性标记

2、XLS Area定义标记

3、XLS Command表示标记

  • bean属性标记

jxls使用 Apache JEXL表达式语言来解析定义在excel模板中的表达式。JEXL与JSTL相似,并对JSTL进行了扩展。eg:

${department.chief.age} //属性可以是无限深度

${utils:dateFmt(date,"yyyy-MM-dd")} //自定义工具函数
  • XLS Area定义标记

XLS Area 是JxlsPlus中的一个重要概念,它代表excel模板中需要被解析的矩形区域,由A1到最后一个单元格表示,有利于加快解析速度。

XLS Area 使用excel注释标注表示,它需要被定义在excel 模板的第一个单元格(A1):

jx:area(lastCell = "<AREA_LAST_CELL>")

这个标记定义了excel模板需要被解析的矩形区域为:A1到<AREA_LAST_CELL>。

  • XLS Command表示标记

XLS Command 使用excel注释标注表示,命令格式如下:

jx:<command_name>(attr1='val1' attr2='val2' ... attrN='valN' lastCell=<last_cell> areas=["<command_area1>", "<command_area2",
... "<command_areaN>"])

<command_name> 是库自带的命名或是用户自定义并注册到XlsCommentAreaBuilder的命令。

each 命令是最常用的XLS命令,形如:

jx:each(items="employees" var="employee" lastCell="D4")

each 可以有如下一些属性:

  • items 上下文中集合的变量名;
  • var 在遍历集合的时候每一条记录的变量名;
  • area 该XLS Command的解析区域;
  • direction 数据在excel中填充的方向,默认(DOWN)向下;
  • select 其值为一个表达式,用来过滤数据。

jexl自定义工具函数

如果你需要自定jexl来处理数据,你可以从Transformer对象获取JexlEngine引用,并对其配置。

下面的例子实现了将一个自定义jexl函数注册到utils命名空间下:

 1 JxlsHelper jxlsHelper = JxlsHelper.getInstance();
 2 
 3 Transformer transformer = jxlsHelper.createTransformer(is, os);
 4 
 5 JexlExpressionEvaluator evaluator = (JexlExpressionEvaluator)transformer.getTransformationConfig().getExpressionEvaluator();
 6 
 7 Map<String, Object> funcs = new HashMap<String, Object>();
 8 
 9 funcs.put("utils", new JxlsUtils()); //添加自定义功能
10 
11 evaluator.getJexlEngine().setFunctions(funcs);
View Code

接下来就是代码的实现 一个完成的工具类。

 1 package com.sgcc.mall.onestop.utils;
 2 import com.sgcc.mall.core.entitys.DejNgOrder;
 3 import java.io.File;
 4 import java.io.IOException;
 5 import java.util.ArrayList;
 6 import java.util.HashMap;
 7 import java.util.List;
 8 import java.util.Map;
 9 
10 public class ExportUtil {
11     //文件保存位置 TODO
12     private static String url = "D:\\tools";
13 
14     public static void outExportFile(List billInfo) throws IOException {
15 
16         Map<String,Object> map = new HashMap<String, Object>();
17         map.put("billInfo", billInfo);
18         //获取模板所在位置 TODO
19         String filePath = "D:\\template.xls";
20         //导出文件名称
21         String fileName = "demo";
22         File file = FreeMarkerFileUtil.getPdfFile(filePath,fileName,map);
23         FreeMarkerFileUtil.outFile(file,url);
24     }
25 
26     public static void main(String[] args) {
27         List<NgOrder> ngOrders = new ArrayList<NgOrder>();
28         NgOrder d = new NgOrder();
29         d.setBrand("海尔");
30         ngOrders.add(d);
31         try {
32             outExportFile(ngOrders);
33         } catch (IOException e) {
34             e.printStackTrace();
35         }
36     }
37 }
View Code
  1 package com.sgcc.mall.onestop.utils;
  2 
  3 import com.aspose.cells.License;
  4 import com.aspose.cells.SaveFormat;
  5 import com.aspose.cells.Workbook;
  6 import org.apache.log4j.Logger;
  7 import org.jxls.common.Context;
  8 import org.jxls.util.JxlsHelper;
  9 
 10 import javax.servlet.ServletOutputStream;
 11 import javax.servlet.http.HttpServletResponse;
 12 import java.io.*;
 13 import java.net.URLEncoder;
 14 import java.util.Map;
 15 
 16 
 17 public final class FreeMarkerFileUtil {
 18     private static Logger log = Logger.getLogger(FreeMarkerFileUtil.class);
 19 
 20     public static final String UTF8 = "utf-8";
 21     /**
 22      * 生成execl文件后缀名
 23      */
 24     public static final String XLS_SUFFIX = ".xls";
 25     /**
 26      * 生成pdf文件后缀名
 27      */
 28     public static final String PDF_SUFFIX = ".pdf";
 29     /**
 30      * 向浏览器输出execl文件类型,用于指定响应头信息
 31      */
 32     public static final int XLS_OUT_TYPE = 1;
 33     /**
 34      * 向浏览器输出execl文件响应头信息
 35      */
 36     public static final String XLS_CONTENT_TYPE = "application/vnd.ms-excel;charset=" + UTF8;
 37     /**
 38      * 向浏览器输出pdf文件类型,用于指定响应头信息
 39      */
 40     public static final int PDF_OUT_TYPE = 2;
 41     /**
 42      * 向浏览器输出pdf文件响应头信息
 43      */
 44     public static final String PDF_CONTENT_TYPE = "application/pdf;charset=" + UTF8;
 45 
 46 
 47     /**
 48      * 根据指定模板生成execl文件
 49      *
 50      * @param tmpFilePath 模板文件
 51      * @param fileName    文件名称
 52      * @param beans       模板填充数据集
 53      * @return
 54      */
 55     public static File getXlsFile(String tmpFilePath, String fileName, Map beans) throws IOException {
 56         File xlsFile = File.createTempFile(fileName, XLS_SUFFIX);
 57         Context context = new Context();
 58         context.putVar("beans", beans);
 59         log.info("进入数据填充");
 60         JxlsHelper.getInstance().processTemplate(new FileInputStream(tmpFilePath), new FileOutputStream(xlsFile), context);
 61         log.info("数据填充完成");
 62         return xlsFile;
 63     }
 64 
 65     /**
 66      * 根据指定模板生成execl的PDF格式文件
 67      *
 68      * @param tmpFilePath 模板文件
 69      * @param fileName    文件名称
 70      * @param beans       模板填充数据集
 71      * @return
 72      */
 73     public static File getPdfFile(String tmpFilePath, String fileName, Map beans) throws IOException {
 74         // 根据模板获取execl文件
 75         File xlsFile = getXlsFile(tmpFilePath, fileName, beans);
 76         File pdfFile = execl2Pdf(xlsFile, fileName);
 77         return pdfFile;
 78     }
 79 
 80     /**
 81      * execl文件转换为pdf文件
 82      *
 83      * @param xlsFile     execl文件
 84      * @param pdfFileName 生成的pdf文件名称
 85      * @return
 86      */
 87     public static File execl2Pdf(File xlsFile, String pdfFileName) {
 88         // 验证License
 89         if (!getLicense()) {
 90             throw new RuntimeException("验证License失败!");
 91         }
 92         try {
 93             InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(xlsFile), "UTF-8");
 94             Workbook wb = new Workbook(new FileInputStream(xlsFile));
 95             File pdfFile = File.createTempFile(pdfFileName, PDF_SUFFIX);
 96             // 输出路径
 97             FileOutputStream fileOS = new FileOutputStream(pdfFile);
 98             wb.save(fileOS, SaveFormat.PDF);
 99             return pdfFile;
100         } catch (Exception e) {
101             e.printStackTrace();
102         }
103         return null;
104     }
105 
106     /**
107      * 输出文件到浏览器
108      *
109      * @param file     需要输出的文件
110      * @param fileName 输出的文件名
111      * @param response
112      * @param type     输出的文件类型
113      * @throws IOException
114      */
115     public static void outFile(File file, String fileName, HttpServletResponse response, int type) throws IOException {
116         try {
117             fileName = URLEncoder.encode(fileName, UTF8);
118         } catch (UnsupportedEncodingException e) {
119             e.printStackTrace();
120             throw new RuntimeException("不支持的编码格式:" + UTF8);
121         }
122 
123         response.reset();
124         //设置响应文本格式
125         if (type == XLS_OUT_TYPE) {
126             response.setContentType(XLS_CONTENT_TYPE);
127         } else if (type == PDF_OUT_TYPE) {
128             response.setContentType(PDF_CONTENT_TYPE);
129         } else {
130             throw new RuntimeException("类型错误");
131         }
132         response.setHeader("Content-Disposition", "attachment;filename=" + new String((fileName).getBytes(), "iso-8859-1"));
133         InputStream bis = null;
134         OutputStream bos = null;
135         try {
136             //将文件输出到页面
137             ServletOutputStream out = response.getOutputStream();
138             bis = new BufferedInputStream(new FileInputStream(file));
139             bos = new BufferedOutputStream(out);
140             byte[] buff = new byte[1024];
141             int bytesRead;
142             // 根据读取并写入
143             while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
144                 bos.write(buff, 0, bytesRead);
145             }
146         } finally {
147             if (bis != null) {
148                 bis.close();
149             }
150             if (bos != null) {
151                 bos.close();
152             }
153         }
154 
155     }
156 
157     /**
158      * 输出文件到本地磁盘
159      *
160      * @param file
161      * @param outDir
162      * @throws IOException
163      */
164     public static void outFile(File file, String outDir) throws IOException {
165         InputStream bis = null;
166         OutputStream bos = null;
167         try {
168             bis = new BufferedInputStream(new FileInputStream(file));
169             bos = new BufferedOutputStream(new FileOutputStream(outDir + file.getName()));
170             byte[] buff = new byte[2048];
171             int bytesRead;
172             // 根据读取并写入
173             while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
174                 bos.write(buff, 0, bytesRead);
175             }
176         } finally {
177             if (null != bis) {
178                 bis.close();
179             }
180             if (null != bos) {
181                 bos.close();
182             }
183         }
184     }
185     /**
186      * 验证license
187      *
188      * @return
189      */
190     public static boolean getLicense() {
191         boolean result = false;
192         try {
193             InputStream is = FreeMarkerFileUtil.class.getClassLoader().getResourceAsStream("\\license.xml");
194             License aposeLic = new License();
195             aposeLic.setLicense(is);
196             result = true;
197         } catch (Exception e) {
198             e.printStackTrace();
199         }
200         return result;
201     }
202 }
View Code

一个根据模板导出Excel的功能就结束了,更多复杂的功能之后继续完善,希望大家多多提意见,共同进步。

 posted on 2019-10-24 20:16  麋途知鹿  阅读(2099)  评论(0编辑  收藏  举报