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