国企或政府单位的项目,经常有这样的需求,把用户填写的数据填充到word或excel模版,然后导出的需求。网上也有解决方案。现在记录下自己的学习过程。采取的方案也是把word或excel转为2003的xml,然后在xml中写velocity的语法,使用velocity引擎解析xml,然后导出(web项目)。这方案唯一不好的地方就是,如果模版稍微改动,那就得重新做一次了。
1.代码
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency> 写个VelocityUtil.java类,需要往word或excel填充数据,并导出,调用createDoc方法就行了。模版放在WEB-INF/vm文件夹下.package com.qhgrain.app.gway.util;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.util.Properties;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
/**
* 用于解析vm模版(world文档保存为xml格式,然后把里面的值改为velocity变量)
* @author Jfei
*注意:解析excel的xml模版时,必须把<NumberFormat ss:Format="_ * #,##0_ ;_ * \-#,##0_ ;_ * "-"_ ;_ @_ "/>
*删掉才行,否则velocity处理模版后,导出的xls会出现内容空白问题
*/
public class VelocityUtil {
private static final Object LOCK = new Object();
/**
* word文件
*/
public static final int WORD_FILE = 1;
/**
* excel文件
*/
public static final int EXCEL_FILE = 2;
private static VelocityEngine ve;
private static VelocityUtil v ;
private VelocityUtil(String templateFolder) {
Properties properties = new Properties();
properties.setProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH, templateFolder);
ve = new VelocityEngine();
ve.init(properties);
ve.init();
}
private static void check(HttpServletRequest request) {
if (v == null) {
synchronized (LOCK) {
v = new VelocityUtil(request.getServletContext().getRealPath("/")+"WEB-INF"+File.separator+"vm");
}
}
}
/**
* 创建 word 文档
* 必须先设置response导出配置,然后解析模版,否则会出问题
* @throws IOException
*/
public static void createDoc(String templateName, VelocityContext vc,HttpServletRequest request, HttpServletResponse response,String docFileName,int fileType) throws IOException {
// response.resetBuffer();
//设置导出
response.addHeader("Cache-Control","no-cache");
response.setCharacterEncoding("UTF-8");
if( WORD_FILE == fileType){
response.setContentType("application/vnd.ms-word;charset=UTF-8");
}else if(EXCEL_FILE == fileType){
response.setContentType("application/vnd.ms-excel;charset=UTF-8");
}else{
response.setContentType("application/octet-stream");
}
String ua = request.getHeader("user-agent");
ua = ua == null ? null : ua.toLowerCase();
if(ua != null && (ua.indexOf("firefox") > 0 || ua.indexOf("safari")>0)){
try {
docFileName = new String(docFileName.getBytes(),"ISO8859-1");
response.addHeader("Content-Disposition","attachment;filename=" + docFileName);
} catch (Exception e) {
}
}else{
try {
docFileName = URLEncoder.encode(docFileName, "utf-8");
response.addHeader("Content-Disposition","attachment;filename=" + docFileName);
} catch (Exception e) {
}
}
//解析模版
check(request);
Template template = ve.getTemplate(templateName, "UTF-8");
PrintWriter write = response.getWriter();
template.merge(vc, write);
if(write != null){
write.flush();
write.close();
}
}
}
action或controller中这样调用即可@RequestMapping("/hurrySupplyFormExport")
public void hurrySupplyCompanyExport(HurrySupplyApplyInfo applyInfo , HttpServletRequest request,HttpServletResponse response) throws IOException{
VelocityContext vc = new VelocityContext();
vc.put("info", applyInfo);
VelocityUtil.createDoc("hurry_supply_apply.vm", vc, request, response, "XXXXX企业资格申请表.xls",VelocityUtil.EXCEL_FILE);
}2.word的处理
然后保存,然后记事本打开,复制放到网上xml格式化下(好看点),解决手写velocity。想下面这样
这样就OK了。
3.excel的处理
excel的处理也和word一样,先转为xml。接下来可以直接在excel中手动写velocity再保存,excel不会把你写的velocity截断。有个特别需要注意的地方,就是转为xml后,记事本打开xml,手动把<NumberFormat ss:Format="_ * #,##0_ ;_ * \-#,##0_ ;_ * "-"_ ;_ @_ "/>,把这个删掉,否则velocity解析的时候会把后面那部分给直接删了,导致导出来的xls文件,打开时是一片空白(这个坑,坑了我)
但是如果是打勾勾选的,那需要先在页面把打勾和没打勾的2个符号先写上,然后在xml中手动处理。
本文介绍了一种在Web项目中使用Velocity引擎填充Word或Excel模板的方法,通过将文档转换为XML并应用Velocity模板语法,实现动态数据填充及导出。
2212





