首先准備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>
然后制作模板,制作模板有一些注意事項,也是必須做到符合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);
接下來就是代碼的實現 一個完成的工具類。

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 }

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 }
一個根據模板導出Excel的功能就結束了,更多復雜的功能之后繼續完善,希望大家多多提意見,共同進步。