背景:要求在不同的条件下导出的文件格式不同。其中每个文件中都包含了图片。
1、实体
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import lombok.Builder;
import lombok.Data;
import java.net.URL;
/**
* @date 2021-03-10 23:32:49
* @author 林渊
*/
@Data
@Builder
@ContentRowHeight(200)
@ColumnWidth(50)
public class OtherGoodsInfoData {
@ExcelProperty(index = 0, value = "商品链接")
private String goodsLink;
@ExcelProperty(index = 1, value = "侵权截图")
private URL tortPicture;
}
复制代码
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import lombok.Builder;
import lombok.Data;
import java.net.URL;
/**
* @date 2021-03-10 23:32:49
* @author 林渊
*/
@Data
@Builder
@ContentRowHeight(200)
@ColumnWidth(50)
public class OtherCopyrightGoodsInfoData {
@ExcelProperty(index = 0, value = "商品链接")
private String goodsLink;
@ExcelProperty(index = 1, value = "侵权截图")
private URL tortPicture;
@ExcelProperty(index = 2, value = "对比截图")
private URL comparePicture;
@ExcelProperty(index = 3, value = "对比链接")
private String compareUrl;
}
复制代码
遇到的问题
1、导出的图片不会随着单元格的移动而移动,就像是一块膏药,贴在那不动。
2、设置好移动之后,会出现一个单元格内有两张图的情况。
3、图片会随着移动,但是不会自适应大小。
解决办法
问题1:EasyExcel需要配置Handler。其中afterCellDataConverted这个方法中,cellData.setType(CellDataTypeEnum.EMPTY);属性这么设置,也就表示EasyExcel在写的时候会忽略这个cell。从而不会出现图片填充两次的情况。但是因为这个需要通用,所以获取导出实体类中的URL字段的属性,获取index,也就是图片的cell需要EasyExcel写入的时候忽略。
import cn.afterturn.easypoi.util.PoiPublicUtil;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.*;
import java.util.List;
import static org.apache.poi.ss.usermodel.ClientAnchor.AnchorType.*;
/**
* easyExcel图片导出处理器
*
* @author linyuan
* @date 2021-03-15 10:45:49
*/
public class ImageModifyHandler implements CellWriteHandler {
private final List<Integer> ignoreIndexes;
public ImageModifyHandler(List<Integer> ignoreIndexes) {
this.ignoreIndexes = ignoreIndexes;
}
@Override
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) {
}
@Override
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) {
}
@Override
public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {
if (!ignoreIndexes.isEmpty()) {
if (!ignoreIndexes.contains(head.getColumnIndex()) || aBoolean) {
return;
}
cellData.setType(CellDataTypeEnum.EMPTY);
}
}
@Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {
// 在 单元格写入完毕后 ,自己填充图片
if (head.getColumnIndex() != 1 || aBoolean || list.isEmpty() || list.get(0).getImageValue() == null) {
return;
}
Sheet sheet = cell.getSheet();
// cellDataList 是list的原因是 填充的情况下 可能会多个写到一个单元格 但是如果普通写入 一定只有一个
int index = sheet.getWorkbook().addPicture(list.get(0).getImageValue(), getImageType(list.get(0).getImageValue()));
Drawing drawing = sheet.getDrawingPatriarch();
if (drawing == null) {
drawing = sheet.createDrawingPatriarch();
}
CreationHelper helper = sheet.getWorkbook().getCreationHelper();
ClientAnchor anchor = helper.createClientAnchor();
// 设置图片坐标
anchor.setDx1(1);
anchor.setDx2(1);
anchor.setDy1(0);
anchor.setDy2(0);
//设置图片位置
anchor.setCol1(cell.getColumnIndex());
anchor.setCol2(cell.getColumnIndex() + 1);
anchor.setRow1(cell.getRow().getRowNum());
anchor.setRow2(cell.getRow().getRowNum() + 1);
// 设置图片可以随着单元格移动
anchor.setAnchorType(MOVE_AND_RESIZE);
drawing.createPicture(anchor, index);
}
/**
* 获取图片类型,设置图片插入类型
* @author JueYue 2013年11月25日
*/
public static int getImageType(byte[] value) {
String type = PoiPublicUtil.getFileExtendName(value);
if ("JPG".equalsIgnoreCase(type)) {
return Workbook.PICTURE_TYPE_JPEG;
} else if ("PNG".equalsIgnoreCase(type)) {
return Workbook.PICTURE_TYPE_PNG;
}
return Workbook.PICTURE_TYPE_JPEG;
}
}
复制代码
EasyExcel.write(excelPath + fileName,clazz )
.registerWriteHandler(new ImageModifyHandler(getIgnoreIndexes(clazz)))
.sheet()
.doWrite(tempList);
/**
* 获取类中URL属性的字段的index集合
* @param clazz clazz
* @return List<Integer></>
*/
private List<Integer> getIgnoreIndexes(Class clazz) {
if (clazz == null) {
return Collections.emptyList();
}
List<Integer> indexes = new ArrayList<>();
Field[] fields = clazz.getDeclaredFields();
Arrays.asList(fields).forEach(f -> {
if (f.getGenericType().equals(URL.class)) {
ExcelProperty excelProperty= f.getAnnotation(ExcelProperty.class);
if (excelProperty != null && excelProperty.index() >= 0) {
indexes.add(excelProperty.index());
}
}
});
return indexes;
}
复制代码
问题2:在问题1中已经解决了。设置属性。
问题3:设置anchor的属性。图片如果完全在这个单元格内,四周都没碰到单元格,图片是可以跟随单元格移动的。
ClientAnchor anchor = helper.createClientAnchor();
// 设置图片坐标
anchor.setDx1(1);
anchor.setDx2(1);
anchor.setDy1(0);
anchor.setDy2(0);
//设置图片位置
anchor.setCol1(cell.getColumnIndex());
anchor.setCol2(cell.getColumnIndex() + 1);
anchor.setRow1(cell.getRow().getRowNum());
anchor.setRow2(cell.getRow().getRowNum() + 1);
// 设置图片可以随着单元格移动
anchor.setAnchorType(MOVE_AND_RESIZE);
复制代码
近期评论