JAVA poi-tl 制作word模板 表格数据行循环 带有复选框勾选的表格

不想敲代码的洋仔 2024-07-27 10:05:02 阅读 79

文章目录

@[TOC](文章目录)

前言一、需要的依赖二、制作word模板1. 原word表单文件2. 制作word模板3. 最后通过代码生成的word数据表格

三、示例代码1.测试工具类2. 表单对象3. 表单行数据循环对象

四、参考或相关文档

前言

        java项目实际开发中经常会遇到制作word表单且表格数据行循环功能,甚至带有复选框勾选功能,本文简单介绍如何制作模板以及使用poi-tl生成word。


<code>提示:以下是本篇文章正文内容,下面案例可供参考

一、需要的依赖

如果只用到word那么需要导入的依赖如下(本案例只需要如下2个依赖生成word):

<dependency>

<groupId>cn.hutool</groupId>

<artifactId>hutool-all</artifactId>

<version>5.8.0.M2</version>

</dependency>

<dependency>

<groupId>com.deepoove</groupId>

<artifactId>poi-tl</artifactId>

<version>1.9.1</version>

</dependency>

正常企业项目还有excel等其他office工具,所以需要导入其他依赖:

<dependency>

<groupId>org.apache.poi</groupId>

<artifactId>poi-scratchpad</artifactId>

<version>4.1.2</version>

</dependency>

<dependency>

<groupId>org.apache.poi</groupId>

<artifactId>ooxml-schemas</artifactId>

<version>1.4</version>

</dependency>

<dependency>

<groupId>org.apache.poi</groupId>

<artifactId>poi</artifactId>

<version>4.1.2</version>

</dependency>

<dependency>

<groupId>org.apache.poi</groupId>

<artifactId>poi-ooxml</artifactId>

<version>4.1.2</version>

</dependency>

<dependency>

<groupId>org.apache.poi</groupId>

<artifactId>poi-ooxml-schemas</artifactId>

<version>4.1.2</version>

</dependency>

注意:一定要看清楚导入的poi-tl的版本,不同版本对应的jdk,Apache POI版本都不一样,且代码中需要调用的函数也可能会不一样。

poi-tl不同版本相关文档介绍

二、制作word模板

以下都是示例模板

1. 原word表单文件

在这里插入图片描述

2. 制作word模板

模板文件链接:https://pan.baidu.com/s/1Lvo43xkYp6ec2RonHpEeKA

提取码:0617

在这里插入图片描述

在这里插入图片描述

3. 最后通过代码生成的word数据表格

在这里插入图片描述


三、示例代码

1.测试工具类

<code>import cn.hutool.core.bean.BeanUtil;

import com.deepoove.poi.XWPFTemplate;

import com.deepoove.poi.config.Configure;

import com.deepoove.poi.config.ConfigureBuilder;

import com.deepoove.poi.policy.HackLoopTableRenderPolicy;

import com.deepoove.poi.util.PoitlIOUtils;

import com.haiyang.Entity.DataForm;

import com.haiyang.Entity.VoteInfo;

import lombok.extern.slf4j.Slf4j;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.boot.test.context.SpringBootTest;

import org.springframework.core.io.ClassPathResource;

import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import org.springframework.web.context.request.RequestContextHolder;

import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletResponse;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.text.SimpleDateFormat;

import java.util.ArrayList;

import java.util.Date;

import java.util.List;

import java.util.Map;

@SpringBootTest

@RunWith(SpringJUnit4ClassRunner.class)

@Slf4j

public class GenerateWordTest {

@Test

public void generateWordForm() {

/**

*

* 若是调用生成word的方法参数不能带response 可以通过request上下文获取

*/

//获取response对象

ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

HttpServletResponse response = attributes.getResponse();

/**

* 1. 获取所有投票人的列表数据

* 此处使用测试数据,实际项目中需要自己从数据库查询

* */

List<VoteInfo> infoList = new ArrayList<VoteInfo>() { {

add(new VoteInfo("张三", "1", "没有意见"));

add(new VoteInfo("李四", "1", "同意"));

add(new VoteInfo("王五", "3", "拒绝,不同意"));

add(new VoteInfo("宋小宝", "4", "我回避!不做任何评价"));

add(new VoteInfo("海燕", "2", "我认为需要续议,日后再重新讨论"));

}};

StringBuffer allOpinion = new StringBuffer();

for (VoteInfo info : infoList) {

//拼接所有投票人的意见 并换行

allOpinion.append(info.getVoterName() + ":" + info.getVoteOpinion() + "\n");

}

/**

* 2. 获取并设置表单数据 此处为测试数据 meetingType和passFlag默认设置为1

* 复选框 meetingType 会议类型 1、股东会 2、董事会 3、合伙人会 4、其他

* 复选框 passFlag 是否通过 1、同意 2、续议 3、拒绝

* */

DataForm dataForm = new DataForm("程序猿公司", "2024", "1", "1",

"程序猿股东大会-如何走向人生巅峰迎娶白富美", "1", "1",

allOpinion.toString(), "程序猿", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));

/**

* 3. 数据map 用于渲染word表单的数据 将表单数据对象存入map中

*/

Map<String, Object> dataMap = BeanUtil.beanToMap(dataForm);

//需要循环的表单数据

dataMap.put("dataTable", infoList);

/**

* 4. Configure类是该库中的一个配置类,其作用是提供了一些全局的配置选项

* (1) useSpringEL() 开启El表达式{ { }} word模板中的数据就以这个表达式传递数据 例如:{ {companyName}};也可以调用buildGramer("${", "}") 可以修改模板为${}

* (2) bind() 绑定标记需要循环的数据

* (3) 实现表格行循环的策略 HackLoopTableRenderPolicy 不同poi版本实现行循环的策略不一样;当前案例是poi-tl 1.9.1版本

* 1.9.x版本:HackLoopTableRenderPolicy 1.10.x以后的版本:LoopRowTableRenderPolicy

*

*/

ConfigureBuilder configureBuilder = Configure.builder().useSpringEL().bind("dataTable", new HackLoopTableRenderPolicy());

Configure config = configureBuilder.build();

InputStream is = null;

try {

/**

* 5. word模板渲染数据 wordForm.docx为模板,本案例放在了项目根目录的wordTemplates下

*/

is = new ClassPathResource("wordTemplates/wordForm.docx").getInputStream();

XWPFTemplate template = XWPFTemplate.compile(is, config).render(dataMap);

/** 6. 根据模板生成word文件的指定路径 */

String filePath = "D:/note/程序猿会议意见反馈表.docx";

//生成 意见反馈表word 到指定路径

OutputStream out = new FileOutputStream(filePath);

/** 若是直接访问下载打开 可以通过如下方式实现 不需要设置文件路径

* String fileName = URLEncodeUtil.encode("程序猿会议意见反馈表");

* response.setContentType("application/octet-stream;charset=utf-8");

* response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".docx");code>

* OutputStream out = response.getOutputStream();

*/

/**

* 7. 文件输出

*/

template.writeAndClose(out);

out.flush();

PoitlIOUtils.closeQuietlyMulti(template, out);

} catch (IOException e) {

log.error("生成意见反馈表失败!", e);

} finally {

if (null != is) {

try {

//最后别忘记了关闭流

is.close();

} catch (IOException e) {

log.error("关闭流失败!", e);

}

}

}

}

}

2. 表单对象

/**

* word数据表单

*/

public class DataForm {

/** 公司名称 */

private String companyName;

/** 时间-年 */

private String year;

/** 时间-月 */

private String month;

/** 时间-日 */

private String day;

/** 会议主题 */

private String meetingTheme;

/** 会议类型 1、股东会 2、董事会 3、合伙人会 4、其他 */

private String meetingType;

/** 是否通过 1、同意 2、续议 3、拒绝 */

private String passFlag;

/** 汇总意见 所有投票人的意见汇总 */

private String allOpinion;

/** 签名 */

private String sign;

/** 签名日期 yyyy-MM-dd */

private String signDate;

public DataForm() {

}

public DataForm(String companyName, String year, String month, String day, String meetingTheme, String meetingType, String passFlag, String allOpinion, String sign, String signDate) {

this.companyName = companyName;

this.year = year;

this.month = month;

this.day = day;

this.meetingTheme = meetingTheme;

this.meetingType = meetingType;

this.passFlag = passFlag;

this.allOpinion = allOpinion;

this.sign = sign;

this.signDate = signDate;

}

public String getCompanyName() {

return companyName;

}

public void setCompanyName(String companyName) {

this.companyName = companyName;

}

public String getYear() {

return year;

}

public void setYear(String year) {

this.year = year;

}

public String getMonth() {

return month;

}

public void setMonth(String month) {

this.month = month;

}

public String getDay() {

return day;

}

public void setDay(String day) {

this.day = day;

}

public String getMeetingTheme() {

return meetingTheme;

}

public void setMeetingTheme(String meetingTheme) {

this.meetingTheme = meetingTheme;

}

public String getMeetingType() {

return meetingType;

}

public void setMeetingType(String meetingType) {

this.meetingType = meetingType;

}

public String getPassFlag() {

return passFlag;

}

public void setPassFlag(String passFlag) {

this.passFlag = passFlag;

}

public String getAllOpinion() {

return allOpinion;

}

public void setAllOpinion(String allOpinion) {

this.allOpinion = allOpinion;

}

public String getSign() {

return sign;

}

public void setSign(String sign) {

this.sign = sign;

}

public String getSignDate() {

return signDate;

}

public void setSignDate(String signDate) {

this.signDate = signDate;

}

}

3. 表单行数据循环对象

/**

* 投票详情

*/

public class VoteInfo {

/** 投票人名称 */

private String voterName;

/** 投票结果 1、同意 2、续议 3、拒绝 4、回避 */

private String voteResult;

/** 投票意见 */

private String voteOpinion;

public VoteInfo() {

}

public VoteInfo(String voterName, String voteResult, String voteOpinion) {

this.voterName = voterName;

this.voteResult = voteResult;

this.voteOpinion = voteOpinion;

}

public String getVoterName() {

return voterName;

}

public void setVoterName(String voterName) {

this.voterName = voterName;

}

public String getVoteResult() {

return voteResult;

}

public void setVoteResult(String voteResult) {

this.voteResult = voteResult;

}

public String getVoteOpinion() {

return voteOpinion;

}

public void setVoteOpinion(String voteOpinion) {

this.voteOpinion = voteOpinion;

}

}

四、参考或相关文档

poi-tl官方文档

poi-tl导出word, 含表格单元格合并,表格单元格多图合并

poi-tl导出复杂word/pdf文档



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。