最近接了个需求,大致是生成一个excel文件,这个文件里面部分内容是动态填充的,并且有些表格还是根据内容的数据大小进行颜色背景填充。看到excel首先想到的是poi,业内还有Easy Excel(阿里开源的)框架,不过笔者先前刚搞了freemarker,就考虑使用freemarker来解决这个问题了,使用freemarker有几个步骤,首先要制作模板,编写ftl语言代码,然后再java代码中生成填充变量,直接生成文件即可。下面给一个类似的需求,要求生成一个excel,里面包含某用户的体检信息如下图,要求体重超过80kg表格背景色变为橙色,心率超过100表格背景色为红色。
样例展示
下面介绍步骤:
1.制作excel模板,先造一个变量填充的模板,先建一个如下图的xlsx文件;
2.将该文件另存为一个xml文件;
3.解读分析xml文件,可以用notepad 打开;找到下xml代码的位置,身高我们用了橙色背景,此处样式id是s52,体重用了红色背景,此处样式id是s53,序号和心率没有背景色样式id是s51,因此我们猜测到这个样式在其他处有定义颜色(事实也是如此);
注意:样式id不一定和我的一样,所以要改为自己的id。
<#--样式id引用-->
<Row ss:StyleID="s50">
<Cell ss:StyleID="s51">
<Data ss:Type="String">序号</Data>
</Cell>
<#--橙色s52-->
<Cell ss:StyleID="s52">
<Data ss:Type="String">身高</Data>
</Cell>
<#--红色s53-->
<Cell ss:StyleID="s53">
<Data ss:Type="String">体重</Data>
</Cell>
<Cell ss:StyleID="s51">
<Data ss:Type="String">心率</Data>
</Cell>
</Row>
<#--样式id定义-->
<Style ss:ID="s51">
<Alignment ss:Horizontal="Center" ss:Vertical="Center"/>
</Style>
<Style ss:ID="s52">
<Alignment ss:Horizontal="Center" ss:Vertical="Center"/>
<Interior ss:Color="#FFC000" ss:Pattern="Solid"/>
</Style>
<Style ss:ID="s53">
<Alignment ss:Horizontal="Center" ss:Vertical="Center"/>
<Interior ss:Color="#FF0000" ss:Pattern="Solid"/>
</Style>
4.编写ftl文件:我们可以先复制一份xml文件避免改错。首先我们将表头都改为无背景色,然后将下面变量写ftl的判断,符合条件为有颜色,不符合无颜色填充;同时为了能分辨出来条件判断有效,我们下面多做几行数据,即为一个list,恰好可以学习下ftl文件里list遍历;
<#--样式id引用, 表头都改为无背景色s51-->
<Row ss:StyleID="s50">
<Cell ss:StyleID="s51">
<Data ss:Type="String">序号</Data>
</Cell>
<Cell ss:StyleID="s51">
<Data ss:Type="String">身高</Data>
</Cell>
<Cell ss:StyleID="s51">
<Data ss:Type="String">体重</Data>
</Cell>
<Cell ss:StyleID="s51">
<Data ss:Type="String">心率</Data>
</Cell>
</Row>
<#--list判空-->
<#if list?? && (list?size>0)>
<#--遍历list-->
<#list list as item>
<Row ss:StyleID="s50">
<Cell ss:StyleID="s51">
<Data ss:Type="number">${item_index 1}</Data>
</Cell>
<Cell ss:StyleID="s51">
<Data ss:Type="String">${item.high}</Data>
</Cell>
<#--string声明为number-->
<#assign weightNum = item.weight?number>
<#if weightNum <= 80 >
<#-- 小于80无颜色-->
<Cell ss:StyleID="s51">
<Data ss:Type="String">${item.weight}</Data>
</Cell>
<#else >
<#-- 大于80橙色-->
<Cell ss:StyleID="s52">
<Data ss:Type="String">${item.weight}</Data>
</Cell>
</#if>
<#assign heartNum = item.heart?number>
<#if heartNum <= 100 >
<#-- 小于100无颜色-->
<Cell ss:StyleID="s51">
<Data ss:Type="String">${item.heart}</Data>
</Cell>
<#else >
<#-- 大于100红色-->
<Cell ss:StyleID="s53">
<Data ss:Type="String">${item.heart}</Data>
</Cell>
</#if>
</Row>
</#list>
</#if>
5.将上述复制修改后的xml文件另存为ftl后缀文件;
6.编写java代码,输出文档,代码如下
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class User {
private Integer high;
private String weight;
private String heart;
}
import com.google.common.collect.Lists;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.commons.codec.CharEncoding;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
public class FTLDemo {
public static void main(String[] args) {
HashMap<String, Object> param = new HashMap<>();
param.put("name","周星星");
param.put("time",new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date()));
User user1 = User.builder().high(180).weight("120").heart("180").build();
User user2 = User.builder().high(168).weight("50").heart("60").build();
List<User> users = Lists.newArrayList(user1, user2);
param.put("list",users);
// todo 此处模板放置路径和生成文件路径修改成自己的
crateFile(param, "C:\\体检模板.ftl","C:\\genetate\\generate.xlsx");
}
/**
* 将数据渲染到ftl生成文件
* @param dataMap 最外层数据
* @param templatePath ftl绝对路径
* @param targetFile 生成文件文档绝对路径
*/
public static void crateFile(Map<String, Object> dataMap, String templatePath, String targetFile){
// 获取ftl的文件路径
String directoryForTemplate = templatePath.substring(0,templatePath.lastIndexOf(File.separator) 1);
String templateName = templatePath.substring(templatePath.lastIndexOf(File.separator) 1);
try (FileOutputStream out = new FileOutputStream(targetFile);
Writer writer = new BufferedWriter(new OutputStreamWriter(out, CharEncoding.UTF_8))){
Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
configuration.setDefaultEncoding(CharEncoding.UTF_8);
configuration.setDirectoryForTemplateLoading(new File(directoryForTemplate));
//加载模板
Template template = configuration.getTemplate(templateName);
//渲染模板
template.process(dataMap, writer);
} catch (Exception e){
e.printStackTrace();
}
}
}
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</dependency>
即可生成符合条件的文件。
大家可以自己去试试,ftl里用到了不少语法,如内置的index索引加1作为序号,list的判空以及遍历,还有字符串转数字if判断等。总之这种方法就是需要分析要生成的文件,使用ftl语言修改模板,最后给出填充数据代码一键生成,还是比较方便的。希望这篇文章能给你一些灵感或启发,欢迎评论,都会回复。感谢观看!
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved