zoukankan      html  css  js  c++  java
  • Freemarker + xml 实现Java导出word

    前言

    最近做了一个调查问卷导出的功能,需求是将维护的题目,答案,导出成word,参考了几种方案之后,选择功能强大的freemarker+固定格式之后的wordxml实现导出功能。导出word的代码是可以直接复用的,于是在此贴出,并进行总结,方便大家拿走。

    实现过程概览

    先在word上,调整好自己想要的样子。然后存为xml文件。保存为freemarker模板,以ftl后缀结尾。将需要替换的变量使用freemarker的语法进行替换。最终将数据准备好,和模板进行渲染,生成文件并返回给浏览器流。

    详细的实现过程

    准备好word的样式

    我们新建一个word,我们应该使用Microsoft office,如果使用wps可能会造成样式有些不兼容。在新建的office中,设置好我们的表格样式。我们的调查问卷涉及到四种类型,单选,多选,填空,简答。我们做出四种类型的示例。

    样式没有问题后,我们选择另存为word xml 2003版本。将会生成一个xml文件。

    格式化xml,并用freemarker语法替换xml

    我们可以先下载一个工具 firstobject xml editor,这个可以帮助我们查看xml,同时方便我们定位我们需要改的位置。
    复制过去之后,按f8可以将其进行格式化,左侧是标签,右侧是内容,我们只需要关注w:body即可。

    像右侧的调查问卷这个就是个标题,我们实际渲染的时候应该将其进行替换,比如我们的程序数据map中,有title属性,我们想要这里展示,我们就使用语法${title}即可。

    freemarker的具体语法,可以参考freemarker的问题,在这里我给出几个简单的例子。
    比如我们将所有的数据放置在dataList中,所以我们需要判断,dataList是不是空,是空,我们不应该进行下面的逻辑,不是空,我们应该先循环题目是必须的,答案是需要根据类型进行再次循环的。语法参考文档,这里不再赘述。

    程序端引入freemarker

    <dependency>
        <groupId>org.freemarker</groupId>
        <artifactId>freemarker</artifactId>
    </dependency>
    

    将我们的flt文件放在resources下的templates下。

    后端代码实现

    此代码可以复用,在此贴出

    public class WordUtils {
    
        private static Configuration configuration = null;
        private static final String templateFolder = WordUtils.class.getClassLoader().getResource("").getPath()+"/templates/word";
        static {
            configuration = new Configuration();
            configuration.setDefaultEncoding("utf-8");
            try {
                configuration.setDirectoryForTemplateLoading(new File(templateFolder));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        /**
         *  @Description:导出word,传入request,response,map就是值,title是导出问卷名,ftl是你要使用的模板名
         */
        public static void exportWord(HttpServletRequest request, HttpServletResponse response, Map map, String title, String ftlFile) throws Exception {
            Template freemarkerTemplate = configuration.getTemplate(ftlFile);
            File file = null;
            InputStream fin = null;
            ServletOutputStream out = null;
            try {
                file = createDocFile(map,freemarkerTemplate);
                fin = new FileInputStream(file);
                String fileName = title + ".doc";
    			response.setCharacterEncoding("utf-8");
    			response.setContentType("application/msword");
    			response.setHeader("Content-Disposition", "attachment;filename="
                 +fileName);
    			out = response.getOutputStream();
                byte[] buffer = new byte[512];  
                int bytesToRead = -1;
                while((bytesToRead = fin.read(buffer)) != -1) {
                    out.write(buffer, 0, bytesToRead);
                }
            }finally {
                if(fin != null) fin.close();
                if(out != null) out.close();
                if(file != null) file.delete(); 
            }
        }
    
        /**
         *  @Description:创建doc文件
         */
        private static File createDocFile(Map<?, ?> dataMap, Template template) {
            File file = new File("init.doc");
            try {
                Writer writer = new OutputStreamWriter(new FileOutputStream(file), "utf-8");
                template.process(dataMap, writer);
                writer.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return file;
        }
    
    }
    

    有了工具类后,我们准备好我们的map数据。map里面的数据大家可以自行定义。然后调用utils中的导出方法即可。

    WordUtils.exportWord(request, response, dataMap, "word", "demo.ftl");
    

    结语

    至此已经结束了,十分的好用,有疑问的话,可以评论交流。

  • 相关阅读:
    常用的Linux操作命令(一)
    本地绑定虚拟域名进行测试
    MVC定义路由
    Asp.Net请求处理机制中IsApiRuntime解析
    IOC
    数据库分页【Limt与Limt..OFFSET 】
    两个域名指向同一个网站
    WebApi服务以及跨域设置
    JS中小数的差,比较大小
    委托
  • 原文地址:https://www.cnblogs.com/jichi/p/11921541.html
Copyright © 2011-2022 走看看