Java 中利用 Freemark 生成 Word 文档

作者: 七弦桐语 | 来源:发表于2017-01-17 23:21 被阅读791次

FreeMarker是一款模板引擎:即一种基于模板、用来生成输出文本(任何来自于HTML格式的文本用来自动生成源代码)的通用工具。 使用MVC模式的动态页面的设计构思使得你可以将前端设计师(编写HTML页面的人员)从程序员中分离出来。本文为使用 freemarker 来生成 word 文档的示例。


工具

  • Word2003 以上版本或者 wps2016 的版本(即可以支持文档另存为xml格式的版本)
  • jar包:freemark.jar

第一步:数据准备

  • 一张图片:1.jpg
  • 一个word文档。内容如下:
word文档

第二步:制作模板

  1. 把word文档另存为.xml格式,我起名称为template.xml
  2. 利用Notepad++或者sublime text这样的工具打开template.xml文件。
  3. 利用Ctrl+F搜索word中你写的信息,如:小明、男...等关键字找到template.xml中对应的字,用${name}${sex}等值代替,${}中的值为代码中要赋值的变量。
  4. 搜索<pkg:binarydata></pkg:binarydata>会发现这俩标签之间是一堆特别特别长的字符。像是这样:
<pkg:binarydata>
把中间的字符替换成${image},如图: 图片替换

4.把替换好的template.xml文件后缀名改为.ftl。至此,模板制作成功。

第三步:编写代码

基于 SpringMVC ,简单写了个 Demo。

页面 index.jsp

<body>
    <center>
        <div style="padding: 3px 2px; border-bottom: 1px solid #ccc">填写相关数据进行导出</div>
        <form name="form" action="" method="post">
            <table>
                <tr>
                    <td>姓名:</td>
                    <td><input name="name" type="text"></input></td>
                </tr>
                <tr>
                    <td>性别:</td>
                    <td><input id="man" name="sex" type="radio" value='1' checked />男
                        <input id="woman" name="sex" type="radio" value='0' />女</td>
                </tr>
                <tr>
                    <td>生日:</td>
                    <td><input name="birthday" type="text"></input></td>
                </tr>
                <tr>
                    <td>电话:</td>
                    <td><input name="telphone" type="text"></input></td>
                </tr>
                <tr>
                    <td>邮箱:</td>
                    <td><input name="email" type="text"></input></td>
                </tr>
                <tr>
                    <td>地址:</td>
                    <td><input name="address" type="text"></input></td>
                </tr>
                <tr>
                    <td>头像路径:</td>
                    <td><input id="photo" name="photo" type="text" /></td>
                </tr>
            </table>
            <br>
            <table>
                <tr>
                    <input type="button" value="导出Word" onclick="exportData('word')">
                </tr>
            </table>
        </form>
    </center>
</body>
<script type="text/javascript">
    function exportData(obj) {
        if (obj == "word") {
            form.action = "${pageContext.request.contextPath}/exportWord.action";
            form.submit();
        }
    }
    
    function showPreview(obj){
        var str = obj.value;
        document.getElementById("previewImg").innerHTML = "![]( + str + )";
    } 
</script>

工具类 ExportWorldUtil.java

package com.export.util;

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.UnsupportedEncodingException;
import java.io.Writer;
import java.util.Map;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import sun.misc.BASE64Encoder;

/**
 * 数据导出World工具类
 * 
 * @author qixiantong
 *
 */
public class ExportWorldUtil {
    private Configuration configuration;

    public void configure(String templatePath) {
        configuration = new Configuration();
        configuration.setDefaultEncoding("utf-8");
        configuration.setClassForTemplateLoading(this.getClass(), templatePath);
    }

    public void create(String templatePath, String templateName, String filePath, String fileName,
            Map<String, Object> map) {
        this.configure(templatePath);
        Template template = null;
        try {
            // 读取freemarker的导出模板
            template = configuration.getTemplate(templateName);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 创建一个file对象
        File outFile = new File(filePath + fileName);
        // 写入字符流的抽象类
        Writer out = null;
        try {
            // 创建一个使用默认大小输出缓冲区的缓冲字符输出流
            // OutputStreamWriter 字节-字符转换流
            // FileOutputStream 文件输出流
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        if (map != null) {
            try {
                // 执行模板,使用提供的数据模型
                template.process(map, out);
                out.close();
            } catch (TemplateException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * 由于word中图片为base64编码, 故将图片转化为base64编码后的字符串
     * @author qixiantong
     * @return String
     */
    public String getImageStr(String imgFile) {
        // String imgFile = new File(this.getClass().getResource("/").getPath())
        // + "/com/export/doc/1.jpg";
        InputStream in = null;
        byte[] data = null;
        try {
            // 创建照片的字节输入流
            in = new FileInputStream(imgFile);
            // 创建一个长度为照片总大小的内存空间
            data = new byte[in.available()];
            // 从输入流中读取文件大小的字节,并将其存储在缓冲区数组 data中
            in.read(data);
            // 关闭输入流
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        BASE64Encoder encoder = new BASE64Encoder();
        // 进行base64加密
        return encoder.encode(data);
    }
}

控制器 ExportDataAction.java

    /**
     * 起始页面
     * 
     * @return
     */
    @RequestMapping("/index")
    public String login() {
        return "index";
    }
    /**
     * 导出到Word
     * 
     * @author zhang_cq
     * @return
     */
    @RequestMapping("/exportWord")
    public String exportWord(HttpServletRequest request, Person person) {
        try {
            ExportWorldUtil util = new ExportWorldUtil();
            String templatePath = "../doc/"; // 模板路径
            String templateName = "template.ftl"; // 模板名称
            String filePath = "d:/";
            String fileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + ".doc"; // 生成的World文档路径
            ExportWorldUtil ewu = new ExportWorldUtil();
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("name", person.getName());
            String sex = person.getSex();
            map.put("sex", "1".equals(sex) ? "男" : "女");
            String imagePath = person.getPhoto();
            //imagePath = imagePath.replace("\\", "/");
            map.put("image", util.getImageStr(imagePath));
            SimpleDateFormat bartDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            Date birthday = person.getBirthday();
            if (birthday != null) {
                String birth = bartDateFormat.format(birthday);
                map.put("birthday", birth);
            }
            map.put("telphone", person.getTelphone());
            map.put("email", person.getEmail());
            map.put("address", person.getAddress());
            ewu.create(templatePath, templateName, filePath, fileName, map);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "index";
    }   
    // 使用注解进行日期格式数据转换
    @InitBinder
    private void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
        // 指定日期类型及日期数据的格式
        // 日期类型要和student类的birthday一致
        binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
    }

至此,在 java 中 生成 word 文档的实例就做完了。想看完整代码,欢迎访问https://coding.net/u/zhang_cq/p/ExportData/git

相关文章

网友评论

    本文标题:Java 中利用 Freemark 生成 Word 文档

    本文链接:https://www.haomeiwen.com/subject/xervbttx.html