首页 > 其他分享 >springboot简单使用poi-tl

springboot简单使用poi-tl

时间:2023-09-08 19:55:45浏览次数:42  
标签:users url tl template poi new out data springboot

简介

poi-tl是一个基于Apache POI的开源Word模板引擎,比 Freemarker 的功能更加强大。

官方文档地址:http://deepoove.com/poi-tl/

导包

导入包时,依赖说明参考官方文档,导入包不适配可能会造成一些问题,此处可以使用

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>5.2.3</version>
        </dependency>
        <dependency>
            <groupId>com.deepoove</groupId>
            <artifactId>poi-tl</artifactId>
            <version>1.12.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>5.3.18</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>5.2.3</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.5.6</version>
        </dependency>

使用

所有的标签都是以{{开头,以}}结尾:{{title}},其余标签参考官方文档

区块对由前后两个标签组成,开始标签以?标识,结束标签以/标识:{{?sections}}{{/sections}}

区块对开始和结束标签中间可以包含多个图片、表格、段落、列表、图表等,开始和结束标签可以跨多个段落,也可以在同一个段落,但是如果在表格中使用区块对,开始和结束标签必须在同一个单元格内,因为跨多个单元格的渲染行为是未知的。
区块对在处理一系列文档元素的时候非常有用,位于区块对中的文档元素可以被渲染零次,一次或N次,这取决于区块对的取值。

  • False或空集合:隐藏区块中的所有文档元素
  • 非False且不是集合:显示区块中的文档元素,渲染一次
  • 非空集合:根据集合的大小,循环渲染区块中的文档元素

数据类似于哈希或者字典,可以是Map结构(key是标签名称):

map:

Map<String, Object> data = new HashMap<>();
data.put("name", "Sayi");
data.put("start_time", "2019-08-04");

entity:

public class Data {
  private String name;
  private String startTime;
  private Author author;
}

以流的方式进行输出:

template.write(OutputStream stream);
// 文件流:
template.write(new FileOutputStream("output.docx"));
// 网络流:
response.setContentType("application/octet-stream");
response.setHeader("Content-disposition","attachment;filename=\""+"out_template.docx"+"\"");

// HttpServletResponse response
OutputStream out = response.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(out);
template.write(bos);
bos.flush();
out.flush();
PoitlIOUtils.closeQuietlyMulti(template, bos, out);

表格

创建:

实现:

List<Users> list = new ArrayList<>(0);
data.put("users", list);
ConfigureBuilder builder = Configure.builder();
LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
builder.bind("users", policy);
XWPFTemplate template = XWPFTemplate.compile(file.getPath(), builder.build()).render(data);

附件

可以直接在文档内打开,文档内保存了附件内容不是映射的本地地址

List<List<Objet>> users = new ArrayList<>(0);
for (int i = 0; i < 4; i++) {
	List<Object> list = new ArrayList<>(0);
	list.add("zhangsan");
	list.add("zhangsan123");
	list.add("pwd123");
	list.add("2022-12-01 12:00:00");
}
List<Object> titles = Arrays.asList("用户名", "账号", "密码", "创建时间");
// 写入缓存文件
String url = "C:\\Users\\Public\\Documents\\users.xlsx";
File file = new File(url);
if (file.isFile()) {
    file.delete();
}
ExcelWriter writer = ExcelUtil.getWriter(file);
writer.writeHeadRow(titles).write(users);
writer.flush().close();
removeUrls.add(url);
// 创建插件
AttachmentRenderData attach = Attachments.ofLocal(url, AttachmentType.XLSX).create();
data.put("users", attach);
AttachmentRenderPolicy attachmentRenderPolicy = new AttachmentRenderPolicy();
ConfigureBuilder builder = Configure.builder();
builder.bind("users", attachmentRenderPolicy);
// 获取模板文件
File fileTemplate = ResourceUtils.getFile("src/main/resources/templates/template.docx");
if (fileTemplate.exists()) {
	XWPFTemplate template = XWPFTemplate.compile(fileTemplate.getPath(), builder.build()).render(data);
	response.setContentType("application/octet-stream");
	response.setHeader("Content-disposition", "attachment;filename=\"" + "out_template.docx" + "\"");

	// HttpServletResponse response
	OutputStream out = response.getOutputStream();
	BufferedOutputStream bos = new BufferedOutputStream(out);
	template.write(bos);
	bos.flush();
	out.flush();
	PoitlIOUtils.closeQuietlyMulti(template, bos, out);
}
// 删除缓存的附件
if (file.isFile()) {
	file.delete();
}

完整代码

private final String linuxUrl = "/home/";
private final String windowsUrl = "C:\\Users\\Public\\Documents\\";

/**
 * 导出根据word模板生成
 */
@Override
public void exportDoc(HttpServletResponse response) throws IOException {
	String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
	Map<String, Object> data = new HashMap<>(0);
	data.put("time", time);
	// 用户数据列表
	List<User> users = new ArrayList<>(0);
	for (int i = 0; i < 12; i++) {
		User user = new User();
		user.setUsername("zhangsan"+i);
		user.setAccount("zhangsan"+i);
		user.setPassword("12345"+i);
		user.setCreateTime("2022-12-01 12:00:00");
		users.add(user);
	}
	data.put("users", users);
	if (users > 10) {
		// 生成excel附件
		List<List<Object>> usersExcels = new ArrayList<>(0);
		for (int i = 0; i < users.size(); i++) {
			List<Object> list = new ArrayList<>(0);
			list.add(users.get(i).getUsername());
			list.add(users.get(i).getAccount());
			list.add(users.get(i).getPassword());
			list.add(users.get(i).getCreateTime());
			usersExcels.add(list);
		}
		List<Object> titles = Arrays.asList("用户名", "账号", "密码", "创建时间");
		String url = this.downloadFileLocal("users.xlsx", titles, usersExcels);
		removeUrls.add(url);
		AttachmentRenderData attach = Attachments.ofLocal(url, AttachmentType.XLSX).create();
		// 此时word文档内标签为{{usersExcels}}
		data.put("usersExcels", attach);
	} 
	File file = ResourceUtils.getFile("src/main/resources/templates/template.docx");
	if (file.exists()) {
		LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
		AttachmentRenderPolicy attachmentRenderPolicy = new AttachmentRenderPolicy();
		ConfigureBuilder builder = Configure.builder();
		builder.bind("users", policy);
		builder.bind("usersExcels", attachmentRenderPolicy);

		XWPFTemplate template = XWPFTemplate.compile(file.getPath(), builder.build()).render(data);
		response.setContentType("application/octet-stream");
		response.setHeader("Content-disposition", "attachment;filename=\"" + "out_template.docx" + "\"");

		// HttpServletResponse response
		OutputStream out = response.getOutputStream();
		BufferedOutputStream bos = new BufferedOutputStream(out);
		template.write(bos);
		bos.flush();
		out.flush();
		PoitlIOUtils.closeQuietlyMulti(template, bos, out);
		// 删除缓存的附件
		this.deleteCacheFiles(removeUrls);
	}
}

/**
 * 生成excel附件
 *
 * @param fileName 文件名
 * @param titles   表头
 * @param data     数据
 */
private String downloadFileLocal(String fileName, List<Object> titles, List<List<Object>> data) throws IOException {
	String url = "";
	String osName = System.getProperty("os.name").toLowerCase();
	if (Constants.isSystem(osName)) {
		// Windows
		url = windowsUrl + fileName;
	} else {
		// Linux
		url = linuxUrl + fileName;
	}
	File file = new File(url);
	if (file.isFile()) {
		file.delete();
	}
	ExcelWriter writer = ExcelUtil.getWriter(file);
	writer.writeHeadRow(titles).write(data);
	writer.flush().close();
	return url;
}

/**
 * 删除缓存附件
 */
private boolean deleteCacheFiles(List<String> urls) {
	for (String url : urls) {
		File files = new File(url);
		if (files.isFile()) {
			files.delete();
		}
	}
	return true;
}

标签:users,url,tl,template,poi,new,out,data,springboot
From: https://www.cnblogs.com/1399z3blog/p/17688439.html

相关文章

  • gitlab搭建
    社区版安装建议4G内存安装并配置必须的依赖sudoyuminstall-ycurlpolicycoreutils-pythonopenssh-serversudosystemctlenablesshdsudosystemctlstartsshdsudofirewall-cmd--permanent--add-service=httpsudosystemctlreloadfirewalld安装Postfix......
  • Web阶段:第十四章:JSTL标签库
    JSTL标签库JSTL标签库全称是指JSPStandardTagLibraryJSP标准标签库。是一个不断完善的开放源代码的JSP标签库。EL表达式主要是为了替换jsp中的表达式脚本,而标签库则是为了替换代码脚本。这样使得整个jsp页面变得更佳简洁。JSTL由五个不同功能的标签库组成。功能范围URI......
  • SpringBoot中配置文件和配置类实现个性化配置的一点区别
    先说配置文件,以properties文件为例,默认存放静态资源文件夹路径是 "classpath:/META-INF/resources/","classpath:/resources/","classpath:/static/","classpath:/public/"。经过下面配置后,这些默认规则都不再生效。#自定义静态资源文件夹位置spring.web.resources.static-locat......
  • 打包发布版时报错 Error: The apk for your currently selected variant cannot be si
    当直接运行release版本时,报错Error:Theapkforyourcurrentlyselectedvariantcannotbesigned.Pleasespecifyasigningconfigurationforthisvariant(release).解决报错:要在配置里添加签名android{signingConfigs{debug{storeFil......
  • POI向Excel中写入数据及追加数据
    importorg.apache.poi.xssf.usermodel.XSSFCell;importorg.apache.poi.xssf.usermodel.XSSFRow;importorg.apache.poi.xssf.usermodel.XSSFSheet;importorg.apache.poi.xssf.usermodel.XSSFWorkbook;importjava.io.*;importjava.util.ArrayList;importjava.util......
  • 为什么 springboot 项目中 使用 lombok 不需要指定版本
    springboot默认管理了lombok的版本依赖,所以不需要指定版本号SpringBoot项目中使用Lombok不需要显式指定Lombok的版本,是因为SpringBoot的父项目(spring-boot-starter-parent)已经为您管理了Lombok的版本。这是通过在SpringBoot的父项目中的dependencyManagement部分指定Lombok的......
  • Annotation processors must be explicitly declared now
    AndroidStudio升级到最新版3.0Canary8后,当使用到注解时,报了如下错误:Error:Executionfailedfortask':app:javaPreCompileDebug'.>Annotationprocessorsmustbeexplicitlydeclarednow.Thefollowingdependenciesonthecompileclasspatharefoundtocontain......
  • springboot实现 伪微信登录
    众所周知,微信扫码登陆的功能,个人网站是无法申请的,我们想在本地测一下微信登录也是无法实现。要实现微信登录,首先你得是一个企业单位,有公章才能申请,申请还要花费300块大洋。如果我们只是想学习和体验一下微信登录,可以自己本地搭建个微型服务模拟一下,过一把瘾也是可以的。如果你是企......
  • 详谈SpringBoot启动项目后执行自定义方法的方式
    在main启动函数中调用这个是在所有启动后执行,也是常用之一。@SpringBootApplicationpublicclassListenerApplication{publicstaticvoidmain(String[]args){SpringApplication.run(ListenerApplication.class,args);System.out.println("启动成......
  • STL在遍历过程中操作地址的改变
    2023-08-2609:57:22startwriting2023.8.269:18又遇到奇怪错误了,其实在打模拟赛(wzOI2023.8.24T1)的时候就发现有这个问题了,赛后来研究一下。以下代码://check是一个返回值为bool类型的判断函数,S是一个unordered_set<int>for(inti=1;i<=n;i++){intx=i,maxx=0,ans......