一步一步带你实现java根据模板导出word循环数据

  • 之前操作EXCEL使用的是poi,用poi操作word有点复杂,且没有模板功能.放弃
  • 找到了freemarker这个工具,他可以根据word的模板生成导出的word

话不多说,跟着我来一步一步走

首先 我默认你已经有个maven或者gradle工程了

先别急着找freemarker的依赖,查查自己已有的依赖中是否已经有freemarker了.
查这里
在这里插入图片描述
有这个包就说明已经有该依赖了,不需要在导入了
在这里插入图片描述

  • 若没有该包,请导入该依赖项:


    org.freemarker
    freemarker
    2.3.28


准备工作结束了,开始创建word模板

新建一个word,做好自己的模板,附上我的模板
在这里插入图片描述

解释:
${}中的是后面要使用的变量.
我用第一个

${l.communityName}

来举例
l表示某个集合中的某个实体,communityName是他的属性,也就是这里要填入的数据
在后面的代码中会有这样的:

List communities = communityMapper.selectList(null);
Map dataMap = new HashMap();
dataMap.put("list", communities);

word设计好后,将其转为xml

对该word文件点击另存为,选择xml
在这里插入图片描述
保存好后,打开,若没有一个xml的格式,大家可以对其格式化,idea直接格式化就行了,notepad++需要下载 xml tools 插件
下载xml tools插件 请自行搜索

下来这步很重要 ,需要各位非常细心!!!

打开xml后,找到第一个变量的位置,可以通过’$'符号找
找到后,会发现,这样的代码

                        
                                
                                    
                                    
                                
                                
                                    
                                        
                                            
                                        
                                    
                                    
                                    
                                        
                                            
                                            
                                        
                                        $
                                    
                                    
                                        
                                            
                                        
                                        {
                                    
                                    
                                    
                                        
                                            
                                            
                                        
                                        l
                                    
                                    
                                        
                                            
                                        
                                        .
                                    
                                    
                                        
                                            
                                        
                                        communityName
                                    
                                    
                                    
                                        
                                            
                                        
                                        }
                                    
                                    
                                
                            

仔细观察这段代码中每个标签,你会发现,他将刚刚我们写好的变量给拆分了.
下来就对这段代码进行修改.

注意:!!!

整个代码不能有删改,否则word会出现问题~~

我们只需要将标签内的内容合并起来,变成如下所示的代码:


                                
                                    
                                    
                                
                                
                                    
                                        
                                            
                                        
                                    
                                    
                                    
                                        
                                            
                                            
                                        
                                        ${l.communityName}
                                    
                                    
                                        
                                            
                                        
                                        
                                    
                                    
                                    
                                        
                                            
                                            
                                        
                                        
                                    
                                    
                                        
                                            
                                        
                                        
                                    
                                    
                                        
                                            
                                        
                                        
                                    
                                    
                                    
                                        
                                            
                                        
                                        
                                    
                                    
                                
                            

就是把标签内的变量全部移动到第一个$后面,其他的标签滞空.

接下来进行循环设置

找到需要循环的代码
将该段填入

<#list list as l>

第一个list表示循环,第二个表示

dataMap.put("list", communities);

dataMap的key

填入的位置

直观来看,是红色框内需要循环向下补充单元格
一步一步带你实现java根据模板导出word循环数据_第1张图片
xml的代码中来看呢,

是单元格的一行结束的标签,找到他,下面就是需要循环的表格

注意!!!

<#list list as l>是需要结束标签的
结束标签:

另外,这个表格最后两个是时间格式的
如果就这样向后执行的话,会报这样的错

Tip: If you need a particular format only once, use ?string(pattern), like ?string('dd.MM.yyyy HH:mm:ss'), to specify which fields to display.

解决方法:

将这个代码
${l.completionTime}
变为
${l.completionTime?string('yyyy.MM.dd')}

处理数据为空的问题

当某个字段数据为空,且不处理时,会报错!
解决方法:
这里假设completionTime这个字段可能为空

<#if l.completionTime??>${l.completionTime?string('yyyy.MM.dd')}

加上

<#if l.completionTime??> 这个代码就行了

将word模板用java处理导出

将改好的xml后缀改为ftl

核心代码:

try {
            List communities = communityMapper.selectList(null);
            for (Community community : communities) {
                Integer state = community.getState();
                if(state==0){
                    community.setStateStr("未开始");
                }else if (state==1){
                    community.setStateStr("进行中");
                }else {
                    community.setStateStr("已完成");
                }
            }
            Map dataMap = new HashMap();
            dataMap.put("list", communities);
            //Configuration 用于读取ftl文件
            //new Configuration()构造方法内是当前依赖的版本号
            Configuration configuration = new Configuration(new Version("2.3.28"));
            configuration.setDefaultEncoding("utf-8");

            /**
             * 指定ftl文件所在目录的路径,而不是ftl文件的路径
             * setClassForTemplateLoading(a,b)
             * a代表某个类加载器,b是ftl文件所在的路径,实在a所在的路径之下
             * 网上查了下有人说可以这么理解
             * 假设a的路径是:org.ql  而ftl在目录org.ql.template下
             * 那么这里需要写为:configuration.setClassForTemplateLoading(a.getClass, "/template下");
             * 但是!!! 我试了不行
             * 所以还是将那个包路径填为空 在后面将ftl文件的相对路径写入
             */
            configuration.setClassForTemplateLoading(this.getClass(), "");

            //输出文档路径及名称
            File outFile = new File("E:/桌面/测试.doc");

            //以utf-8的编码读取ftl文件
            Template template = configuration.getTemplate("/template/老旧小.ftl", "utf-8");
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"), 10240);
            template.process(dataMap, out);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

实际上,我的ftl文件放在该类所在的同包下的template包下

结束!

效果:
一步一步带你实现java根据模板导出word循环数据_第2张图片

你可能感兴趣的:(java,java,word)