一.通过XDocReport和FreeMarker模板引擎生成Word文档的方法。
1.依赖:
</dependency> <dependency> <groupId>fr.opensagres.xdocreport</groupId> <artifactId>fr.opensagres.xdocreport.document.docx</artifactId> <version>2.0.2</version> </dependency> <dependency> <groupId>fr.opensagres.xdocreport</groupId> <artifactId>fr.opensagres.xdocreport.template.freemarker</artifactId> <version>2.0.2</version> </dependency> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.30</version> </dependency>
二.数据类型
1.普通数据
2.表格
三.实现
3.1编辑模板:选中区域,按ctrl+F9,右键编辑域,选择邮件合并,输入参数
参数后面加“!”可以避免参数为null而报错,
3.2.代码:
//获取Word模板,模板存放路径在项目的resources目录下 InputStream ins = this.getClass().getResourceAsStream("/RE22-08.docx"); //注册xdocreport实例并加载FreeMarker模板引擎 IXDocReport report = XDocReportRegistry.getRegistry().loadReport(ins,TemplateEngineKind.Freemarker); //创建xdocreport上下文对象 IContext context = report.createContext(); //往模板里填充数据(普通数据) context.put("projectFile",itemPlanVo.getNumber()); context.put("projectName",itemPlanVo.getProjectName()); context.put("startTime",Handler.dateToString1(itemPlanVo.getStartTime())); context.put("endTime",Handler.dateToString1(itemPlanVo.getEndTime())); context.put("sumDay",itemPlanVo.getSumDay()); context.put("step1StartTime",Handler.dateToString2(itemPlanVo.getStep1StartTime())); context.put("step1EndTime",Handler.dateToString2(itemPlanVo.getStep1EndTime())); context.put("step2StartTime",Handler.dateToString2(itemPlanVo.getStep2StartTime())); context.put("step2EndTime",Handler.dateToString2(itemPlanVo.getStep2EndTime())); context.put("step3StartTime",Handler.dateToString2(itemPlanVo.getStep3StartTime())); context.put("step3EndTime",Handler.dateToString2(itemPlanVo.getStep3EndTime())); context.put("step4StartTime",Handler.dateToString2(itemPlanVo.getStep4StartTime())); context.put("step4EndTime",Handler.dateToString2(itemPlanVo.getStep4EndTime())); context.put("step5StartTime",Handler.dateToString2(itemPlanVo.getStep5StartTime())); context.put("step5EndTime",Handler.dateToString2(itemPlanVo.getStep5EndTime())); context.put("step6StartTime",Handler.dateToString2(itemPlanVo.getStep6StartTime())); context.put("step6EndTime",Handler.dateToString2(itemPlanVo.getStep6EndTime())); context.put("step7StartTime",Handler.dateToString2(itemPlanVo.getStep7StartTime())); context.put("step7EndTime",Handler.dateToString2(itemPlanVo.getStep7EndTime())); context.put("step8StartTime",Handler.dateToString2(itemPlanVo.getStep8StartTime())); context.put("step8EndTime",Handler.dateToString2(itemPlanVo.getStep8EndTime())); context.put("step9StartTime",Handler.dateToString2(itemPlanVo.getStep9StartTime())); context.put("step9EndTime",Handler.dateToString2(itemPlanVo.getStep9EndTime())); context.put("step10StartTime",Handler.dateToString2(itemPlanVo.getStep10StartTime())); context.put("step10EndTime",Handler.dateToString2(itemPlanVo.getStep10EndTime())); context.put("step11StartTime",Handler.dateToString2(itemPlanVo.getStep11StartTime())); context.put("step11EndTime",Handler.dateToString2(itemPlanVo.getStep11EndTime())); context.put("step12StartTime",Handler.dateToString2(itemPlanVo.getStep12StartTime())); context.put("step12EndTime",Handler.dateToString2(itemPlanVo.getStep12EndTime())); context.put("step13StartTime",Handler.dateToString2(itemPlanVo.getStep13StartTime())); context.put("step13EndTime",Handler.dateToString2(itemPlanVo.getStep13EndTime())); context.put("step1Hour",itemPlanVo.getStep1Hour()); context.put("step2Hour",itemPlanVo.getStep2Hour()); context.put("step3Hour",itemPlanVo.getStep3Hour()); context.put("step4Hour",itemPlanVo.getStep4Hour()); context.put("step5Hour",itemPlanVo.getStep5Hour()); context.put("step6Hour",itemPlanVo.getStep6Hour()); context.put("step7Hour",itemPlanVo.getStep7Hour()); context.put("step8Hour",itemPlanVo.getStep8Hour()); context.put("step9Hour",itemPlanVo.getStep9Hour()); context.put("step10Hour",itemPlanVo.getStep10Hour()); context.put("step11Hour",itemPlanVo.getStep11Hour()); context.put("step12Hour",itemPlanVo.getStep12Hour()); context.put("step13Hour",itemPlanVo.getStep13Hour()); context.put("sumHour1",itemPlanVo.getSumHour1()); context.put("sumHour",itemPlanVo.getSumHour());
往模板里填充数据(表格) int j = 0; List<ProjectTestItemsRelationEntity> projectTestItemsRelationEntities = projectTestItemsRelationRepository.findAllByFileNumber(fileNumber); ArrayList<TestItemDocx> testItemDocxes = new ArrayList<>(); for (ProjectTestItemsRelationEntity entity : projectTestItemsRelationEntities) { TestItemDocx testItemDocx = new TestItemDocx(); BeanUtils.copyProperties(entity,testItemDocx); testItemDocx.setIndex(++j); testItemDocxes.add(testItemDocx); } context.put("testItemDocx", testItemDocxes); FieldsMetadata fm = report.createFieldsMetadata(); //Word模板中的表格数据对应的集合类型 fm.load("roleAndDutyDocx", RoleAndDutyDocx.class,true); fm.load("testItemDocx", TestItemDocx.class, true); fm.load("hardWareDocx", HardWareDocx.class, true); fm.load("softWareDocx", SoftWareDocx.class, true); //输出到本地目录 FileOutputStream out = new FileOutputStream(new File("D:\\Desktop\\RE22-08 测试实施方案.docx")); report.process(context, out);
3.3展示
四.freemaker不同数据类型取值方法
1.数据类型
布尔型:等价于java的Boolean类型,不同的是不能直接输出,可转化为字符串输出
日期型:等价于java的Date类型,不同的是不能直接输出,需要转换为字符串再输出
数值型:等价于java中int,float,double等数值类型 (有三种显示形式:数值型(默认)、货币型、百分比型)
字符型:等价于java中的字符串,有很多内置函数
sequence类型:等价于java中的数组,list,set等集合类型
hash类型:等价于java中的Map类型
2.取值
1.布尔类型
在freeMarker页面中不能直接输出,如果要输出需要转换成字符串
方式一:?c
方式二:?string 或 ?string(‘为true时显示的内容’,’为false时显示的内容’)
方式三:?then(‘为true时显示的内容’,’为false时显示的内容’)
–>Boolean flage = true
${flag?c}
${flag?string}
${flag?string(‘yes’,’no’)}
${flag?string(‘喜欢’,’不喜欢’)}
${flag?then(‘yes’,’no’)}
${flag?then(‘喜欢’,’不喜欢’)}
2.日期类型
在freemarker中日期类型不能直接输出:如果输出要先转成日期型或字符串
1.年月日 ?date
2.时分秒 ?time
3.年月日时分秒 ?datetime
4.指定格式 ?string (”自定义格式”)
y: 年 M:月 d:日
H: 时 m:分 s:秒
–>
<#– 输出日期格式 –>
${createDate?date}
<#– 输出时间格式 –>
${createDate?time}
<#– 输出日期时间格式 –>
${createDate?datetime}
<#– 输出格式化日期格式 –>
${createDate?string(“yyyy年MM月dd日 HH:mm:ss”)}
3.数值类型
在freemarker中数值类型可以直接输出;
1.转字符串
普通字符串 ?c
货币型字符串 ?string.currency
百分比型字符串 ?string.percent
2.保留浮点型数值指定小数位(#表示一个小数位)
?string[“0.##”
–>
<#– 直接输出数值型 –>
${age}
${salary}
${avg}
<#– 将数值转换成字符串类型 –>
${salary?c}
<#– 将数值转化成货币类型字符串 –>
${salary?string.currency}
<#– 将数值转化成百分比类型的字符串 –>
${avg?string.percent}
<#– 将浮点型的数值转换成指定小数位输出(四舍五入) –>
${avg?string[“0.##”]}
4.字符串类型
在freemarker中字符串类型可以直接输出:
1.截取字符串(左闭右开)?substring(start,end)
2.首字母小写输出 ?uncap_first
3.首字母大写输出 ?cap_first
4.字母转小写输出 ?lower_case
5.字母转大写输出 ?upper_case
6.获取字符串长度 ?length
7.是否以指定字符开头(boolean 类型) ?starts_with(“xx”)?string
8.是否以指定字符结尾(boolean 类型) ?ends_with(“xx”)?string
9.获取指定字符的索引 ?index_of(“xx”)
10.去除字符串前后空格 ?trim
11.替换指定字符串 ?replace(“xx”,”xx”)
–>
${msg} — ${msg2}
${msg?string} — ${msg2?string}
<#–1.截取字符串(左闭右开)?substring(start,end)–>
${msg?substring(0,2)}
<#–2.首字母小写输出 ?uncap_first–>
${msg?uncap_first}
<#–3.首字母大写输出 ?cap_first–>
${msg?cap_first}
<#–4.字母转小写输出 ?lower_case–>
${msg?lower_case}
<#–5.字母转大写输出 ?upper_case–>
${msg2?upper_case}
<#–6.获取字符串长度 ?length–>
${msg?length}<
<#–7.是否以指定字符开头(boolean 类型) ?starts_with(“xx”)?string–>
${msg?starts_with(“a”)?string}
<#–8.是否以指定字符结尾(boolean 类型) ?ends_with(“xx”)?string–>
${msg?ends_with(“o”)?string}
<#–9.获取指定字符的索引 ?index_of(“xx”)–>
${msg2?index_of(“m”)}
<#–10.去除字符串前后空格 ?trim–>
${msg2?trim}
<#–11.替换指定字符串 ?replace(“xx”,”xx”)–>
${msg?replace(“he”,”we”)}
5.空值类型
<#–
字符串空值情况处理:
FreeMarker的变量必须赋值,否则就会抛出异常。而对于FreeMarker来说,null值和不存在的变量是完全一样的,因为FreeMarker无法理解null值。
FreeMarker提供两个运算符来避免空值:
①!:指定缺失变量的默认值
${value!}:如果value值为空,则默认值是空字符串
${value!”默认值”}:如果value值为空,则默认值是字符串“默认值”
②??:判断变量是否存在
如果变量存在,返回true,否则返回false
${(value??)?string}
–>
<#– 如果值不存在,直接输出会报错 –>
<#– ${bb}–>
<#– 值为null的数据 –>
<#–${str1}<br/>–>
<#– 值为空字符串的数据 –>
${str2}<br/>
<#– 使用!,当值不存在时,默认显示空字符串 –>
${str!}<br/>
<#– 使用!”xx”,当值不存在时,默认显示指定字符串 –>
${str!”这是一个默认值”}<br/>
<#– 使用??,判断字符串是否为空;返回布尔类型,如果想要输出,需要将布尔类型转换成字符串–>
${(str??)?string}
6.sequence类型
<#–
FreeMarker 数据类型
序列类型 (数组、List、Set)
通过list指令输出序列
<#list 序列名 as 元素名>
${元素名}
</#list>
获取序列的长度 ${序列名?size}
获取序列元素的下标 ${元素名?index}
获取第一个元素 ${序列名?first}
获取最后一个元素 ${序列名?last}
倒序输出 序列名?reverse
升序输出 序列名?sort
降序输出 序列名?sort?reverse
指定字段名排序 序列名?sort_by(“字段名”)
注:一般是JavaBean集合,对应的字段名需要提供get方法
–>
<#– 数组操作 –>
<#list stars as star>
下标:${star?index}-姓名:${star}<br/>
</#list>
获取序列的长度: ${stars?size}<br/>
获取第一个元素: ${stars?first}<br/>
获取最后一个元素: ${stars?last}<br/><#– List操作 –>
<#list cityList as city>
${city}-
</#list>
<br/>
<#–倒序输出 序列名?reverse–>
<#list cityList?reverse as city>
${city}-
</#list>
<br/>
<#–升序输出 序列名?sort–>
<#list cityList?sort as city>
${city}-
</#list>
<br/>
<#–降序输出 序列名?sort?reverse–>
<#list cityList?sort?reverse as city>
${city}-
</#list>
<br/>
<#list userList as user>
编号:${user.id} 姓名:${user.username} ${user.age}<br/>
</#list>
<#–指定字段名排序 序列名?sort_by(“字段名”)–>
<#list userList?sort_by(“age”) as user>
编号:${user.id} 姓名:${user.username} ${user.age}<br/>
</#list>
7.hash类型
<#–
数据类型:hash类型
key遍历输出
<#list hash?keys as key>
${key} — ${hash[key]}
</#list>
value遍历输出
<#list hash?values as value>
${value}
</#list>
–>
<#– key遍历输出 –>
<#list cityMap?keys as key>
${key} — ${cityMap[key]} <br/>
</#list>
<#–value遍历输出–>
<#list cityMap?values as value>
${value}<br/>
</#list>
参考:Java导出Word文档的几种方法_Archie_java的博客-CSDN博客
Freemarker简单概述及其数据类型的简单学习—快速入门(一)_freemark 判断日期类型_@夜魅的博客-CSDN博客
版权声明:本文为博主作者:lyt5701原创文章,版权归属原作者,如果侵权,请联系我们删除!
原文链接:https://blog.csdn.net/qq_41786090/article/details/132317719