• SpringBoot整合Freemarker导出word文档表格


    freemarker模板里面的template.process()方法里传入的第一个参数Object类型,如果是一个实体类对象在模板上怎么进行渲染,将实体类的值取出

    freemarker会调用ObjectWrapper对传入的对象进行warp,具体类型在代码里面用instanceof进行判断。一般类型的实体对象,使用BeanModel进行解析,通过invoke getter方法取到对应的值。

    所谓的object类型其实它并不是指所有类型,必须是Collection类型的

    1、pom.xml

    在pom.xml文件中添加freemarker的依赖包

    	<dependency>
    		<groupId>org.springframework.bootgroupId>
    		<artifactId>spring-boot-starter-freemarkerartifactId>
    	dependency>
    
    • 1
    • 2
    • 3
    • 4

    2、制作.ftl模板

    2.1 创建word模板

    创建word文档,制定表格。其中需要根据实际替换的元素用${...}书写。
    主要包含几种情况:
    1)正常需要替换的元素
    2)“判断a”、“判断b”演示需要判断是否显示整行
    3)“循环合并行”演示没有内容右边为空,有多条数据右边分行显示,左边自动合并。
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    2.2 另存为xml格式,进行简单处理

    将word文档另存为xml格式。

    1)首先找到之前写的替换元素,确保${…}和单词是连在一起的,如果不在一起,就把中间的删掉,处理到一起。
    在这里插入图片描述
    2)我习惯把xml文件按行给他格式化好
    表示表格
    表示行
    表示列
    在这里插入图片描述

    2.3 创建实体类

    public class DemoWordDetail {
    
        private String title;
        private String type;
        private String time;
        private String aaa;
        private int isShowA=1;//控制行显示
        private String bbb;
        private int isShowB=1;//控制行显示
        private List<CyclicModel> cyclics;//合并数据
    
    }
    
    public class CyclicModel {
    
        private String cyclic;
        /**
         * 合并标志;第一行"",后边行""
         */
        private String merge;
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    2.4处理xml文件

    1)对于正常需要替换的元素可以不用做任何操作
    2)“判断a”、“判断b”演示需要判断是否显示整行,定义字段isShowA、isShowB来控制

    在行的外层添加<#if>标签,如果isShowA==1则显示这一行,如果为其他值则不显示。

    在这里插入图片描述
    3)“循环合并行”处理

    采用<#if>显示处理数据<#else>显示空白,把${…}删掉
    c y c l i c s . m e r g e 处理第一列合并问题;将之前的 {cyclics.merge}处理第一列合并问题; 将之前的 cyclics.merge处理第一列合并问题;将之前的{cyclic}替换成${cyclics.cyclic}

    在这里插入图片描述

    2.5修改后缀为ftl

    3、导出word方法

    3.1将demo.ftl放入resources/template

    在这里插入图片描述

    3.2通用的word导出方法

    @Service
    public class WordService {
    
        public void exportWord(HttpServletRequest request, HttpServletResponse response, String fileName , String templeteName, Object dataModel){
    
            Configuration configuration=new Configuration();
            configuration.setDefaultEncoding("utf-8");
            configuration.setEncoding(Locale.getDefault(),"utf-8");
    
            try {
    
                configuration.setClassicCompatible(true);//处理dataModel中如果为null的情况
    	            
           		//既能保证本地运行找得到模板文件,又能保证jar包运行能找到得到模板文件
                configuration.setClassForTemplateLoading(this.getClass(),"/template");
                configuration.setTemplateLoader(new ClassTemplateLoader(this.getClass(),"/template"));
                //            configuration.setDirectoryForTemplateLoading(new File(CommonUtil.getTempletePath()+"/template/"));
                Template t=configuration.getTemplate(templeteName,"utf-8");
    
                response.setContentType("application/msword; charset=UTF-8");// application/x-download
                response.setHeader("Content-Disposition", "attachment; "
                        + encodeFileName(request, fileName+".doc"));
    
                OutputStream outputStream = response.getOutputStream();
                Writer out=new OutputStreamWriter(outputStream);
    			// 重要方法 <-----------------
                t.process(dataModel, out);
                outputStream.close();
                out.close();
    
            } catch (IOException | TemplateException e) {
                e.printStackTrace();
            }
    
        }
        
    	public static String encodeFileName(HttpServletRequest request, String fileName)
                throws UnsupportedEncodingException
        {
    
            String new_filename = URLEncoder.encode(fileName, "UTF8").replaceAll("\\+", "%20");
    
            String agent = request.getHeader("USER-AGENT").toLowerCase();
            if (null != agent && -1 != agent.indexOf("msie"))
            {
                /**
                 * IE浏览器,只能采用URLEncoder编码
                 */
                return "filename=\"" + new_filename +"\"";
            }else if (null != agent && -1 != agent.indexOf("applewebkit")){
                /**
                 * Chrome浏览器,只能采用ISO编码的中文输出
                 */
                return "filename=\"" + new String(fileName.getBytes("UTF-8"),"ISO8859-1") +"\"";
            } else if (null != agent && -1 != agent.indexOf("opera")){
                /**
                 * Opera浏览器只可以使用filename*的中文输出
                 * RFC2231规定的标准
                 */
                return "filename*=" + new_filename ;
            }else if (null != agent && -1 != agent.indexOf("safari")){
                /**
                 * Safani浏览器,只能采用iso编码的中文输出
                 */
                return "filename=\"" + new String(fileName.getBytes("UTF-8"),"ISO8859-1") +"\"";
            }else if (null != agent && -1 != agent.indexOf("firefox"))
            {
                /**
                 * Firfox浏览器,可以使用filename*的中文输出
                 * RFC2231规定的标准
                 */
                return "filename*=" + new_filename ;
            } else
            {
                return "filename=\"" + new_filename +"\"";
            }
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79

    3.3执行导出方法

            DemoWordDetail demoWordDetail=new DemoWordDetail();
            //一系列处理
            wordService.exportWord(request, response, "title", "demo.ftl", demoWordDetail);
    
    • 1
    • 2
    • 3

    3.4测试效果

    判断a、判断b均显示,循环合并行多条数据

    img

    判断a这行不显示,循环合并行无数据

    img

    4、遇到的坑

    1)导出对象字段有为null时,报错,加上“configuration.setClassicCompatible(true);2)idea运行能正常导出,jar运行不能找到模板,代码中给出了解决
    3)cmd运行jar,能正常导出word,但是打开错误。
    	经过测试发现导出word文档乱码,发现是是cmd默认编码问题,在cmd执行时加上:
    	start javaw -Dfile.encoding=utf-8 -jar xxx.jar
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    网络安全-态势感知
    王道考研--》顺序表课后习题C语言代码实现(冲刺)
    linux 基础知识3---上下文
    java-php-net-python-4餐饮管理系统.计算机毕业设计程序
    Windows安装nginx
    OpenCV实战(29)——视频对象追踪
    Flutter笔记:桌面应用 窗口定制库 bitsdojo_window
    EN 13969防水用柔性薄板.沥青防潮薄板—CE认证
    安卓调用onnx模型并计算
    供应链管理(SCM):界面设计全面扫盲,得供应链者得天下
  • 原文地址:https://blog.csdn.net/qq_43842093/article/details/126475806