使用的jar包版本:freemarker-2.3.28.jar
使用开发工具:idea
动态数据替换成${xxx},如果是多条集合用${xx.xxx};
如果没有对应数据会报错。可以替换成${(xx.xxx)?if_exists} (这里表示内容为空不显示)就不会报错了
姓名 | 性别 |
---|---|
${zsxm?if_exists} | ${zsxb?if_exists} |
然后在word里面点击另存为 ——xml格式文件
然后把这个xml文件后缀改成.ftl 得到:
然后把文件拖到idea编译器里格式化一下代码格式
WordUtil.java代码:
import java.io.*;
import java.net.URLEncoder;
import java.util.Map;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.gsgy.utils.DateUtil;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.springframework.util.ResourceUtils;
public class WordUtil {
private static Configuration configuration = null;
//模板文件的位置
private static String templateFolder ="";
static {
try {
//这个是获取到项目里的路径(对应resources文件夹下的template目录)
templateFolder = ResourceUtils.getURL("classpath:").getPath()+ "template/";
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
//或者注释上面的 选择这个固定的地址
// private static final String templateFolder = "D:/wzy/template";
static {
configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
try {
configuration.setDirectoryForTemplateLoading(new File(templateFolder));
} catch (IOException e) {
e.printStackTrace();
}
}
private WordUtil() {
throw new AssertionError();
}
public static void exportMillCertificateWord(HttpServletRequest request, HttpServletResponse response, Map map, String title, String ftlFile) throws IOException {
Template freemarkerTemplate = configuration.getTemplate(ftlFile);
File file = null;
InputStream fin = null;
ServletOutputStream out = null;
try {
// 调用工具类的createDoc方法生成Word文档
file = createDoc(map,freemarkerTemplate);
fin = new FileInputStream(file);
response.setCharacterEncoding("utf-8");
response.setContentType("application/msword");
// 设置浏览器以下载的方式,处理该文件名
String fileName = title+ "自定义名称" + ".doc";
response.setHeader("Content-Disposition", "attachment;filename="
.concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));
out = response.getOutputStream();
byte[] buffer = new byte[512];
int bytesToRead = -1;
// 通过循环将读入的Word文件的内容输出到浏览器中
while((bytesToRead = fin.read(buffer)) != -1) {
out.write(buffer, 0, bytesToRead);
}
} finally {
if(fin != null) fin.close();
if(out != null) out.close(); //关闭对应流
if(file != null) file.delete(); // 删除临时文件
}
}
private static File createDoc(Map<?, ?> dataMap, Template template) {
String name = "sellPlan.doc";
File f = new File(name);
Template t = template;
try {
// 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");
t.process(dataMap, w);
w.close();
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
return f;
}
}
建一个Controller类写调用接口:
@RestController
@RequestMapping("test")
public class testController{
@Autowired
private YwXsRyxxService ywXsRyxxService;
@RequestMapping("/getWord")
@ResponseBody
public void getWord(HttpServletRequest request,HttpServletResponse response) {
//---------------这里开始调用自己需要的数据(粘过去替换成自己的数据方法)--------------------
Page page = new Page();
//人员
List<YwXsRyxx> ryList = ywXsRyxxService.selectlistPage(page);
//-----------------------------结束------------------------------------------
//封装数据
Map<String, Object> map = new HashMap<String, Object>();
map.put("ryList", ryList);
try {
//这里设置文档的名称 和模板的名字
WordUtils.exportMillCertificateWord(request, response, map, "文档名称", "ypbg.ftl");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
这里我们封装了ryList 和wlList两个集合
在模板里CTRL+F 搜索 人员信息
然后慢慢往下 会看到 姓名 、性别 ~~~ 等名称(不熟悉这个文档的小白可以大致看一眼结构)
继续往下看到第一个动态数据姓名的替换符哪里(下图1处)
然后看上图2处 的
<#list ryList as ry> 这里的ryList 是我们后台封装过来的数据
ry是别名
就是模板里定义的变量名ry.xxxx
找到<#list ryList as ry> 下面
在后面加上 #list>
以下二选一
(1)然后将模板放在项目的 resources/template目录下 (没有就建一个)
(2)本地找个文件夹下新建一个template文件夹 把路径考到代码里下面图片位置把2处的值替换了。然后注释1处代码
启动项目 在浏览器输入对应的请求路径
我这是: http://localhost:8088/test/getWord
然后浏览器会下载一个word
一个简单的文档就生成了,复杂的继续摸索延伸。希望能帮到大家 (代码部分有参考网上的文章,自己学习整理了下)
最后加一些Freemarker中用到的判断的语法供参考:
${(xxx)!''} //判断xxx为null 输出'' 或者用${xxx?if_exists}
<#list ryList as ry></#list> //循环遍历集合
<#if xxx?? ></#if> //判断xxx变量是否存在,存在执行里面内容;同java里if判断
<#if type??>
<#if type == 1>是</#if>
<#if type == 0>否</#if>
</#if>
${(dateTime?string('yyyy-MM-dd HH:mm:ss'))!''} //实体类Date类型会报错 这样转换一下(替换dateTime为自己的变量名)