freemarker模板替换生成word
工具类
public static void createWord(Map<String,Object> dataMap, String templateName, String filePath, String fileName){
try {
//创建配置实例
Configuration configuration = new Configuration();
//设置编码
configuration.setDefaultEncoding("UTF-8"); //设置编码
//configuration.setDefaultEncoding("UTF-8"); //ftl模板文件统一放至 com.lun.template 包下面
//configuration.setClassForTemplateLoading(this.getClass(), "com.jesims.modules.freemarker.entity");
//request.getSession().getServletContext().getRealPath("/WEB-INF/ftl") 获取文件夹下面的所有模版
// configuration.setDirectoryForTemplateLoading(new File(request.getSession().getServletContext().getRealPath("/WEB-INF/ftl"))); configuration.setDirectoryForTemplateLoading(new File("C:\\Users\\18300\\Desktop\\aaa"));// 本地模板路径
//获取模板
Template template = configuration.getTemplate(templateName);
//输出文件
File outFile = new File(filePath+File.separator+fileName); //如果输出目标文件夹不存在,则创建
if (!outFile.getParentFile().exists()){
outFile.getParentFile().mkdirs();
} //将模板和数据模型合并生成文件
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8")); //生成文件
template.process(dataMap, out); //关闭流
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
调用
一对一传值
集合传值
注:集合传值中也可以返回一个集合,在调用的时候放到map中去,获取值的方式是${别称dian集合的实体类中对于的属性},但有个前提 属性的类型都得是String类型的 不然就报错
模板内增加占位符
注:占位符随意填写,自己能分清就行,没必要和后台的map保持绝对一致
一对一
集合
注:感叹号的意思是其值为null 的话 不报错,
结果如下:
1.一对一的
2.表格
在写的时候遇到了两个问题:
问题1:
本来以为这是两个表格,但其实是一个。要知道既然是一个表 那么他们的key值就不能一样
刚开始是这么写的 出现了上述问题 就是对于不上 因为第一年循环的时候 后面的值都是空的
其中的a是年份循环的下标
解决问题:
在年份循环的外面
//统计map
Map<Integer,Map> sumMap = new HashMap<>();
//记录最大值
int max= 0;
加上这两行代码主要是为了统计map;
具体代码如下:
private ArrayList<Map<String, String>> topTenInflows(String companyId) {
ArrayList<Map<String, String>> result = new ArrayList<>();
// 创建对象
DueDiligenceReport dueDiligenceReport=new DueDiligenceReport();
//设置companyId
dueDiligenceReport.setCompanyId(companyId);
List<String> years = this.towYearList(companyId);
//统计map
Map<Integer,Map> sumMap = new HashMap<>();
//记录最大值
int max= 0;
for (int a = 0; a < years.size(); a++) {
//设置年份
dueDiligenceReport.setYears(years.get(a));
//查询前十大流入
List<DueDiligenceReport> topTenInflowsList = dueDiligenceReportDao.topTenInflows(dueDiligenceReport);
// 流入总金额的初始值
BigDecimal transactionAmountSums = new BigDecimal(0);
// 判断流入集合是否有数据
if (topTenInflowsList.size()>0) {
// 计算流入金额的总和
for (DueDiligenceReport list : topTenInflowsList) {
BigDecimal transactionAmountSum = list.getTransactionAmountSum();
transactionAmountSums = transactionAmountSum.add(transactionAmountSums);
}
for (int i = 0; i < topTenInflowsList.size(); i++) {
// 循环显示标题下对应的数据
Map<String,String> map=new HashMap<>();
// 获取流入金额
BigDecimal transactionAmountSum = topTenInflowsList.get(i).getTransactionAmountSum();
// 单个除以总和 四舍五入 保留两位小数 乘以100
BigDecimal divide = transactionAmountSum.divide(transactionAmountSums, 2, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
// 给算出的百分比拼接百分号
String proportion = divide + "%";
// 关系
List<String> relationshipLabel = dueDiligenceReportDao.getRelationshipLabel(dueDiligenceReport);
if (relationshipLabel.size()>0){
topTenInflowsList.get(i).setRelationshipLabel(relationshipLabel.get(0));
}else {
topTenInflowsList.get(i).setRelationshipLabel("");
}
if (a==0){
map.put("counterpartyAccountName",topTenInflowsList.get(i).getCounterpartyAccountName());
map.put("relationshipLabel",topTenInflowsList.get(i).getRelationshipLabel());
map.put("transactionAmountSum",topTenInflowsList.get(i).getTransactionAmountSum().toString());
map.put("proportion",proportion);
if (max < i){
max = i;
}
sumMap.put(i,map);
}else {
if(sumMap.get(i)!=null){
map=sumMap.get(i);
}
if (max < i){
max = i;
}
map.put("counterpartyAccountName2",topTenInflowsList.get(i).getCounterpartyAccountName());
map.put("relationshipLabel2",topTenInflowsList.get(i).getRelationshipLabel());
map.put("transactionAmountSum2",topTenInflowsList.get(i).getTransactionAmountSum().toString());
map.put("proportion2",proportion);
sumMap.put(i,map);
} } } }
for(int i = 0 ;i<= max;i++){
result.add(sumMap.get(i));
}
return result;
}
具体效果如下:
至此,问题解决。
问题二:
需求是这种表格
刚开始看到很烦恼,因为后面是12个月 不知道该怎么写 有人可能会说直接按照表格那种方式写不行么?答案显然是不行的 因为我不可能去写12个属性,并获取每个属性对应的值。
后来发现我可以循环获取 简单点来说就是 你需要12个key和12个vaule 当然采用集合实体类那种方式显然是行不通的 于是我设置了12个key 循环设置的,vaule肯定也是循环获取的
具体代码如下:
/**
* 3.2.7工资社保统计
* */
public ArrayList<Map<String,String>> wageAndSocialSecurity(String companyId){
ArrayList<Map<String, String>> result = new ArrayList<>();
List<String> year = this.towYearList(companyId); List<String> monthLabel= new ArrayList<>();
for (int i = 1; i <=12 ; i++) {
monthLabel.add("month"+i);
} // 存放月份的集合
List<String> month= new ArrayList<>();
// 设置月份字符串
String tempYear = "";
// 将月份设置成01,02*****10,11,12的形式
for(int a = 0; a < 12; a++) {
if (a < 9) {
tempYear = "0" + (a + 1);
} else {
tempYear = ""+(a+1);
}
// 添加到存放月份的集合中
month.add(tempYear);
}
// 根据年份去遍历
for (int j = 0; j <year.size() ; j++) {
// 创建对象 并设置 companyId和年份
DueDiligenceReport dueDiligenceReport = new DueDiligenceReport();
// companyId
dueDiligenceReport.setCompanyId(companyId);
// 年份
dueDiligenceReport.setYears(year.get(j));
// 工资
List<DueDiligenceReport> wages = dueDiligenceReportDao.wages(dueDiligenceReport);
//社保
List<DueDiligenceReport> socialSecurity = dueDiligenceReportDao.socialSecurity(dueDiligenceReport);
// 判断工资集合是否为空
if (StringUtils.isEmpty(wages)){
// 如果为空 就根据月份的长度创建对象
for (int i = 0; i <month.size() ; i++) {
//创建对象
wages.add(new DueDiligenceReport());
// 将金额设置成0
wages.get(i).setTransactionAmountSum(new BigDecimal(0));
// 设置对应的月份
wages.get(i).setYears(month.get(i));
}
}else {
//定义一个set,因为set集合是有序的
Set<String> mArr = new HashSet<>();
// 将查到的所以月份放到set中
for (DueDiligenceReport w: wages) {
mArr.add(w.getYears());
}
// 循环判断月份
for (int i = 0; i <month.size() ; i++) {
//判断set中的月份 是否包含month集合中的月份
// 不包含就创建对象设置值
if (!mArr.contains(month.get(i))){
//创建对象
wages.add(i,new DueDiligenceReport());
// 将金额设置成0
wages.get(i).setTransactionAmountSum(new BigDecimal(0));
// 设置对应的月份
wages.get(i).setYears(month.get(i));
}
}
}
// 判断社保集合是否为空
if (StringUtils.isEmpty(socialSecurity)){
//如果为空 根据月份的长度 创建对象
for (int i = 0; i <month.size() ; i++) {
//创建对象
socialSecurity.add(new DueDiligenceReport());
// 将金额设置成0
socialSecurity.get(i).setTransactionAmountSum(new BigDecimal(0));
// 设置对应的月份
socialSecurity.get(i).setYears(month.get(i));
}
}else {
//定义一个set集合,因为set集合是有序的
Set<String> mArr = new HashSet<>();
// 将查到的所以月份放到set中
for (DueDiligenceReport w: socialSecurity) {
mArr.add(w.getYears());
}
// 循环判断月份
for (int i = 0; i <month.size() ; i++) {
//判断set中的月份 是否包含month集合中的月份
// 不包含就创建对象设置值
if (!mArr.contains(month.get(i))){
socialSecurity.add(i,new DueDiligenceReport());
socialSecurity.get(i).setTransactionAmountSum(new BigDecimal(0));
socialSecurity.get(i).setYears(month.get(i));
}
}
}
if (wages.size()>0){
Map<String,String> map =new HashMap<>();
map.put("year",year.get(j)+"年");
map.put("type","工资");
for (int i = 0; i < wages.size() ; i++) {
map.put(monthLabel.get(i),wages.get(i).getTransactionAmountSum().toString());
}
result.add(map);
}
if (socialSecurity.size()>0){
Map<String,String> map =new HashMap<>();
map.put("type","社保");
for (int i = 0; i < socialSecurity.size() ; i++) {
map.put(monthLabel.get(i),socialSecurity.get(i).getTransactionAmountSum().toString());
}
result.add(map);
}
}
return result;
}
具体效果如下:
freemarker模板替换生成word的更多相关文章
- 使用freemarker模板引擎生成word文档的开发步骤
1.准备模板文档,如果word文档中有表格,只保留表头和第一行数据:2.定义变量,将word文档中的变量用${var_name}替换:3.生成xml文件,将替换变量符后的word文档另存为xml文件: ...
- windows&lunix下node.js实现模板化生成word文件
最近在做了一个小程序!里面有个功能就是根据用户提交的数据,自动生成一份word文档返回给用户.我也是第一次做这功能,大概思路就是先自己弄一份word模板,后台接受小程序发过来的数据,再根据这些数据将相 ...
- velocity模板技术生成word文档
本文介绍採用velocity技术在Java中生成word文档的方法. 1.新建一个word文档,编辑内容例如以下: 2.将上述word文档另存为htm格式的文件 3.新建一个Java Project项 ...
- python基于word模板批量生成word文件
1.需要用到docxtpl库,用于操作word模板 安装:pip insatll docxtpl 处理之前的word模板 处理后的word 下面直接上代码揭开它的神秘面纱:第一步,读取excel中的内 ...
- poi读写word模板 / java生成word文档
有一word文档表格 形如: 姓名 ${name} 电话 ${tel} 从数据库读取记录替换上述变量 import java.io.FileOutputStream; import java.util ...
- C# 通过word模板动态生成Word
object oMissing = System.Reflection.Missing.Value; Word._Application oWord = new Word.Application(); ...
- [转]java 根据模板文件生成word文档
链接地址:https://blog.csdn.net/ai_0922/article/details/82773466
- FreeMarker生成Word文档
FreeMarker简介: FreeMarker是一款模板引擎:即一种基于模板和要改变的数据,并用来生成输出文本(HTML网页.电子邮件.配置文件.源代码等)的通用工具,它不是面向最终用户的,而是一个 ...
- java通过word模板生成word文档
介绍 上次公司项目需要一个生成word文档的功能,有固定的模板根据业务填充数据即可,由于从来没做过,项目也比较着急于是去网上找有没有合适的工具类,找了好几种,看到其中有freeMark模板生成比较靠谱 ...
- PoiDemo【Android将表单数据生成Word文档的方案之二(基于Poi4.0.0)】
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 使用Poi实现android中根据模板文件生成Word文档的功能.这里的模板文件是doc文件.如果模板文件是docx文件的话,请阅读 ...
随机推荐
- 疫情带火了这款APP:2600个学生一天点赞70万次
这几天,全国中小学生经历了"过山车"一样的心情. 因为疫情的不断蔓延,1月27日,教育部下发通知,2020年春季学期延期开学. 随后,教育部又提出"利用网络平台,停课 ...
- 平安保险基于 SPI 机制的 RocketMQ 定制化应用
简介:本文讲讲述平安保险为何选择 RocketMQ,以及在确定使用消息中间件后,又是如何去选择哪款消息中间件的. 作者:孙园园|平安人寿资深开发 为什么选用 RocketMQ 首先跟大家聊聊我们为什 ...
- DevOps 能力提升模型
简介: DevOps 能力反映的是技术研发响应业务变化的能力.随着组织规模的增加和业务复杂性增长,DevOps 能力会变得越来越重要.持续提升 DevOps 的能力成为技术研发的共同挑战. 编者按:本 ...
- WPF 解决 ObservableCollection 提示 Cannot change ObservableCollection during a CollectionChanged event 异常
本文告诉大家在使用 ObservableCollection 时,抛出 InvalidOperationException 异常,提示 Cannot change ObservableCollecti ...
- WPF 自己封装 Skia 差量绘制控件
使用 Skia 能做到在多个不同的平台使用相同的一套 API 绘制出相同界面效果的图片,可以将图片绘制到应用程序的渲染显示里面.在 WPF 中最稳的方法就是通过 WriteableBitmap 作为承 ...
- 优秀的 Modbus 主站(主机、客户端)仿真器、串口调试工具
目录 优秀的 Modbus 主站(主机.客户端)仿真器.串口调试工具 主要功能 软件截图 优秀的 Modbus 主站(主机.客户端)仿真器.串口调试工具 modbus master,modbus,串口 ...
- 通过Google浏览器Cookie文件获取cookie信息,80以上版本有效
public class ReadCookie { /// <summary> /// </summary> /// <param name="hostName ...
- 深入浅出玩转fPGA-读书笔记
笔记1 关于异步复位同步释放的理解 先看代码: 其中有两个always语句,把2个触发器叠加,当按下复位信号rst_n是,两个触发器都复位(清零).当rst_n释放时,重点就来了,rst_n释放的时刻 ...
- JS制作日历小事件和数码时钟--JavaScript实例集锦(初学)
运用JS的innerHTML,和for循环实现日历小部件内容和日期的转换. <!DOCTYPE html> <html> <head> <title>日 ...
- 扩展实现Unity协程的完整栈跟踪
现如今Unity中的协程(Coroutine)方案已显得老旧,Unitask等异步方案可以做到异常捕获等yield关键字处理起来很麻烦的问题, 并且Unity官方也在开发一套异步方案,但对于临时加入到 ...