没错,你们最爱的小工具又要出现了。博客好久没有更新了。主要吧,最近好像也没有学习什么东西。之前导出word使用的是freemaker,将编写好的word模板保存为xml格式在改成ftl。然后导出
抽取出一个工具类
import freemarker.template.Configuration;
import freemarker.template.Template;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.Map;
/**
* Word工具类 <br>
*
* @author gzm
*/
public class WordUtils {
/**
* 下载动态生成的Word文件。只支持ftl文件模板。
* @param response response
* @param map 值
* @param templatePath 模板路径,即模板放在哪个位置
* @param templateName 模板名称。
* @param downloadName 导出文件名。
* @throws IOException IO异常
*/
public static void downloadWordByTemplate(HttpServletResponse response,
Map map, String templatePath, String templateName, String downloadName) throws IOException {
MapNullToSpace(map);
Configuration configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
configuration.setDirectoryForTemplateLoading(new File(templatePath));
Template freemarkerTemplate = configuration.getTemplate(templateName);
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");
// 设置浏览器以下载的方式处理该文件名
response.setHeader("Content-Disposition", "attachment;filename="
.concat(String.valueOf(URLEncoder.encode(downloadName, "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 = "test.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;
}
/**
* Map中null值改为空字符串
* @param map Map
*/
private static void MapNullToSpace(Map<String, Object> map) {
for (String key : map.keySet()) {
if (null == map.get(key)) {
map.put(key, "");
}
}
}
}
导出是没有问题了,但是在使用模板的时候却发生了问题
我的word中使用这样的变量,转成ftl时候值却被分割开了
之前我的做法是找到这些值手动去调。眼睛都要瞅瞎了效率还低。所以抽时间写了段脚本,变量中的标签情况掉
public static void main(String[] args) {
FileReader fileReader = new FileReader("E:\\个人基本信息表.ftl");
List<String> strings = fileReader.readLines();
FileAppender appender = new FileAppender(FileUtil.newFile("D:\\reslut3.ftl"), 16, true);
for (String string : strings) {
if (!string.contains("$")) {
appender.append(string);
continue;
}
string = string.replaceAll("\\$", "#\\$");
String[] ss = string.split("#");
// 同一行的内容写到同一行,文件追加自动换行了
StringBuilder sb = new StringBuilder();
for (int i = 0; i < ss.length; i++) {
String s1 = ss[i];
if (!s1.startsWith("$")) {
sb.append(s1);
continue;
}
int i1 = s1.lastIndexOf("}");
String substr = s1.substring(0, i1 + 1);
sb.append(substr.replaceAll("<[^>]+>", ""));
sb.append(s1.substring(i1 + 1));
}
appender.append(sb.toString());
}
appender.flush();
appender.toString();
}
脚本中的文件操作使用的是hutool,这个工具包还是非常强大值得使用,如果没有添加hutool依赖的话,可以自己修改一下文件操作的部分
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.10</version>
</dependency>
好了,这样导出的工作就变得简单了很多。