java利用模板导出word文档

一.通过XDocReportFreeMarker模板引擎生成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}&nbsp;姓名:${user.username}&nbsp;${user.age}<br/>
</#list>
<#--指定字段名排序   序列名?sort_by("字段名")-->
<#list userList?sort_by("age") as user>
    编号:${user.id}&nbsp;姓名:${user.username}&nbsp;${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博客

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Java可以使用第三方工具类库Hutool或者fr.opensagres.xdocreport来根据Word模板导出Word文档docx。其中,使用Hutool可以通过以下步骤实现: 1. 引入Hutool依赖: ``` <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.10</version> </dependency> ``` 2. 加载Word模板文件: ``` DocxWriter writer = new DocxWriter("template.docx"); ``` 3. 替换模板中的变量: ``` writer.replace("name", "张三"); ``` 4. 保存并关闭文件: ``` writer.flush(new FileOutputStream("output.docx")).close(); ``` 而使用fr.opensagres.xdocreport可以通过以下步骤实现: 1. 引入相关依赖: ``` <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> ``` 2. 加载Word模板文件: ``` InputStream in = new FileInputStream(new File("template.docx"));IXDocReport report = XDocReportRegistry.getRegistry().loadReport(in, TemplateEngineKind.Freemarker); ``` 3. 创建数据模型并填充数据: ``` IContext context = report.createContext(); context.put("name", "张三"); ``` 4. 生成Word文档并保存: ``` OutputStream out = new FileOutputStream(new File("output.docx")); report.process(context, out); out.close(); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lyt5701

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值