前言
还在为Java应用中复杂的Excel报表导出而头疼吗?是否厌倦了在代码里逐行逐单元格拼接数据的繁琐操作?如果你的答案是肯定的,那么这篇文章正是为你准备的!
作为开发者,高效、优雅地生成格式化的Excel报表是一项高频且关键的需求。手动操作POI API不仅代码冗长、维护困难,模板稍有变动就需要重新调整代码,灵活性极差。而 JXLS 正是为解决这一痛点而生的利器,它通过声明式的模板驱动方式,让Excel报表生成变得直观、简洁且易于维护。
在本文中,将聚焦于 JXLS最核心也最强大的功能之一:基于Excel批注的模板配置。
我的公众号(附有面试资料):Java乐享
一、引入依赖
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls-poi</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls-jexcel</artifactId>
<version>1.0.7</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
二、编写代码
实体类
package com.lexiang.demo.dto;
import lombok.Data;
/**
* @author lexiang
*/
@Data
public class UserDTO {
private Long id;
private String username;
private String phone;
}
工具类JxlsExcelUtil
package com.lexiang.demo.util;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.jxls.common.Context;
import org.jxls.transform.Transformer;
import org.jxls.transform.poi.PoiTransformer;
import org.jxls.util.JxlsHelper;
import org.springframework.util.ClassUtils;
import org.springframework.util.ResourceUtils;
import java.io.*;
import java.net.URLEncoder;
import java.util.Map;
/**
* @author lexiang
*/
public class JxlsExcelUtil {
private static final String EXCEL_XLS = ".xls";
private static final String EXCEL_XLSX = ".xlsx";
/**
* 导出工具类
* @param response
* @param input
* @param data
*/
public static void export(HttpServletResponse response, InputStream input, Map<String, Object> data, String importFileName) {
OutputStream outStream = null;
try {
Context context = new Context();
for (Map.Entry<String, Object> element : data.entrySet()) {
context.putVar(element.getKey(), element.getValue());
}
outStream = response.getOutputStream();
// 设置ContentType请求信息格式
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyExcel没有关系
String fileName = URLEncoder.encode(importFileName, "UTF-8").replaceAll("\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=" + fileName + EXCEL_XLSX);
Transformer transformer = PoiTransformer.createTransformer(input, outStream);
JxlsHelper.getInstance().setEvaluateFormulas(true).processTemplate(context, transformer);
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
try {
assert outStream != null;
outStream.flush();
outStream.close();
} catch (IOException e) {
}
}
}
/**
* 获取模板文件流
*/
public static InputStream getTplIs(String tpl) {
InputStream is = null;
try {
String tplPath = "templates/" + tpl;
is = ClassUtils.class.getClassLoader().getResourceAsStream(tplPath);
if (is == null) {
File file = ResourceUtils.getFile("classpath:" + tplPath);
is = new FileInputStream(file);
}
} catch (Exception e) {
String eMsg = StringUtils.isBlank(e.getMessage()) ? e.toString() : e.getMessage();
}
return is;
}
}
测试类
package com.lexiang.demo.controller;
import com.lexiang.demo.dto.UserDTO;
import com.lexiang.demo.util.JxlsExcelUtil;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.InputStream;
import java.util.*;
/**
* jxls导出
* @author lexiang
*/
@RestController
@RequestMapping("/jxls")
public class JxlsController {
@GetMapping("export")
public void export(HttpServletResponse response) {
Map<String,Object> param = new HashMap<>(8);
param.put("unitName", "学生状态表");
param.put("className", "高一三班");
param.put("people", "张三");
param.put("phone", "13666666666");
param.put("num", 30);
param.put("gameNum", 12);
param.put("bookNum", 10);
param.put("musicNum", 8);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Access-Control-Expose-Headers","Content-Disposition");
InputStream inputStream = JxlsExcelUtil.getTplIs("people_report.xlsx");
JxlsExcelUtil.export(response, inputStream, param, "学生状态表");
}
@GetMapping("exportList")
public void exportList(HttpServletResponse response) {
Map<String,Object> param = new HashMap<>(8);
param.put("title", "标题");
List<UserDTO> users = new ArrayList<>();
UserDTO dto1 = new UserDTO();
dto1.setId(1L);
dto1.setUsername("张三");
dto1.setPhone("13645634563");
UserDTO dto2 = new UserDTO();
dto2.setId(2L);
dto2.setUsername("李思思");
dto2.setPhone("13645634666");
users.add(dto1);
users.add(dto2);
param.put("users", users);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Access-Control-Expose-Headers","Content-Disposition");
InputStream inputStream = JxlsExcelUtil.getTplIs("list_demo.xlsx");
JxlsExcelUtil.export(response, inputStream, param, "用户信息表");
}
}
三、在templates下创建excel模板
语法
jx:area 定义 Jxls 应处理的单元格区域。jx:area 通常位于单元格 A1 中,而 其 lastCell 属性定义所用工作表区域的右下角。
jx:each 主要用于创建行。一般用于循环列表。
jx:each(items=”users”,var=”use”,lastCell=”C3”)
说明: items: 返回 Iterable 或数组的表达式 ;var:保存每行对象的变量名称; lastCell:区域结束
官方文档:jxls.sourceforge.net/commands.ht…
1.单个字段名称
创建people_report.xlsx
选中{people}和${num}同理设置
2.列表数据
创建list_demo.xl
title批注设置的是jx:area(lastCell=”C3”)
${user.id}批注设置的是jx:each(items=”users”,var=”use”,lastCell=”C3”)
四、测试
启动项目后用apifox或者postman调用接口测试
接口地址:http://localhost:8080/jxls/export
效果如下:
接口地址:http://localhost:8080/jxls/exportList
效果如下: