需要用到的jar包:

commons-codec-1.10.jar

freemarker-2.3.21.jar

jacob-1.6.jar

实现思路:

1、先将word文档另存为 : Word 2003 XML文档(*.xml) 格式的模板文件;

2、通过Java程序,使用 freemarker.jar包转换为xml格式的word文档文件

3、使用jacob包,将xml格式的word文档文件,转换为docx格式的文档文件

具体实现步骤:

一、模板编辑

1、将word文档另存为xml模板:

2、模板中需要动态改变的内容,通过freemarker标签:${variableName}

说明:variableName是需要动态添加内容的一个标志符号,可自由命名

注意:freemarker标签:${variableName},不能再word文档中直接输入,需要通过记事本,或者其他notePad++ 文本编辑工具先写好,然后再复制到文档中,否则在转换为xml模板时会出问题。具体问题可百度查找

模板样式(参考):

3、处理将要替换的图片,通过xml编辑工具打开xml模板文件:(可使用notePad++打开)

两种替换图片方式,一种是直接动态插入一张图片,另一种是从数据库中读取,并循环插入图片

(1)直接动态插入单张图片:(编辑xml模板文件)

每个位置在保存模板前,放置一张图片,通过notePad++ 打开xml模板文件,找到对应的图片,在xml模板中,图片会发生转换,以base64的编码形式存在,只要找到一长串的字符就能确定这是一张图片;

把红框中的内容(后面还有很长),删除掉,直接替换freemarker标签,另外一张图片同样操作,如图所示:

(2)需要循环插入图片:(编辑xml模板文件)

循环插图,需要加入freemarker循环标签,xml模板中:一对 <tr></tr>,为一行;我的模板设置了表格,需要循环插入表格,那么需要将循环标签包围到图片所在的 tr 标签:

图片中横线说明:

(1)图片中因为有两个地方插入图片,所以需要将一个list对象中,要存两张图片的数据,

(2)<#list loopImageList as imgList> :loopImageList 可自由命名,但是在Java代码中动态填充的数据对象名要一致,imageList 作为一个遍历的对象名,等于将loopImageList的内容赋值给imageList ,获取对象中的属性值,通过imageList.attr 获取

(3)上面的 w:name= 后面是图片的名称,不能一致,必须存不同的文件名,所以,这个需要改动,否则一旦所有文件名称一致,则会出现问题。

(4)如果需要合并第一列的单元格,需要在tr加入标签:

具体合并方法:<#if imageList_index == 0><w:vmerge w:val="restart"/><#else><w:vmerge/></#if>

a、开始合并的行:<w:vmerge w:val="restart"/>

b、需要合并的行:<w:vmerge/>

上面的语句中,_index为imageList 的索引写法,因为需要合并,所以通过判断的方式,将第一个单元格作为合并起始行,其余需要合并的行需要添加结束标签。

(5)如果不需要合并,则不用添加(4)中的语句

二、Java后台代码实现

(1)创建一个封装图片对象的ImageBean类:

(由于list遍历中存了两张不同的图片,所以参数设计不太合理,可参考例子,自己进行优化)

package testXML;
/*** 图片bean*/
public class ImageBean {// 图片1private Integer img1Index;private String imgName;private String img1Width;private String img1Height;private String img1Base64;// 图片2private Integer img2Index;private String img2Width;private String img2Height;private String img2Base64;public ImageBean(Integer img1Index, String imgName, String img1Width,String img1Height, String img1Base64, Integer img2Index,String img2Width, String img2Height,String img2Base64) {this.img1Index = img1Index;this.imgName = imgName;this.img1Width = img1Width;this.img1Height = img1Height;this.img1Base64 = img1Base64;this.img2Index = img2Index;this.img2Width = img2Width;this.img2Height = img2Height;this.img2Base64 = img2Base64;}public Integer getImg1Index() {return img1Index;}public void setImg1Index(Integer img1Index) {this.img1Index = img1Index;}public String getImgName() {return imgName;}public void setImgName(String imgName) {this.imgName = imgName;}public String getImg1Width() {return img1Width;}public void setImg1Width(String img1Width) {this.img1Width = img1Width;}public String getImg1Height() {return img1Height;}public void setImg1Height(String img1Height) {this.img1Height = img1Height;}public String getImg1Base64() {return img1Base64;}public void setImg1Base64(String img1Base64) {this.img1Base64 = img1Base64;}public Integer getImg2Index() {return img2Index;}public void setImg2Index(Integer img2Index) {this.img2Index = img2Index;}public String getImg2Width() {return img2Width;}public void setImg2Width(String img2Width) {this.img2Width = img2Width;}public String getImg2Height() {return img2Height;}public void setImg2Height(String img2Height) {this.img2Height = img2Height;}public String getImg2Base64() {return img2Base64;}public void setImg2Base64(String img2Base64) {this.img2Base64 = img2Base64;}}

(2)将xml模板生成word文档(本质是xml):(代码中存在通用工具处理类)

package testXML;import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import org.apache.commons.codec.binary.Base64;import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;public class XmlTemplate2Word {public static void main(String[] args) throws IOException, TemplateException{Map<String, Object> dataMap = new HashMap<String, Object>();dataMap.put("title", "测试转换word文档");dataMap.put("head", "头部信息");dataMap.put("content", "主要内容主要内容主要内容");dataMap.put("tableDescription", "表格描述内容");// 构造一个list,存放图片相关信息List<Object> list = new ArrayList<Object>();// 将图片转为base64编码格式 (实际运用中可通过循环处理)String imgBase64Str1 = getImgStr("C:/Users/admin/Desktop/签名/李燕萍.png");String imgBase64Str2 = getImgStr("C:/Users/admin/Desktop/签名/李燕萍2.png");String imgBase64Str3 = getImgStr("C:/Users/admin/Desktop/签名/彭玉婷.png");String imgBase64Str4 = getImgStr("C:/Users/admin/Desktop/签名/琪.png");String imgBase64Str5 = getImgStr("C:/Users/admin/Desktop/签名/婿丹.png");String imgBase64Str6 = getImgStr("C:/Users/admin/Desktop/签名/杨诗敏.png");list.add(new ImageBean(1,"图片1","101","35",imgBase64Str1,2,"101","35",imgBase64Str2));list.add(new ImageBean(3,"图片2","101","35",imgBase64Str3,4,"101","35",imgBase64Str4));list.add(new ImageBean(5,"图片3","101","35",imgBase64Str5,6,"101","35",imgBase64Str6));dataMap.put("loopImageList", list);// 模板文件路径:String templetFilePath = "C:/Users/admin/Desktop/测试模板.xml";// 目标文件存放路径String targetFilePath = "C:/Users/admin/Desktop/测试模板(xml格式).doc";// 将xml模板转换为后缀为doc文件,本质仍是属于xmlxml2XmlDoc(dataMap,templetFilePath,targetFilePath);}/*** 将xml模板转换为后缀为doc文件,本质仍是属于xml* @param dataMap  需要填充到模板的数据* @param templetFilePath 模板文件路径* @param targetFilePath  目标文件保存路径* @throws IOException * @throws TemplateException */public static void xml2XmlDoc(Map<String,Object> dataMap, String templetFilePath, String targetFilePath) throws IOException, TemplateException{// 将模板文件路径拆分为文件夹路径和文件名称String tempLetDir = templetFilePath.substring(0,templetFilePath.lastIndexOf("/"));// 注意:templetFilePath.lastIndexOf("/")中,有的文件分隔符为:\ 要注意文件路径的分隔符String templetName = templetFilePath.substring(templetFilePath.lastIndexOf("/")+1);// 将目标文件保存路径拆分为文件夹路径和文件名称String targetDir = targetFilePath.substring(0,targetFilePath.lastIndexOf("/"));String targetName = targetFilePath.substring(targetFilePath.lastIndexOf("/")+1);Configuration configuration = new Configuration();configuration.setDefaultEncoding("UTF-8");// 如果目标文件目录不存在,则需要创建File file = new File(targetDir);if(!file.exists()){file.mkdirs();}// 加载模板数据(从文件路径中获取文件,其他方式,可百度查找)configuration.setDirectoryForTemplateLoading(new File(tempLetDir));// 获取模板实例Template template = configuration.getTemplate(templetName);File outFile = new File(targetDir + File.separator + targetName);//将模板和数据模型合并生成文件Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8"));//生成文件template.process(dataMap, out);out.flush();out.close();}/*** 将图片转换成Base64编码 (优化:在web工程下,可通过工程路径获取流的方式获取图片)* @param imgFile    图片路径* @return* @throws IOException */ public static String getImgStr(String imgFilePath) throws IOException{//将图片文件转化为字节数组字符串,并对其进行Base64编码处理InputStream in = null;byte[] data = null;//读取图片字节数组in = new FileInputStream(imgFilePath);        data = new byte[in.available()];in.read(data);in.close();return new String(Base64.encodeBase64(data));}
}

(3)模板准备好,模板路径正确后,运行程序,得到输出文件:文件内容如下。表格内容进行了替换,图片也循环填充到文档中,但是,这个文档,本质仍然属于xml.格式文档,打开之后,点击另存为会发现是xml格式。

    (4)通过调用转换docx方法,将xml格式的doc转换为docx的word文档格式:

    注意:此步骤,需要用到jacob的jar包,在进行此操作之前,需要将对应jacob包的dll文件,拷贝到系统盘的目录和jdk目目录下的 jre\lib\ 下面

目前我测试的版本有:jacob-1.6.jar、jacob-1.14.3.jar

1.6版本对应的dll : jacob-1.17-M2-x64.dll

1.14.3版本对应的dll : jacob-1.14.3-x64.dll

我展示的展示的是64位操作系统的,具体32位的到网上查找,不懂的可评论留言我看到会回复

具体的资源文件jar包,可自行到网上找,或者到maven仓库中下载。

/*** xml形式的doc文件转换为Docx格式* @param sourcePath 被转换文件的路径* @param targetPath 目标文件路径* @return* @author lixs * @Date 2018年5月29日16:24:08*/public static void docToDocx(String sourcePath, String targetPath){//Word.Application代表COM OLE编程标识,可查询MSDN得到  ActiveXComponent app = new ActiveXComponent("Word.Application");  //设置Word不可见  app.setProperty("Visible",false);  //调用Application对象的Documents属性,获得Documents对象  Dispatch docs = app.getProperty("Documents").toDispatch();  //Dispatch doc = Dispatch.call(docs,"Open",sourcePath,new Variant(false),new Variant(true)).getDispatch();  Dispatch doc = Dispatch.call(docs,"Open",sourcePath).getDispatch(); Dispatch.call(doc,"SaveAS",targetPath,12);  //关闭打开的Word文件  Dispatch.call(doc,"Close",false);  //关闭Word应用程序  app.invoke("Quit",0);  }

(5)有的需要将word文档转换为PDF文件,这里提供一个转PDF的通用方法,:

/*** @Description: word文件转pdf文件* @param sourcePath 被转换word文档路径* @param targetPath 目标PDF文件路径路径* @return boolean* @date 2018年5月22日15:19:48*/public static boolean word2pdf(String sourcePath, String targetPath) {ActiveXComponent app = null;try {app = new ActiveXComponent("Word.Application");app.setProperty("Visible", false);Dispatch docs = app.getProperty("Documents").toDispatch();Dispatch doc = Dispatch.call(docs, "Open", sourcePath, false, true).toDispatch();File tofile = new File(targetPath);if (tofile.exists()) {tofile.delete();}Dispatch.call(doc, "SaveAs", targetPath, 17); // word转PDF格式Dispatch.call(doc, "Close", false);return true;} catch (Exception e) {e.printStackTrace();return false;} finally {if (app != null) {app.invoke("Quit", 0); // 不保存待定的更改}}}

Java 将xml模板动态填充数据转换为word文档相关推荐

  1. java如何根据模板填充数据生成word文档

    java根据模板填充数据生成word文档 这篇文章干什么? 思路总览 1.准备word模板 2.转换文件格式 3.编写代码 补充--下载流 这篇文章干什么?   使用代码将word模板内容进行替换,并 ...

  2. 关于用java编写生成word文档,动态添加数据到word文档的一些心得

    关于用java编写生成word文档,动态添加数据到word文档的一些心得,经过翻阅了无数的有用的和无用的资料以后,总算找到了一种靠谱的方法 1.概述 经过反反复复的查阅资料,总算找到了一个靠谱的生成w ...

  3. java利用Freemarker模板生成docx格式的word文档(全过程)

    参考汇总: wordexport: JAVA生成并导出Word文档技术论证 java利用Freemarker模板生成docx格式的word文档(全过程) - 旁光 - 博客园 # 参考资料 - 其他项 ...

  4. java poi doc转docx_POI动态插入数据到Word文档

    模板制作 制作word模版,${xxxx}是要替换的内容.注意${xxxx}是一个整体,中间不能断开,因为利用POI的API程序操作时,判断是否有这个${xxxx}才进行替换. 依赖的包 org.ap ...

  5. springboot结合Freemarker模板生成docx格式的word文档(附代码)

    首先参考的是这篇文章: java利用Freemarker模板生成docx格式的word文档(全过程) - 旁光 - 博客园参考:https://my.oschina.net/u/3737136/blo ...

  6. java 导出word 带格式_java 导出数据为word文档(保持模板格式)

    导出数据到具体的word文档里面,word有一定的格式,需要保持不变 这里使用freemarker来实现: ①:设计好word文档格式,需要用数据填充的地方用便于识别的长字符串替换  如  aaaaa ...

  7. java通过Excel 模板导出复杂统计类excel文档,在ruoyi前后端分离框架中的应用

    Hello, 大家好! 我是不作死就不会死,智商不在线,但颜值超有品的拆家队大队长 --咖啡汪 一只不是在戏精,就是在戏精路上的极品二哈 前几天刚做了java通过Excel 模板导出复杂统计类exce ...

  8. Word处理控件Aspose.Words功能演示:在 Java 中将 HTML 文件转换为 Word 文档

    在各种情况下,您可能需要将 HTML 内容转换为 Word 文档.例如,用于从所见即所得 HTML 编辑器生成文档或将网页转换为 DOCX 或 DOC 格式.为了以编程方式执行此转换,本文介绍了如何将 ...

  9. java将后台数据库查询到的数据导出word文档当中

    java将后台数据库查询到的数据导出word文档当中 之前项目需求使用Java导出word文档,一直没有进行整理,今天把它进行整理出来,以便以后使用到:下面是导出的word文档. // 前端报告表格 ...

最新文章

  1. easy-x库graphics.h图形库安装
  2. pgsql 两个时间字段相减_如何在Excel做专业的时间序列分析
  3. CircleList
  4. SAP Fiori elements第二次重复加载的问题
  5. Android开发之fragment之replace用法
  6. ant引入html页面,antdesign 中 使用 iconfont symbol方式引入图标不展示
  7. 两线怎么接三线插座图_什么是RTD热电阻?两线制和三线制RTD有什么不同?
  8. mysql建立索引注意事项_索引的原理及索引建立的注意事项
  9. android 游戏引擎 排行_4月旗舰手机性能排行榜:小米10 Pro第四,OPPO Ace2第五
  10. Image-based Lighting approaches and parallax-corrected cubemap
  11. foobar插件_如何为 caddy 添写自定义插件
  12. POJ 1639 Picnic Planning:最小度限制生成树
  13. mysql小黑屏怎么用,兰蔻小黑瓶怎么用?多种使用方法教给大家
  14. 【ArcGIS进阶】制作土地利用转移矩阵
  15. 千月最新影视APICLOUD完整安卓程序源码+UI非常不错
  16. 每一代内存的读写速度大概是多少?
  17. 一分钟让你知道Hadoop是什么
  18. python实现简单的求矩阵的逆
  19. 数学149的女学霸,直言想当程序员!女生当程序员到底行不行?
  20. 云端极简部署Svelte3聊天室

热门文章

  1. Linux 替换字符 换行,sed将换行替换成空格或者其他字符linux操作系统 -电脑资料...
  2. 安装指南:Win10系统+ tensorflow 1.7 GPU+Cuda v9.0+cudnnv7.1 +Python3.6
  3. 记一次U盘量产过程【PS2251-07(PS2307) - F/W 01.02.53 [2014-05-12]】
  4. Ubuntu npm 切换淘宝镜像源
  5. 用java编写在界面中画圆_用java语言编写画随机的圆 十万火急 求大神帮忙!!!...
  6. python智联招聘爬虫
  7. IOS音频转换器 AudioConverterRef
  8. 在Mac上怎么给文件设置密码
  9. 为什么大学要学一堆纸上谈兵的课程?
  10. 记录--两行CSS让页面提升了近7倍渲染性能!