Java 将xml模板动态填充数据转换为word文档 您所在的位置:网站首页 word文档另存为pdf格式 Java 将xml模板动态填充数据转换为word文档

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

2023-08-01 16:58| 来源: 网络整理| 查看: 265

需要用到的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 标签:

图片中横线说明:

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

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

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

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

            具体合并方法:

                    a、开始合并的行:

                    b、需要合并的行:

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

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

二、Java后台代码实现

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

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

package testXML; /** * 图片bean */ public class ImageBean { // 图片1 private Integer img1Index; private String imgName; private String img1Width; private String img1Height; private String img1Base64; // 图片2 private 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 dataMap = new HashMap(); dataMap.put("title", "测试转换word文档"); dataMap.put("head", "头部信息"); dataMap.put("content", "主要内容主要内容主要内容"); dataMap.put("tableDescription", "表格描述内容"); // 构造一个list,存放图片相关信息 List list = new ArrayList(); // 将图片转为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文件,本质仍是属于xml xml2XmlDoc(dataMap,templetFilePath,targetFilePath); } /** * 将xml模板转换为后缀为doc文件,本质仍是属于xml * @param dataMap 需要填充到模板的数据 * @param templetFilePath 模板文件路径 * @param targetFilePath 目标文件保存路径 * @throws IOException * @throws TemplateException */ public static void xml2XmlDoc(Map 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); // 不保存待定的更改 } } }



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有