1. 背景
在实际的业务开发中,我们经常会遇到需要导入和导出Excel文件的需求。例如,HR部门可能需要从系统中导出员工信息,或者销售团队需要上传每月的销售数据。虽然市面上有很多功能强大的Excel处理工具,但有时候,我们只需要一个简单、轻量级的工具来完成基本的导入和导出操作。
因此,我创建了一个简单的ExcelUtil工具类,使用了EasyExcel库来简化和优化Excel操作。
2. 什么时候需要这个工具类?
当你需要进行以下操作时,可以考虑使用这个工具类:
- 创建一个带有指定表头的Excel文件。
- 从Excel文件中读取数据,并按照给定的表头进行映射。
- 将数据写入到一个已经存在的Excel文件中。
3. 如何使用?
创建Excel文件:
Map<String, Object> headers = new HashMap<>();
headers.put("Name", null);
headers.put("Age", null);
OutputStream os = new FileOutputStream("path_to_file.xlsx");
ExcelUtil.createExcelWithHeaders(os, headers);
从Excel文件中读取数据:
Map<String, Integer> headers = new HashMap<>();
headers.put("Name", 0);
headers.put("Age", 1);
InputStream is = new FileInputStream("path_to_file.xlsx");
ExcelUtil.readExcelWithHeaders(is, headers, rowMap -> {
System.out.println(rowMap);
});
将数据写入Excel文件:
Map<String, Object> headers = new HashMap<>();
headers.put("Name", null);
headers.put("Age", null);
List<Map<String, Object>> data = new ArrayList<>();
// ... 填充数据 ...
OutputStream os = new FileOutputStream("path_to_file.xlsx");
ExcelUtil.writeDataToExcel(os, headers, data);
4. 代码附录
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import com.alibaba.excel.EasyExcel;
/**
* @author aihe.ah
* @time 2023/10/12
* 功能说明:
*/
public class ExcelUtil {
/**
* 根据给定的表头创建一个Excel文件。
*
* @param os 输出流
* @param headers 表头
* @return 返回输出流
*/
public static OutputStream createExcelWithHeaders(OutputStream os, Map<String, Object> headers) {
if (os == null || headers == null || headers.isEmpty()) {
throw new IllegalArgumentException("参数不能为空");
}
List<List<String>> headerList = headers.keySet().stream()
.map(Collections::singletonList)
.collect(Collectors.toList());
// 注意:此处的OutputStream不会被关闭
EasyExcel.write(os).head(headerList).sheet("Sheet1").doWrite(Collections.emptyList());
return os;
}
/**
* 根据给定的表头读取Excel文件。
*
* @param is 输入流
* @param headers 表头
* @param processor 数据处理函数
*/
public static void readExcelWithHeaders(InputStream is, Map<String, Integer> headers,
Consumer<Map<String, Object>> processor) {
if (is == null || headers == null || headers.isEmpty() || processor == null) {
throw new IllegalArgumentException("参数不能为空");
}
EasyExcel.read(is, new com.alibaba.excel.event.AnalysisEventListener<Map<Integer, String>>() {
@Override
public void invoke(Map<Integer, String> data, com.alibaba.excel.context.AnalysisContext context) {
Map<String, Object> rowMap = headers.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> data.getOrDefault(entry.getValue(), null)
));
processor.accept(rowMap);
}
@Override
public void doAfterAllAnalysed(com.alibaba.excel.context.AnalysisContext context) {}
}).sheet().doRead();
}
/**
* 将数据写入Excel文件。
*
* @param os 输出流
* @param headers 表头
* @param data 要写入的数据
*/
public static void writeDataToExcel(OutputStream os, Map<String, Object> headers, List<Map<String, Object>> data) {
if (os == null || headers == null || headers.isEmpty() || data == null || data.isEmpty()) {
throw new IllegalArgumentException("参数不能为空");
}
List<List<String>> headerList = headers.keySet().stream()
.map(Collections::singletonList)
.collect(Collectors.toList());
List<List<Object>> dataList = data.stream()
.map(rowMap -> headers.keySet().stream()
.map(rowMap::get)
.collect(Collectors.toList()))
.collect(Collectors.toList());
EasyExcel.write(os).head(headerList).sheet("Sheet1").doWrite(dataList);
}
}
第二版
public class ExcelUtil {
/**
* 根据给定的表头创建一个Excel文件。
*
* @param headers
* @return
*/
public static byte[] createExcelWithHeaders(Map<String, Object> headers) {
if (headers == null || headers.isEmpty()) {
throw new IllegalArgumentException("参数不能为空");
}
ByteArrayOutputStream os = new ByteArrayOutputStream();
List<List<String>> headerList = headers.keySet().stream()
.map(Collections::singletonList)
.collect(Collectors.toList());
// 注意:此处的OutputStream不会被关闭
EasyExcel.write(os)
.head(headerList)
.sheet("Sheet1")
.registerWriteHandler(new SimpleColumnWidthStyleStrategy(TafpCommonSwitch.excelColumnWidth))
// .registerWriteHandler(new CommentWriteHandler(headers))
.doWrite(Collections.emptyList());
return os.toByteArray();
}
public static void readExcelWithHeaders(InputStream is,
Consumer<Map<String, Object>> processor) {
if (is == null || processor == null) {
throw new IllegalArgumentException("参数不能为空");
}
EasyExcel.read(is, new AnalysisEventListener<Map<Integer, String>>() {
Map<Integer, String> headerMap = new HashMap<>();
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
// 将表头的映射存储起来
headerMap = headMap;
}
@Override
public void invoke(Map<Integer, String> data, AnalysisContext context) {
Map<String, Object> rowMap = new HashMap<>();
for (Map.Entry<Integer, String> headerEntry : headerMap.entrySet()) {
Integer columnIndex = headerEntry.getKey();
String key = headerEntry.getValue();
Object value = data.get(columnIndex);
rowMap.put(key, value);
}
processor.accept(rowMap);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {}
}).sheet().doRead();
}
/**
* 使用EasyExcel将数据写入Excel。
*
* @param os 输出流,用于写入Excel数据。
* @param headers 表头和对应的宽度。
* @param data 数据列表,每个Map代表一行数据,key为表头,value为单元格的值。
*/
public static void writeDataToExcel(OutputStream os, Map<String, Object> headers, List<Map<String, Object>> data) {
if (os == null || headers == null || headers.isEmpty() || data == null || data.isEmpty()) {
throw new IllegalArgumentException("参数不能为空");
}
List<List<String>> headerList = headers.keySet().stream()
.map(Collections::singletonList)
.collect(Collectors.toList());
List<List<Object>> dataList = data.stream()
.map(rowMap -> headers.keySet().stream()
.map(rowMap::get)
.collect(Collectors.toList()))
.collect(Collectors.toList());
// 创建Excel写入器
ExcelWriter excelWriter = EasyExcel.write(os).build();
// 创建Sheet并设置表头宽度
WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1")
.head(headerList)
.registerWriteHandler(new SimpleColumnWidthStyleStrategy(TafpCommonSwitch.excelColumnWidth))
.build();
// 写入数据
excelWriter.write(dataList, writeSheet);
// 关闭Excel写入器
excelWriter.finish();
}
}