最近在工作中实现了一个将多张图片导出到 Excel 表格,而且图片需要在单元格内平铺展示的需求。
需求通过 EasyExcel(版本 3.3.4)中提供的转换器(Converter)和拦截器(Handler)实现。
EasyExcel 官网地址
实现效果
![EasyExcel-01.png](https://img-blog.csdnimg.cn/img_convert/7c3a0a4f0d7c9e33733041805a24246c.png)
实现过程
EasyExcel 支持导出 ByteArray、File、String、InputStream、URL 五种类型的图片。项目中图片字段存储的是图片 URL 地址,因此本文将介绍导出 String 类型图片的实现过程。
实现过程主要包括两个关键步骤:
自定义转换器(实现 Converter 接口):图片数据转换(将 String 类型图片的 URL 地址转换为字节数组,并设置到 writeCellData对象的 imageDataList 属性中)。自定义拦截器(实现 CellWriteHandler 接口):阻止 EasyExcel 默认的图片导出操作,使用 Apache POI 库向 Excel 表格中手动写入图片。
执行流程和具体步骤如下。
![EasyExcel-02.png](https://img-blog.csdnimg.cn/img_convert/5f62a05ae861b1f5e26b1f0432db78e5.png)
1、引入依赖
com.alibaba
easyexcel
3.3.4
2、定义实体类
/**
* @author Cleaner
* @description 只保留图片字段,省略其他字段
*/
@Data
public class ExportImageVO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 图片地址列表
*/
@ExcelProperty(value = "图片", order = 1,converter = ExcelUrlConverterUtil.class)
private List imageUrlList;
}
3、定义转换器
public class ExcelImageUrlConverterUtil implements Converter {
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public WriteCellData convertToExcelData(List value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
List imageDataList = new ArrayList();
for (String url : value) {
try {
URL imageUrl = new URL(url);
byte[] bytes = IoUtils.toByteArray(imageUrl.openConnection().getInputStream());
ImageData imageData = new ImageData();
imageData.setImage(bytes);
imageDataList.add(imageData);
} catch (Exception e) {
e.printStackTrace();
}
}
WriteCellData writeCellData = new WriteCellData();
writeCellData.setImageDataList(imageDataList);
writeCellData.setType(CellDataTypeEnum.STRING);
return writeCellData;
}
}
4、定义拦截器
afterCellDataConverted 方法:单元格数据经过转换器处理之后,会回调执行该方法。在这个方法中阻止默认的图片导出操作。afterCellDispose 方法:单元格数据已经写入到 Excel 表格后,会回调执行该方法。在这个方法中实现手动插入图片到 Excel 表格。
public class ImageCellWriteHandler implements CellWriteHandler {
private final HashMap imageDataMap = new HashMap(16);
@Override
public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, WriteCellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
if (isHead) {
return;
}
// 将单元格图片数据复制出来,清空单元格图片数据
if (!CollectionUtils.isEmpty(cellData.getImageDataList())) {
imageDataMap.put(cell.getRowIndex() + "_" + cell.getColumnIndex(), cellData.getImageDataList());
cellData.setType(CellDataTypeEnum.EMPTY);
cellData.setImageDataList(new ArrayList());
}
}
@Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
if (isHead || CollectionUtils.isEmpty(cellDataList)) {
return;
}
String key = cell.getRowIndex() + "_" + cell.getColumnIndex();
List imageDataList = imageDataMap.get(key);
if (CollectionUtils.isEmpty(imageDataList)) {
return;
}
// 设置单元格行高和列宽
Sheet sheet = cell.getSheet();
sheet.getRow(cell.getRowIndex())
.setHeight((short) 900);
sheet.setColumnWidth(cell.getColumnIndex(), 250 * 50);
// 插入图片
for (int i = 0; i |