概述
Hutool是一个Java工具库,提供了许多方便实用的工具类和方法。其中,Hutool也提供了一个ExcelWriter
类,用于简化在Java中写入Excel文件的操作。通过ExcelWriter,你可以直接在代码中导出Excel文件,本文利用反射机制封装公共的导出工具类,并且支持指定某些字段进行导出。
POM引入
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-poi</artifactId>
<version>5.8.16</version>
</dependency>
实体类
创建实体,定义需要进行导出的字段
@Data
public class User {
public String name;
public Integer age;
public String gender;
public String address;
}
公共导出工具类
封装公共的
导出工具类
,以便于在其他请求方法中,可以直接进行使用,同时也提高了代码的可维护性、重用性和安全性。
import cn.hutool.core.lang.Dict;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @Date: 2023/3/31 16:45
* @Description:
**/
public class ExportUtil {
/**
* @param map key是字段名, value是映射的中文名称
* @param fieldList 需要指定导出的字段
* @param list 待导出的数据集合
* @param classes 待导出数据的class对象
* @return
*/
public static List<Dict> export(Map<String, String> map, List<String> fieldList, List<?> list, Class<?> classes) {
try {
List<Dict> res = new ArrayList<>();
// 遍历需要导出的集合
for (Object o : list) {
Dict data = new Dict();
// 获取map中需要匹配的字段
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
// 如果fieldList中存在数据,那么只会导出指定的字段数据
if (fieldList != null && fieldList.size() > 0) {
if (fieldList.contains(entry.getKey())) {
Field field = classes.getDeclaredField(entry.getKey());
data.set(entry.getValue(), field.get(o));
}
} else {
Field field = classes.getDeclaredField(entry.getKey());
data.set(entry.getValue(), field.get(o));
}
}
res.add(data);
}
return res;
} catch (Exception e) {
throw new RuntimeException("数据导出失败");
}
}
}
测试类
通过controller,对外暴漏一个导出接口,导出的数据进行模拟生成,再配合封装的
公共工具类
进行导出操作。
import cn.hutool.core.lang.Dict;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.hutool.poi.excel.StyleSet;
import cn.lihuazhi.poi.pojo.User;
import cn.lihuazhi.poi.service.UserService;
import cn.lihuazhi.poi.util.ExportUtil;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author LiGezZ
*/
@RestController
@RequestMapping("/HuTool")
public class HuToolExcelController {
@Resource
private UserService userService;
@Resource
private HttpServletResponse response;
/**
* 数据的导出
*
* @param fieldList 由前端传入的,指定的导出字段名称,比如:["name","age"];为空则标识导出所有
*/
@PostMapping("/exportExcel")
@ResponseBody
public void exportExcel(@RequestBody(required = false) List<String> fieldList) {
// 通过工具类创建writer,默认创建xls格式
try (ExcelWriter writer = ExcelUtil.getWriter(); ServletOutputStream outputStream = response.getOutputStream()) {
// 模拟从数据库获取数据
List<User> dataList = userService.getUserInfo();
if (dataList.size() <= 0) {
dataList.add(new User());
}
// 需要导出的字段与中文对应关系,可以少于实体类中的字段
Map<String, String> map = new HashMap<>(8);
map.put("name", "名称");
map.put("age", "年龄");
map.put("gender", "性别");
List<Dict> res = ExportUtil.export(map, fieldList, dataList, User.class);
// 设置全局边框样式
StyleSet styleSet = writer.getStyleSet();
styleSet.setBorder(BorderStyle.THIN, IndexedColors.BLACK);
// 浏览器下载
writer.write(res);
response.reset();
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("test.xlsx", "UTF-8"));
response.setContentType("application/octet-stream; charset=UTF-8");
writer.flush(outputStream, true);
} catch (Exception e) {
e.printStackTrace();
}
}
}
测试结果
1、全字段导出
流程:前端不传入任何数据,实体字段:name、age、gender、address
,导出字段:name、age、gender
2、指定字段导出
流程:前端传入["name","gender"]
,实体字段:name、age、gender、address
,导出字段:name、age、gender
其他用法及总结:
Hutool的ExcelWriter提供了丰富的方法和选项,可以方便地导出数据到Excel文件。下面是一些常用的导出操作和说明:
1. 创建ExcelWriter对象:
在创建ExcelWriter时,指定输出的Excel文件名。
ExcelWriter writer = ExcelUtil.getWriter("output.xlsx");
1. 写入表头数据:
使用writeHeadRow方法写入表头数据,传入一个字符串列表作为表头内容。
writer.writeHeadRow(headerList);
3. 写入普通数据:
使用writeRow方法写入一行普通数据,传入一个字符串列表作为行数据内容。
writer.writeRow(rowDataList);
4. 写入多行普通数据:
使用write方法写入多行普通数据,传入一个列表,每个元素都是一个字符串列表,表示一行数据。
writer.write(rows);
5. 写入自定义样式:
使用getStyleSet获取样式集,然后使用setStyle方法设置自定义样式。可以设置表头样式、数据样式等。
CellStyle style = writer.getStyleSet().getHeadCellStyle();
writer.setStyle(style);
6. 合并单元格:
使用merge方法合并单元格,传入起始单元格的行索引、列索引,以及结束单元格的行索引、列索引。
writer.merge(rowIndex, columnIndex, lastRowIndex, lastColumnIndex);
7. 写入图片:
使用addPicture方法写入图片,传入图片所在的单元格索引、图片的字节数组和图片类型。
writer.addPicture(columnIndex, rowIndex, imageBytes, ImageType.PNG);
8. 设置列宽度:
使用setColumnWidth方法设置指定列的宽度,传入列索引和宽度值。
writer.setColumnWidth(columnIndex, width);
9. 冻结窗口:
使用setFreezePane方法在指定的单元格位置冻结窗口,传入分割的列数、行数以及左边和上边最可见的列号和行号
writer.setFreezePane(colSplit, rowSplit, leftmostColumn, topRow);