使用Freemarker导出Word文档(包含图片)代码实现及总结
.personSunflowerP { background: rgba(51, 153, 0, 0.66); border-bottom: 1px solid rgba(0, 102, 0, 1); border-top-left-radius: 7px; border-top-right-radius: 7px; color: rgba(255, 255, 255, 1); height: 1.8em; line-height: 1.8em; padding: 5px }
声明:转载需要注明出处 https://www.cnblogs.com/sun-flower1314/p/10126111.html
本篇是关于利用FreeMarker导出Word的实现步骤。
优点:采用FreeMarker是导出Word的最佳实现,非常的灵活,能够按照自己指定的样式设置并输出内容,操作简单方便,代码实现也容易。代码量少,样式、内容容易控制,打印不变形,完全符合office标准
缺点:需要提前设计好word模板,把需要替换的地方用特殊标记标出来
关于使用POI的导出方案在另一篇博客:https://www.cnblogs.com/sun-flower1314/p/10128796.html
下面是实现的效果图:
下面是实现步骤:
1.添加FreeMarker需要的jar包(这里用的是2.3.28版本,从网上的maven仓库中获取的)
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
2.然后制作需要导出的Word模板。先利用office工具生成导出怎样的word样式,如图是我绘制的模板:
3.制作好了基本的样式之后,然后另存为.xml格式文档,如:
4.打开这个text.xml文件,在相应的地方填入${xx}表达式:
5.填好后,使用其Notepad++或Sublime工具打开文件,能够看到xml的内容如下:
填入后,如果有可能${}与 telephone 分离,则删除分离后${},然后在telephone上添加${}后保存。
另一种最安全的方式是:不删除分离的${},先在telephone上添加${},保存后,用word工具打开test.xml,将原来分离的${}删除即可。
6.成功修改后,将文件重命名为.ftl格式的文件。然后将文件放置在项目中或其他路径。这里我是将其拷贝至包中
7. 接下来是代码层的实现
package com.myHelloWorld; import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Map; import freemarker.core.ParseException;
import freemarker.log.Logger;
import freemarker.template.Configuration;
import freemarker.template.MalformedTemplateNameException;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import freemarker.template.TemplateNotFoundException;
import sun.misc.BASE64Encoder; /**
* @Description 利用FreeMarker导出Word
* 2018年12月15日 下午10:23:40
* @Author Huang Xiaocong
*/
public class ExportMyWord { private Logger log = Logger.getLogger(ExportMyWord.class.toString());
private Configuration config = null; public ExportMyWord() {
config = new Configuration(Configuration.VERSION_2_3_28);
config.setDefaultEncoding("utf-8");
}
/**
* FreeMarker生成Word
* @param dataMap 数据
* @param templateName 目标名
* @param saveFilePath 保存文件路径的全路径名(路径+文件名)
* @Author Huang Xiaocong 2018年12月15日 下午10:19:03
*/
public void createWord(Map<String, Object> dataMap, String templateName, String saveFilePath) {
//加载模板(路径)数据
config.setClassForTemplateLoading(this.getClass(), "");
//设置异常处理器 这样的话 即使没有属性也不会出错 如:${list.name}...不会报错
config.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
Template template = null;
if(templateName.endsWith(".ftl")) {
templateName = templateName.substring(0, templateName.indexOf(".ftl"));
}
try {
template = config.getTemplate(templateName + ".ftl");
} catch (TemplateNotFoundException e) {
log.error("模板文件未找到", e);
e.printStackTrace();
} catch (MalformedTemplateNameException e) {
log.error("模板类型不正确", e);
e.printStackTrace();
} catch (ParseException e) {
log.error("解析模板出错,请检查模板格式", e);
e.printStackTrace();
} catch (IOException e) {
log.error("IO读取失败", e);
e.printStackTrace();
}
File outFile = new File(saveFilePath);
if(!outFile.getParentFile().exists()) {
outFile.getParentFile().mkdirs();
}
Writer out = null;
FileOutputStream fos = null;
try {
fos = new FileOutputStream(outFile);
} catch (FileNotFoundException e) {
log.error("输出文件时未找到文件", e);
e.printStackTrace();
}
out = new BufferedWriter(new OutputStreamWriter(fos));
//将模板中的预先的代码替换为数据
try {
template.process(dataMap, out);
} catch (TemplateException e) {
log.error("填充模板时异常", e);
e.printStackTrace();
} catch (IOException e) {
log.error("IO读取时异常", e);
e.printStackTrace();
}
log.info("由模板文件:" + templateName + ".ftl" + " 生成文件 :" + saveFilePath + " 成功!!");
try {
out.close();//web项目不可关闭
} catch (IOException e) {
log.error("关闭Write对象出错", e);
e.printStackTrace();
}
}
/**
* 获得图片的Base64编码
* @param imgFile
* @return
* @Author Huang Xiaocong 2018年12月15日 下午10:15:10
*/
public String getImageStr(String imgFile) {
InputStream in = null;
byte[] data = null;
try {
in = new FileInputStream(imgFile);
} catch (FileNotFoundException e) {
log.error("加载图片未找到", e);
e.printStackTrace();
}
try {
data = new byte[in.available()];
//注:FileInputStream.available()方法可以从输入流中阻断由下一个方法调用这个输入流中读取的剩余字节数
in.read(data);
in.close();
} catch (IOException e) {
log.error("IO操作图片错误", e);
e.printStackTrace();
}
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data); }
}
下面是测试类:
public static void main(String[] args) {
ExportMyWord emw = new ExportMyWord();
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put("name", "黄xx");
dataMap.put("age", 26);
dataMap.put("blog", "sun_flower火柴客");
dataMap.put("email", "sun_flower@xxxx.com");
dataMap.put("gender", "男");
dataMap.put("imgheader", emw.getImageStr("D:\\picture\\23.jpg"));
dataMap.put("telephone", "123456789101");
dataMap.put("address", "深圳");
dataMap.put("naturework", "全职");
dataMap.put("industry", "IT");
dataMap.put("aplication", "Java开发");
dataMap.put("time", "2013年-2017年");
dataMap.put("schoolname", "南昌大学");
dataMap.put("education", "本科");
dataMap.put("projectname", "电子证照xxxx");
dataMap.put("projecttime", "2017年3月");
dataMap.put("projectcontent", "我们除了有视、听、味、嗅、触这些外感系统之外,人类还有一个非常重要的内感系统,就是我们情绪和情感的世界。"
+ "这种感受是那样地细腻、微妙、强烈、深沉;看不见、摸不着,说不清、道不明。...");
emw.createWord(dataMap, "test.ftl", "E:/简历.doc");
}
7.效果图:
整个过程就是这样。
对于需要多条记录或循环的部分,只要在模板层的代码中添加标签:
<#list project as Item>
<w:t>${Item.projectname}</w:t><w:br/>
</#list>
这里说下需要注意的点:
1)很多项目中采用的是Log4j或 Commons Logging日志形式。而Freemarker自带日志类型,即:
若导入的FreeMarker 2.3.x版本以下,可能回抛出Freemarker模版缓存问题:
Compiling FreeMarker template test.ftl[zh_CN,UTF-8,parsed] .... Could not find template in cache
看官方解释:
2)插入图片的时候格外小心,因为可能导出后是一堆图片代码,那是因为模板未能识别这个图片。说明导出没有问题,而是模板有问题。解决方案就是在原来的地方随便插入一张图片,然后在ftl中删除图片代码就可以了。
同时 希望各位能提出宝贵的意见方便改进 不甚感激!!
使用Freemarker导出Word文档(包含图片)代码实现及总结的更多相关文章
- freemarker导出word文档——WordXML格式解析
前不久,公司一个项目需要实现导出文档的功能,之前是一个同事在做,做了3个星期,终于完成了,但是在项目上线之后却发现导出的文档有问题,此时,这个同事已经离职,我自然成为接班者,要把导出功能实现,但是我看 ...
- freemarker导出word文档
使用freemarker导出word文档的过程 **************************************************************************** ...
- Java使用freemarker导出word文档
通过freemarker,以及JAVA,导出word文档. 共分为三步: 第一步:创建模板文件 第二步:通过JAVA创建返回值. 第三步:执行 分别介绍如下: 第一步: 首先创建word文档,按照想要 ...
- Java用freemarker导出Word 文档
1.用Microsoft Office Word打开word原件: 2.把需要动态修改的内容替换成***,如果有图片,尽量选择较小的图片几十K左右,并调整好位置: 3.另存为,选择保存类型Word 2 ...
- 使用FreeMarker导出word文档(支持导出图片)
一.添加maven依赖,导入FreeMarker所需要的jar包 <dependency> <groupId>org.freemarker</groupId> &l ...
- Java 用Freemarker完美导出word文档(带图片)
Java 用Freemarker完美导出word文档(带图片) 前言 最近在项目中,因客户要求,将页面内容(如合同协议)导出成word,在网上翻了好多,感觉太乱了,不过最后还是较好解决了这个问题. ...
- 【Java】用Freemarker完美导出word文档(带图片)
Java 用Freemarker完美导出word文档(带图片) 前言 最近在项目中,因客户要求,将页面内容(如合同协议)导出成word,在网上翻了好多,感觉太乱了,不过最后还是较好解决了这个问题. ...
- 【Java】导出word文档之freemarker导出
Java导出word文档有很多种方式,本例介绍freemarker导出,根据现有的word模板进行导出 一.简单导出(不含循环导出) 1.新建一个word文件.如下图: 2.使用word将文件另存为x ...
- PHP网页导出Word文档的方法分离
今天要探讨的是PHP网页导出Word文档的方法,使用其他语言的朋友也可以参考,因为原理是差不多的. 原理 一般,有2种方法可以导出doc文档,一种是使用com,并且作为php的一个扩展库安装到服务器上 ...
随机推荐
- 16、lnmp_mysql二进制安装
16.1.lnmp介绍: lnmp架构,linux的php的程序架构: linux nginx MySQL PHP; # lamp:linux apache mysql php; 16.2.mysql ...
- form 向java控制类 提交多表数据 、提交list数组数据
案例:form中有三个表的数据,一个主表,两个子表 1.在主表model类添加 对应子表数据集 2.界面上主表定义 3.控制类接收,直接用主表对象接收即可
- gRPC(3):拦截器
在 gRPC 调用过程中,我们可以拦截 RPC 的执行,在 RPC 服务执行前或执行后运行一些自定义逻辑,这在某些场景下很有用,例如身份验证.日志等,我们可以在 RPC 服务执行前检查调用方的身份信息 ...
- Basic remains java入门题
Basic remains input: b p m 读入p进制的p,m, 求p%m ,以b进制输出 1 import java.util.*; 2 import java.math ...
- webrtc之TURE、STUN、摄像头打开实战
前言: 大家周末好,今天给 webrtc之TURE.STUN.摄像头打开实战 大家分享的是webrtc第一篇文章,在之前的音视频文章里面没有分享过关于webrtc的内容:在上个周末分享了一篇关于播放器 ...
- Python - 基本数据类型_Number 数字、bool 布尔、complex 复数
Number 数字,是一个大的分类,细分四小类 整数:int 浮点数:float 布尔:bool 复数:complex int 的栗子 print(type(-1)) print(type(1)) p ...
- SELECT SQL
替换换行符: update qgnews set article_url=REPLACE(article_url,char(10),'') 替换回车符: update qgnews set artic ...
- 团队开发day04
通过myurl.openConnection()连接一直连接失败,问题解决: 在一般的Java Web程序开发中,我们通常使用localhost或者127.0.0.1来访问本机的Web服务, 但是如果 ...
- xmind8 Mac序列号
1.首先去官网下载xmind8的安装包:XMind for Mac 也可以去我的百度网盘下载: 链接:https://pan.baidu.com/s/1eY52YsSaPmr-YFhB62Cli ...
- File类与常用IO流第六章——使用try...catch...finally处理流中的异常
在JDK1.7之前: 1 package com.itheima.demo06.trycatch; 2 3 import java.io.FileWriter; 4 import java.io.IO ...