SpringBoot+Poi-tl根据Word模板动态生成word(含动态行表格)
Poi-tl官方文档:http://deepoove.com/poi-tl/
一、实现过程
1.添加必要依赖
<!-- word导出 --> <dependency> <groupId>com.deepoove</groupId> <artifactId>poi-tl</artifactId> <version>1.7.3</version> </dependency> <!-- 上面需要的依赖--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.2</version> </dependency> <!-- 对JSP的支持 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency>
2.新建一个word,编写word模板:
把该模板放到项目中的static/template/文件夹下:
3.编写一个controller 类,导出销售订单信息的接口类,供页面请求
package com.example.word.controller; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.util.ClassUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.ModelAndView; import com.deepoove.poi.XWPFTemplate; import com.deepoove.poi.config.Configure; import com.deepoove.poi.data.PictureRenderData; import com.deepoove.poi.policy.HackLoopTableRenderPolicy; import com.example.word.common.MoneyUtils; /** * 导出Word * @author Administrator * */ @RequestMapping("/auth/exportWord/") @RestController public class ExportWordController { /** * 销售订单信息导出word --- poi-tl(包含动态表格) * @throws IOException */ @RequestMapping("/exportDataWord3") public void exportDataWord3(HttpServletRequest request,HttpServletResponse response) throws IOException{ try { Map<String, Object> params = new HashMap<>(); // TODO 渲染其他类型的数据请参考官方文档 DecimalFormat df = new DecimalFormat("######0.00"); Calendar now = Calendar.getInstance(); double money = 0;//总金额 //组装表格列表数据 List<Map<String,Object>> detailList=new ArrayList<Map<String,Object>>(); for (int i = 0; i < 6; i++) { Map<String,Object> detailMap = new HashMap<String, Object>(); detailMap.put("index", i+1);//序号 detailMap.put("title", "商品"+i);//商品名称 detailMap.put("product_description", "套");//商品规格 detailMap.put("buy_num", 3+i);//销售数量 detailMap.put("saleprice", 100+i);//销售价格 double saleprice=Double.valueOf(String.valueOf(100+i)); Integer buy_num=Integer.valueOf(String.valueOf(3+i)); String buy_price=df.format(saleprice*buy_num); detailMap.put("buy_price", buy_price);//单个商品总价格 money=money+Double.valueOf(buy_price); detailList.add(detailMap); } //总金额 String order_money=String.valueOf(money); //金额中文大写 String money_total = MoneyUtils.change(money); //word模板地址获取方式一:缺点---打jar包获取不到该路径 // String basePath=ClassUtils.getDefaultClassLoader().getResource("").getPath()+"static/template/"; // String resource =basePath+"order1.docx";//word模板地址 //word模板地址获取方式二:优点---相比上一种方式,这种方法不会在linux或者jar上失效 ClassPathResource classPathResource = new ClassPathResource("static/template/order1.docx"); String resource = classPathResource.getURL().getPath(); //渲染表格 HackLoopTableRenderPolicy policy = new HackLoopTableRenderPolicy(); Configure config = Configure.newBuilder().bind("detailList", policy).build(); XWPFTemplate template = XWPFTemplate.compile(resource, config).render( new HashMap<String, Object>() {{ put("detailList", detailList); put("order_number", "2356346346645"); put("y", now.get(Calendar.YEAR));//当前年 put("m", (now.get(Calendar.MONTH) + 1));//当前月 put("d", now.get(Calendar.DAY_OF_MONTH));//当前日 put("order_money",order_money);//总金额 put("money_total",money_total);//金额中文大写 }} ); //=================生成文件保存在本地D盘某目录下================= String temDir="D:/mimi/"+File.separator+"file/word/"; ;//生成临时文件存放地址 //生成文件名 Long time = new Date().getTime(); // 生成的word格式 String formatSuffix = ".docx"; // 拼接后的文件名 String fileName = time + formatSuffix;//文件名 带后缀 FileOutputStream fos = new FileOutputStream(temDir+fileName); template.write(fos); //=================生成word到设置浏览默认下载地址================= // 设置强制下载不打开 response.setContentType("application/force-download"); // 设置文件名 response.addHeader("Content-Disposition", "attachment;fileName=" + fileName); OutputStream out = response.getOutputStream(); template.write(out); out.flush(); out.close(); template.close(); } catch (Exception e) { e.printStackTrace(); } } }
需要注意的是:
方法中的代码:
FileOutputStream fos = new FileOutputStream(temDir+fileName);//输出路径(下载到指定路径)
exportDataWord3方法中的两行代码:
//浏览器下载 response.setContentType("application/force-download"); response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
如果想要显示浏览器下载
,exportDataWord3方法中的这两行代码必须显示
。
5.MoneyUtils 工具类
package com.example.word.common; /** * 金额转换工具类 */ public class MoneyUtils { private static final String UNIT = "万千佰拾亿千佰拾万千佰拾元角分"; private static final String DIGIT = "零壹贰叁肆伍陆柒捌玖"; private static final double MAX_VALUE = 9999999999999.99D; public static String change(double v) { if (v < 0 || v > MAX_VALUE){ return "参数非法!"; } long l = Math.round(v * 100); if (l == 0){ return "零元整"; } String strValue = l + ""; // i用来控制数 int i = 0; // j用来控制单位 int j = UNIT.length() - strValue.length(); String rs = ""; boolean isZero = false; for (; i < strValue.length(); i++, j++) { char ch = strValue.charAt(i); if (ch == '0') { isZero = true; if (UNIT.charAt(j) == '亿' || UNIT.charAt(j) == '万' || UNIT.charAt(j) == '元') { rs = rs + UNIT.charAt(j); isZero = false; } } else { if (isZero) { rs = rs + "零"; isZero = false; } rs = rs + DIGIT.charAt(ch - '0') + UNIT.charAt(j); } } if (!rs.endsWith("分")) { rs = rs + "整"; } rs = rs.replaceAll("亿万", "亿"); return rs; } public static void main(String[] args){ System.out.println(MoneyUtils.change(12356789.9845)); } }
5.jsp部分代码:
<a href="#" class="easyui-linkbutton" onclick="doExportWord3();" data-options="iconCls:'icon-save'">导出word(包含动态表格)</a> function doExportWord3(){ window.location.href="<%=basePath%>/auth/exportWord/exportDataWord3"; }
---------------------------------
解决ajax下载乱码:
let uri = '/live/sum/exportExcel'
let xhr = new XMLHttpRequest()
xhr.onload = function(e) {
if (this.status == 200) {
/* 文件下载 */
let blob = new Blob([this.response], {
type: "application/vnd.ms-excel;charset=UTF-8"
})
let downloadUrl = window.URL.createObjectURL(blob)
let link = document.createElement('a')
link.href = downloadUrl
link.download = '统计.xlsx'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
window.URL.revokeObjectURL(downloadUrl)
}
hideLoading_dialog()
}
xhr.open("POST", uri, true)
/* 重点:后端返回的响应类型为 arraybuffer,不是常用的 blob */
xhr.responseType = "arraybuffer"
/* 此处为后端接受请求数据的 MIME 类型 */
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
let param = new URLSearchParams()
param.append("queryDate", queryDate)
xhr.send(param)
6.导出结果:
功能延伸
SpringBoot+Poi-tl根据Word模板动态生成word(含动态行表格、合并单元格)
转载https://blog.csdn.net/qq_26383975/article/details/111561540