官方文档Hutool
目录:
1.1 写出List数据
1.2 写出Map数据
1.3 写出我们的Bean对象
1.4 自定义Bean的key别名
1.5 写出到IO流
1.6 写出到客户端下载(写出到Servlet)
2.1 设置单元格背景色
2.2 自定义字体
2.3 写出多个sheet
2.4 更详细的定义样式
3.1 常用的读取方式
4.1 实现Excel的下载
4.2 实现Excel导入到数据库
4.3 实现Excel的模板从服务器下载到客户端
基本依赖的导入
<!-- 基本依赖包 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.8</version>
</dependency>
<!-- Excel包 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
Writer方法的使用
1. 写出List数据
1.1 制造我们的rows集合对象
List<String> row1 = CollUtil.newArrayList("aa", "bb", "cc", "dd");
List<String> row2 = CollUtil.newArrayList("aa1", "bb1", "cc1", "dd1");
List<String> row3 = CollUtil.newArrayList("aa2", "bb2", "cc2", "dd2");
List<String> row4 = CollUtil.newArrayList("aa3", "bb3", "cc3", "dd3");
List<String> row5 = CollUtil.newArrayList("aa4", "bb4", "cc4", "dd4");
List<List<String>> rows = CollUtil.newArrayList(row1, row2, row3, row4, row5);
1.2 将我们的对象写出
//通过工具类创建writer
ExcelWriter writer = ExcelUtil.getWriter("d:/writeTest.xlsx");
//通过构造方法创建writer
//ExcelWriter writer = new ExcelWriter("d:/writeTest.xls");
//跳过当前行,既第一行,非必须,在此演示用
writer.passCurrentRow();
//合并单元格后的标题行,使用默认标题样式
writer.merge(row1.size() - 1, "测试标题");
//一次性写出内容,强制输出标题
writer.write(rows, true);
//关闭writer,释放内存
writer.close();
2. 写出Map数据
1.1 制造我们的Map对象
Map<String, Object> row1 = new LinkedHashMap<>();
row1.put("姓名", "张三");
row1.put("年龄", 23);
row1.put("成绩", 88.32);
row1.put("是否合格", true);
row1.put("考试日期", DateUtil.date());
Map<String, Object> row2 = new LinkedHashMap<>();
row2.put("姓名", "李四");
row2.put("年龄", 33);
row2.put("成绩", 59.50);
row2.put("是否合格", false);
row2.put("考试日期", DateUtil.date());
ArrayList<Map<String, Object>> rows = CollUtil.newArrayList(row1, row2);
1.2 写出我们的rows对象
// 通过工具类创建writer
ExcelWriter writer = ExcelUtil.getWriter("d:/writeMapTest.xlsx");
// 合并单元格后的标题行,使用默认标题样式
writer.merge(row1.size() - 1, "一班成绩单");
// 一次性写出内容,使用默认样式,强制输出标题
writer.write(rows, true);
// 关闭writer,释放内存
writer.close();
3. 写出我们的Bean对象
1.1 制造我们的Bean数据
TestBean bean1 = new TestBean();
bean1.setName("张三");
bean1.setAge(22);
bean1.setPass(true);
bean1.setScore(66.30);
bean1.setExamDate(DateUtil.date());
TestBean bean2 = new TestBean();
bean2.setName("李四");
bean2.setAge(28);
bean2.setPass(false);
bean2.setScore(38.50);
bean2.setExamDate(DateUtil.date());
List<TestBean> rows = CollUtil.newArrayList(bean1, bean2);
1.2 写出我们的Rows对象
// 通过工具类创建writer
ExcelWriter writer = ExcelUtil.getWriter("d:/writeBeanTest.xlsx");
// 合并单元格后的标题行,使用默认标题样式
writer.merge(4, "一班成绩单");
// 一次性写出内容,使用默认样式,强制输出标题
writer.write(rows, true);
// 关闭writer,释放内存
writer.close();
4. 自定义Bean的key别名
// 通过工具类创建writer
ExcelWriter writer = ExcelUtil.getWriter("d:/writeBeanTest.xlsx");
//自定义标题别名
writer.addHeaderAlias("name", "姓名");
writer.addHeaderAlias("age", "年龄");
writer.addHeaderAlias("score", "分数");
writer.addHeaderAlias("isPass", "是否通过");
writer.addHeaderAlias("examDate", "考试时间");
// 合并单元格后的标题行,使用默认标题样式
writer.merge(4, "一班成绩单");
// 一次性写出内容,使用默认样式,强制输出标题
writer.write(rows, true);
// 关闭writer,释放内存
writer.close();
5. 写出到IO流
// 通过工具类创建writer,默认创建xls格式
ExcelWriter writer = ExcelUtil.getWriter();
//创建xlsx格式的
//ExcelWriter writer = ExcelUtil.getWriter(true);
// 一次性写出内容,使用默认样式,强制输出标题
writer.write(rows, true);
//out为OutputStream,需要写出到的目标流
writer.flush(out);
// 关闭writer,释放内存
writer.close();
6. 写出到客户端下载(写出到Servlet)
1.1 写出xls
// 通过工具类创建writer,默认创建xls格式
ExcelWriter writer = ExcelUtil.getWriter();
// 一次性写出内容,使用默认样式,强制输出标题
writer.write(rows, true);
//out为OutputStream,需要写出到的目标流
//response为HttpServletResponse对象
response.setContentType("application/vnd.ms-excel;charset=utf-8");
//test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
response.setHeader("Content-Disposition","attachment;filename=test.xls");
ServletOutputStream out=response.getOutputStream();
writer.flush(out, true);
// 关闭writer,释放内存
writer.close();
//此处记得关闭输出Servlet流
IoUtil.close(out);
1.2 写出xlsx
ExcelWriter writer = ExcelUtil.getWriter(true);
writer.write(rows, true);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
response.setHeader("Content-Disposition","attachment;filename=test.xlsx");
writer.flush(out, true);
writer.close();
IoUtil.close(out);
Writer方法的使用补充
1. 设置单元格背景色
// 定义单元格背景色
StyleSet style = writer.getStyleSet();
// 第二个参数表示是否也设置头部单元格背景
style.setBackgroundColor(IndexedColors.RED, false);
Copy to clipboardErrorCopied
2. 自定义字体
ExcelWriter writer = ...;
//设置内容字体
Font font = writer.createFont();
font.setBold(true);
font.setColor(Font.COLOR_RED);
font.setItalic(true);
//第二个参数表示是否忽略头部样式
writer.getStyleSet().setFont(font, true);
Copy to clipboardErrorCopied
3. 写出多个sheet
//初始化时定义表名
ExcelWriter writer = new ExcelWriter("d:/aaa.xls", "表1");
//切换sheet,此时从第0行开始写
writer.setSheet("表2");
...
writer.setSheet("表3");
...
Copy to clipboardErrorCopied
4. 更详细的定义样式
在Excel中,由于样式对象个数有限制,因此Hutool根据样式种类分为4个样式对象,使相同类型的单元格可以共享样式对象。样式按照类别存在于StyleSet中,其中包括:
头部样式 headCellStyle
普通单元格样式 cellStyle
数字单元格样式 cellStyleForNumber
日期单元格样式 cellStyleForDate
其中cellStyleForNumber cellStyleForDate用于控制数字和日期的显示方式。
因此我们可以使用以下方式获取CellStyle对象自定义指定种类的样式:
StyleSet style = writer.getStyleSet();
CellStyle cellStyle = style.getHeadCellStyle();
...
ExcelReader读取Excel、流、工作簿
1. 常用的读取方式
1.1 构建我们的实体类
@Data
public class Student {
String name;
String gender;
String idCard;
String mobile;
String education;
String remarks;
// 这个字段在Excel表中没有就不会被Htool封装进入数据
String more;
}
1.2 选择一张excel表
1.3 进行ExcelReader的测试使用
@Test
public void test01() {
// 直接按照行读取所有行的数据
ExcelReader reader = ExcelUtil.getReader("B:/xlxx backup.xlsx");
List<List<Object>> read = reader.read();
read.stream().forEach(objects -> System.out.println(objects));
System.out.println("-----------------");
// 第一行的列名 ——> 接下来的列的对应值
List<Map<String, Object>> maps = reader.readAll();
maps.stream().forEach(map -> map.entrySet().stream().forEach(item -> System.out.println("Column: "+item.getKey()+" Value: "+item.getValue())));
System.out.println("-----------------");
// 根据实体类进行字段的对应
List<Student> students = reader.readAll(Student.class);
students.stream().forEach(student -> System.out.println(student));
}
简单实战
1. 实现Excel的下载
1.1 Controller
/**
* @param pageNum 当前页
* @param pageSize 页面信息条数
* @param response 返回流信息对象
* @description 导出学生Excel
* @author 叶之越
* @email [email protected]
* @date 2020/7/7 13:50
*/
@ApiOperation("导出分页学生信息")
@PostMapping("/export")
public void export(Integer pageNum, Integer pageSize,HttpServletResponse response) {
talentStudentService.export(pageNum, pageSize, response);
}
1.2 Service
/**
* @param pageNum 当前页
* @param pageSize 页面信息条数
* @param talentStudent 我们导出的学生数据类型
* @param response 返回流信息对象
* @description 导出学生Excel
* @author 叶之越
* @email [email protected]
* @date 2020/7/7 13:54
*/
@Override
public void export(Integer pageNum, Integer pageSize, TalentStudent talentStudent, HttpServletResponse response) {
// 从数据库查出数据对象封装成map
final List<Map<String, Object>> educationList = page(new Page<>(pageNum, pageSize), Wrappers.lambdaQuery(talentStudent)).getRecords()
.stream()
// 封装成 Map 并且放入 List
.map(item -> {
final Map<String, Object> map = new LinkedHashMap<>();
// 错误,这里需要根据表中字段名称进行命名
map.put("name", item.getName());
map.put("gender", item.getGender());
map.put("idCard", item.getIdCard());
map.put("mobile", item.getMobile());
map.put("education", item.getEducation());
map.put("remarks", item.getRemarks());
return map;
})
.collect(Collectors.toList());
// 准备将数据集合封装成Excel对象
ExcelWriter writer = ExcelUtil.getWriter(true);
// 通过工具类创建writer并且进行别名
writer.addHeaderAlias("name", "姓名");
writer.addHeaderAlias("gender", "性别( 0 表示男 , 1 表示 女)");
writer.addHeaderAlias("idCard", "身份证");
writer.addHeaderAlias("mobile", "电话");
writer.addHeaderAlias("education", "个人介绍");
writer.addHeaderAlias("remarks", "备注");
// 准备将对象写入我们的 List
writer.write(educationList, true);
try {
// 获取我们的输出流
final OutputStream output = response.getOutputStream();
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("stu.xlsx", "UTF-8"));
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
writer.flush(output, true);
writer.close();
// 这里可以自行关闭资源或者写一个关闭资源的工具类
IoUtil.close(output);
} catch (IOException e) {
log.error("EducationServiceImpl [export] 输出到响应流失败", e);
throw new BusinessException("导出Excel异常");
}
}
2. 实现Excel导入到数据库
1.1 Controller
/**
* @param file 需要同步学生信息用户的Excel文件
* @description 导入查询学生信息
* @author 叶之越
* @email [email protected]
* @date 2020/7/7 13:50
*/
@ApiOperation("通过Excel表导入数据")
@PostMapping("/importStudent")
public ResultBean<Boolean> importStudent(@RequestParam MultipartFile file) {
try {
return ResultBean.restResult(talentStudentService.getStudentInfos(file.getInputStream()), ErrorCodeInfo.OK);
} catch (IOException e) {
log.error("EducationController [getEducation] 获取输入流失败", e);
throw new BusinessException("获取输入流失败");
}
}
1.2 Service
/**
* @param pageNum 当前页
* @param pageSize 页面信息条数
* @param talentStudent 我们导出的学生数据类型
* @param response 返回流信息对象
* @description 导出学生Excel
* @author 叶之越
* @email [email protected]
* @date 2020/7/7 13:50
*/
@ApiOperation("导出分页学生信息")
@PostMapping("/export")
public void export(Integer pageNum, Integer pageSize, TalentStudent talentStudent, HttpServletResponse response) {
talentStudentService.export(pageNum,pageSize, talentStudent,response);
}
3. 实现Excel的模板从服务器下载到客户端
1.1 Controller
/**
* @param response: 需要对返回IO流
* @description 返回我们 Excel 的模板
* @author 叶之越
* @email [email protected]
* @date 2020/7/7 15:15
*/
@ApiOperation("获取学生的数据模板")
@PostMapping("/getExcelTemplate")
public void getExcelTemplate(HttpServletResponse response) {
talentStudentService.getExcelTemplate(response);
}
}
1.2 Service
/**
* @param response: 返回输入流
* @description 下载我们 Excel 的模板
* @author 叶之越
* @email [email protected]
* @date 2020/7/7 15:17
*/
@Override
public void getExcelTemplate(HttpServletResponse response) {
try {
// 1 读取对象
final ExcelReader reader = ExcelUtil.getReader(this.getClass().getResourceAsStream("/exceltemplate/stu.xlsx"));
List<List<Object>> lists = reader.read();
ExcelWriter writer = ExcelUtil.getWriter(true);
writer.write(lists);
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("stu.xlsx", "UTF-8"));
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
// 2 写出对象
ServletOutputStream outputStream = response.getOutputStream();
// 通过IO写出我们的表格对象
writer.flush(outputStream, true);
writer.close();
IoUtil.close(outputStream);
} catch (IOException e) {
log.error("EducationServiceImpl [export] 输出到响应流失败", e);
throw new BusinessException("导出Excel异常");
}
}