Java word动态数据填充并转为pdf最详细的讲解【附带源码项目】

Java Word数据动态填充,并将word转为pdf

适用范围:
1.已有word模板,word中的一些数据需要动态生成。
2.word转为pdf

本文章讲解的内容是一个完整的适用流程。就是首先是一个word模板,然后动态填充数据生成了一个新的word,填充数据之后最后转换成了pdf。
如果你只需要动态填充数据,得到一个新的word的话,适当修改下代码就可以了。说白了就是删代码,因为本身就用到了此功能。
如果你需要word转为pdf,适当修改下代码也是可以的。说白了还是删代码,因为本身也用到此功能。
发挥您的想象空间,此插件甚是强大。有问题联系我哦。代码注释里说了怎么找我…

话不多说,上干货,上代码…

Constants.java

package org.example.util;

/**
 * @author lucas
 * @program wtp-site
 * @description
 * @createDate 2020-03-04 23:05:31
 * 关注微信公众号"程序员无名",600GJava架构师网盘资料等你下载
 * 这套代码我已经亲测可用了。若有特殊问题,请于公众号里随时与我联系。
 **/
public class Constants {


    /**
     * aspose需要的签名文件名称
     */
    public static String licensePath = "license.xml";

    /**
     * 模板,签名文件存放的路径(绝对路径哈,我这里是mac的绝对路径。)
     */
    public static String docXmlTemplatePath = "/Users/lisw/work/work-project/workTppdf/";
}

DocToPdf.java

package org.example.util;

import com.aspose.words.Document;
import com.aspose.words.FontSettings;
import com.aspose.words.License;
import com.aspose.words.SaveFormat;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Map;
import java.util.UUID;
/**
 * @author lucas
 * @program wtp-site
 * @description  word转pdf核心代码
 * @createDate 2020-03-04 23:05:31
 * 关注微信公众号"程序员无名",600GJava架构师网盘资料等你下载
 * 这套代码我已经亲测可用了。若有特殊问题,请于公众号里随时与我联系。
 **/
public class DocToPdf {

    static String docTemplatePath = Constants.docXmlTemplatePath;
    public static boolean getLicense() {
        boolean result = false;
        try {
            InputStream is = new FileInputStream(docTemplatePath+Constants.licensePath);
            License aposeLic = new License();
            aposeLic.setLicense(is);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public static  String DocToPdf(Map<String,Object> params,String documentXmlName,String documentDocName) throws Exception {
        try{
            if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
                return null;
            }

            String templateUUId = UUID.randomUUID().toString();
            String baseUrl=System.getProperty("java.io.tmpdir")+"/";
            String xml = baseUrl+templateUUId+".xml";
            XmlToDocx.toDocx(documentXmlName,docTemplatePath+documentDocName,xml,baseUrl+templateUUId+".docx",params);
            String docx = baseUrl+templateUUId+".docx";
            String pdf = baseUrl+templateUUId+".pdf";
            File file = new File(pdf); // 新建一个空白pdf文档
            FileOutputStream os = new FileOutputStream(file);
            Document doc = new Document(docx); // Address是将要被转化的word文档
            String osName = isWindows();
            String fonts [] = null;
            /**
             * 适配字体文件
             */
            if(osName.equals("linux")){
                fonts = new String[]{"/usr/share/fonts/chinese/","/usr/share/fonts/simsun/","/usr/share/fonts/black/","/usr/share/fonts/wingdings/"};
            }else if(osName.equals("mac")){
                fonts = new String[]{"/Users/fonts/chinese/","/Users/fonts/simsun/","/Users/fonts/black/","/Users/fonts/wingdings/"};
            }
            FontSettings.setFontsFolders(fonts, true);
            doc.save(os, SaveFormat.PDF);// 全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF,
            if(os!=null){
                os.close();
            }
            delete(xml,docx);//删除文件
            return pdf;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }

    }
    private static String isWindows() {
        String osName = System.getProperties().getProperty("os.name").toUpperCase();
        if(osName.indexOf("WINDOWS")!=-1){
            return "windows";
        }else if(osName.indexOf("MAC")!=-1){
            return "mac";
        }else{
            return "linux";
        }
    }
    public static void delete(String xmlPath,String wordPath){
        File file = new File(xmlPath);
        if(file.exists()){
            file.delete();
        }
        File wordFile = new File(wordPath);
        if(wordFile.exists()){
            wordFile.delete();
        }
    }

}

XmlToDocx.java

package org.example.util;

import freemarker.template.TemplateException;

import java.io.*;
import java.util.Enumeration;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

/**
 * @author lucas
 * @program wtp-site
 * @description word动态填充数据核心类
 * @createDate 2020-03-04 23:05:31
 * 关注微信公众号"程序员无名",600GJava架构师网盘资料等你下载
 * 这套代码我已经亲测可用了。若有特殊问题,请于公众号里随时与我联系。
 **/
public class XmlToDocx {

    /**
     * @param xmlTemplate  xml的文件名
     * @param docxTemplate docx的路径和文件名
     * @param xmlTemp      填充完数据的临时xml
     * @param toFilePath   目标文件名
     * @param map          需要动态传入的数据
     * @throws IOException
     */
    public static void toDocx(String xmlTemplate, String docxTemplate, String xmlTemp, String toFilePath, Map map) {
        try {
            // 1.map是动态传入的数据
            // 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
            Writer w1 = new OutputStreamWriter(new FileOutputStream(xmlTemp), "utf-8");
            // 2.把map中的数据动态由freemarker传给xml
            XmlTplUtil.process(xmlTemplate, map, w1);
            // 3.把填充完成的xml写入到docx中
            XmlToDocx xtd = new XmlToDocx();
            xtd.outDocx(new File(xmlTemp), docxTemplate, toFilePath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @param documentFile 动态生成数据的docunment.xml文件
     * @param docxTemplate docx的模板
     * @param toFilePath   需要导出的文件路径
     * @throws ZipException
     * @throws IOException
     */

    public void outDocx(File documentFile, String docxTemplate, String toFilePath) throws ZipException, IOException {

        try {
            File docxFile = new File(docxTemplate);
            ZipFile zipFile = new ZipFile(docxFile);
            Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();
            ZipOutputStream zipout = new ZipOutputStream(new FileOutputStream(toFilePath));
            int len = -1;
            byte[] buffer = new byte[1024];
            while (zipEntrys.hasMoreElements()) {
                ZipEntry next = zipEntrys.nextElement();
                InputStream is = zipFile.getInputStream(next);
                // 把输入流的文件传到输出流中 如果是word/document.xml由我们输入
                zipout.putNextEntry(new ZipEntry(next.toString()));
                if ("word/document.xml".equals(next.toString())) {
                    InputStream in = new FileInputStream(documentFile);
                    while ((len = in.read(buffer)) != -1) {
                        zipout.write(buffer, 0, len);
                    }
                    in.close();
                } else {
                    while ((len = is.read(buffer)) != -1) {
                        zipout.write(buffer, 0, len);
                    }
                    is.close();
                }
            }
            zipout.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

XmlTplUtil.java

package org.example.util;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.util.Map;

/**
 * @author lucas
 * @program wtp-site
 * @description  word动态填充工具类
 * @createDate 2020-03-04 23:05:31
 * 关注微信公众号"程序员无名",600GJava架构师网盘资料等你下载
 * 这套代码我已经亲测可用了。若有特殊问题,请于公众号里随时与我联系。
 **/
public class XmlTplUtil {

    private static XmlTplUtil tplm = null;
    private Configuration cfg = null;

    private XmlTplUtil() {
        cfg = new Configuration();
        try {
            cfg.setDirectoryForTemplateLoading(new File(Constants.docXmlTemplatePath));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static Template getTemplate(String name) throws IOException {
        if (tplm == null) {
            tplm = new XmlTplUtil();
        }
        Template template = tplm.cfg.getTemplate(name,"utf-8");
        return template;
    }

    /**
     * @param templatefile 模板文件
     * @param param        需要填充的内容
     * @param out          填充完成输出的文件
     * @throws IOException
     * @throws TemplateException
     */
    public static void process(String templatefile, Map param, Writer out) throws IOException, TemplateException {
        // 获取模板
        Template template = XmlTplUtil.getTemplate(templatefile);
        template.setOutputEncoding("utf-8");
        // 合并数据
        template.process(param, out);
        if (out != null) {
            out.close();
        }
    }

}

App.java Main方法主类执行入口

package org.example;

import org.example.util.DocToPdf;

import java.util.HashMap;
import java.util.Map;

/**
 * @author lucas
 * @program wtp-site
 * @description
 * @createDate 2020-03-04 23:05:31
 * 关注微信公众号"程序员无名",600GJava架构师网盘资料等你下载
 * 这套代码我已经亲测可用了。若有特殊问题,请于公众号里随时与我联系。
 **/
public class App 
{
    /**
     * 注意事项
     * 1:如果转换之后有乱码现象,极大的概率是你的word当中用了系统不支持的字体。
     * 比如微软雅黑,你在本地windows上可能可以用,一旦你放到了服务器上面,Linux没有这个字体就会乱码。需要安装字体。
     * @param args
     * @throws Exception
     */
    public static void main( String[] args ) throws Exception {
        Map<String,Object> params = new HashMap<String,Object>();
        params.put("name","Lucas");
        String pdfPath = DocToPdf.DocToPdf(params, "document.xml", "template.docx");
        //pdfPath便是最后在系统磁盘里生成的绝对路径地址了,后续业务如果需要,可以读取这个路径进行把文件上传到云空间里或者其他地方。
        //如果上传到云空间了,记得把这个文件在系统磁盘删掉,避免占用系统磁盘。
        //有问题,公众号找我。我等你
        System.out.println("pdf已生成,路径是:"+pdfPath);
    }
}

截止到此,代码已经贴完了。不想看,就下附件,小意思…
注意事项:
1:使用前需要准备三个文件,第一个word模板文件(word格式,代码中文件名叫做template.docx),第二个签名文件(xml格式。我会给你,直接用就行了,代码中叫做license.xml),第三个word模板的源代码文件(xml格式,代码中文件名叫做document.xml)
2:word模版文件:找到你需要生成的word源文件,名字改为template.docx(不改文件名,你就改代码,改成你的文件名字)
3:word源代码文件:这个就需要点东西才能生成了,首先把你的word源文件复制一份哈,毕竟代码还是要用到的。然后将复制后的文件,后缀名改为zip,然后解压zip,找到word文件夹里面的document.xml,这个就是word的源代码文件啦。
4:Constants.java里面需要配置一下,你这些源文件所在的文件夹路径(切记切记切记)。

我的template.docx是这样的
在这里插入图片描述
我的document.xml是这样的
在这里插入图片描述
生成生后的pdf是这样的
在这里插入图片描述
动态数据填充完成,并且成功转换成了pdf。结束了。有问题代码中找我哦…

以下是项目工程哈,有一个aspose的jar包在maven里面是没有的,我也附带给你们了哈。

完整实例代码请关注微信公众号:程序员无名。回复“word”就可以领取了哦。

  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
Java 中,可以使用 Apache POI 库来操作 Word 文档。要实现动态填充数据,可以使用 Word 模板和占位符。具体步骤如下: 1. 创建 Word 模板,并在需要填充数据的位置添加占位符,例如 ${name}。 2. 使用 Apache POI 打开模板文件,并读取文件中的内容。 3. 将读取到的内容转换为一个 XWPFDocument 对象。 4. 使用 XWPFDocument 对象中的方法,查找并替换所有的占位符,例如使用 replaceAll 方法将 ${name} 替换为具体的数据。 5. 保存修改后的 Word 文档。 下面是一个示例代码,演示如何实现动态填充数据: ``` import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; public class WordFiller { public static void main(String[] args) throws IOException { // 读取 Word 模板 FileInputStream fis = new FileInputStream("template.docx"); XWPFDocument doc = new XWPFDocument(fis); // 填充数据 Map<String, String> data = new HashMap<>(); data.put("name", "张三"); data.put("age", "20"); for (XWPFParagraph p : doc.getParagraphs()) { String text = p.getText(); for (String key : data.keySet()) { if (text.contains("${" + key + "}")) { text = text.replace("${" + key + "}", data.get(key)); } } p.setText(text); } // 保存 Word 文档 FileOutputStream fos = new FileOutputStream("output.docx"); doc.write(fos); fos.close(); doc.close(); } } ``` 在代码中,我们首先读取了一个名为 template.docx 的 Word 模板文件。然后,我们定义了一个存储数据的 Map 对象,并将需要填充的数据存储在其中。接下来,我们遍历文档中的所有段落,查找并替换所有的占位符。最后,我们将修改后的文档保存到一个名为 output.docx 的文件中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员无名

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值