首页 > 其他分享 >EasyExcel 单元格根据图片数量动态设置宽度

EasyExcel 单元格根据图片数量动态设置宽度

时间:2024-07-05 18:19:47浏览次数:19  
标签:EasyExcel 单元格 excel alibaba cell 宽度 import com

在使用 EasyExcel 导出 Excel 时,如果某个单元格是图片内容,且存在多张图片,此时就需要单元格根据图片数量动态设置宽度。
经过自己的研究和实验,导出效果如下:
image.png
具体代码如下:

  1. EasyExcel 版本
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.3.2</version>
</dependency>
  1. 定义Excel图片链接转换工具
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ImageData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.IoUtils;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
 * Excel图片链接转换工具
 *
 * @author 天航星
 * @date 2024-07-05 15:03
 */
public class ExcelImageUrlConverterUtils implements Converter<List<String>> {

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }

    @Override
    public WriteCellData<?> convertToExcelData(List<String> value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
        
        List<ImageData> 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;
    }
}
  1. 定义图片属性
@ExcelProperty(value = "现场图片(模拟机器人视角)", converter = ExcelImageUrlConverterUtils.class)
private List<String> images;
  1. 定义单元格图片写入拦截器
import cn.hutool.core.util.ObjUtil;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.ImageData;
import com.alibaba.excel.metadata.data.WriteCellData;
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.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.util.Units;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 单元格图片写入拦截器
 * 
 * @author 天航星
 * @date 2024-07-05 15:03
 */
public class ImageCellWriteHandler implements CellWriteHandler {

    private final Map<String,List<ImageData>> imageDataMap = new HashMap<>();

    /**
     * 单元格的图片最大张数(每列的单元格图片张数不确定,单元格宽度需按照张数最多的长度来设置)
     */
    private final AtomicReference<Integer> MAX_IMAGE_SIZE = new AtomicReference<>(0);
    
    @Override
    public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, WriteCellData<?> cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        
        if (isHead) {
            return;
        }
        // 将单元格图片数据复制出来,清空单元格图片数据
        if (!ObjUtil.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<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        
        if (isHead || ObjUtil.isEmpty(cellDataList)) {
            return;
        }
        String key = cell.getRowIndex() + "_" + cell.getColumnIndex();
        List<ImageData> imageDataList = imageDataMap.get(key);
        if (ObjUtil.isEmpty(imageDataList)) {
            return;
        }
        if (imageDataList.size() > MAX_IMAGE_SIZE.get()) {
            MAX_IMAGE_SIZE.set(imageDataList.size());
        }
        Sheet sheet = cell.getSheet();
        // 设置单元格行高
        sheet.getRow(cell.getRowIndex()).setHeight((short) 900);
        // 设置单元格列宽(乘多少代表容纳多少张图片)
        sheet.setColumnWidth(cell.getColumnIndex(), MAX_IMAGE_SIZE.get() > 0 ? 3493 * MAX_IMAGE_SIZE.get() : 3493);
        // 插入图片
        for (int i = 0; i < imageDataList.size(); i++) {
            ImageData imageData = imageDataList.get(i);
            if (ObjUtil.isEmpty(imageData)) {
                continue;
            }
            byte[] image = imageData.getImage();
            this.insertImage(sheet, cell, image, i);
        }
        imageDataMap.remove(key);
    }
    
    private void insertImage(Sheet sheet, Cell cell, byte[] pictureData, int i) {
        
        // 图片宽度
        int pictureWidth = Units.pixelToEMU(100);
        int index = sheet.getWorkbook().addPicture(pictureData, HSSFWorkbook.PICTURE_TYPE_PNG);
        Drawing<?> drawing = sheet.getDrawingPatriarch();
        if (ObjUtil.isEmpty(drawing)) {
            drawing = sheet.createDrawingPatriarch();
        }
        CreationHelper helper = sheet.getWorkbook().getCreationHelper();
        ClientAnchor anchor = helper.createClientAnchor();
        // 设置图片在哪个单元格中
        anchor.setCol1(cell.getColumnIndex());
        anchor.setCol2(cell.getColumnIndex());
        anchor.setRow1(cell.getRowIndex());
        anchor.setRow2(cell.getRowIndex() + 1);
        // 设置图片在单元格中的位置
        anchor.setDx1(pictureWidth * i);
        anchor.setDx2(pictureWidth + pictureWidth * i);
        anchor.setDy1(0);
        anchor.setDy2(0);
        // 设置图片可以随着单元格移动
        anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
        drawing.createPicture(anchor, index);
    }
}
  1. 写入时引用
EasyExcel.write("Excel文件名称.xlsx", DemoData.class).sheet("测试").registerWriteHandler(new ImageCellWriteHandler()).doWrite(new DemoData());

环境:

  • JDK:1.8.0_202
  • SpringBoot:2.7.17
  • EasyExcel:3.3.2

标签:EasyExcel,单元格,excel,alibaba,cell,宽度,import,com
From: https://www.cnblogs.com/skysailstar/p/18286394

相关文章

  • EasyExcel简单使用教程(大量数据分批入库;非固定Excel解析)
    前言本文记录了如何使用EasyExcel完成简单的表格解析操作,同时实现了大量数据情况下数据的分次批量入库,并记录每条数据入库的状态,以便进行结果统计。固定模板及表数据格式的解析实现Excel模板内容对应的实体类importcom.alibaba.excel.annotation.ExcelIgnore;importcom.al......
  • 使用EasyExcel的AnalysisEventListener读取EXCEL导入数据
    1、实体对象VOimportcom.alibaba.excel.annotation.ExcelProperty;importlombok.Data;@DatapublicclassPrizeLogImportExcelVO{@ExcelProperty("订单编号")privateStringprizeSn;@ExcelProperty("快递公司")privateStringexpressN......
  • 【python小记】使用openpyxl库在同一个工作表下复制单元格(包括它们的值、样式和合并属
    fromopenpyxlimportload_workbook#加载工作簿和工作表wb=load_workbook('test.xlsx')sheet=wb['sheet1']#定义一个函数来复制样式defcopy_style(source_cell,target_cell):ifsource_cell.has_style:target_cell.font=source_cell.font.co......
  • EasyExcel 填充+写入
    使用EasyExcel导出Excel时,有时会遇到如下情况:既要根据模板填充某些sheet又要根据业务写入某些sheetEasyExcel官方没有提供这样的示例,经过自己的研究和实验,得到了如下步骤:定义导出文件名StringfileName="测试.xlsx";获取模板文件InputStreamtemplateFile......
  • QTableWidget单元格设置控件居中以及背景颜色问题
    QTableWidget的单元格如果要显示其他控件,可以使用setCellWidget,但是控件没有居中,要想使控件居中,可以先创建一个QWidget对象,并设置布局器,然后将控件放到布局器中,并把这个QWidget对象放到单元格内,但是此时若要设置单元格的背景颜色,QTableWidget只能通过设置QTableWidgetItem的颜色来......
  • EasyExcel 自定义表头颜色
    publicvoidexport(ObjectDTOdto,HttpServletResponseresponse){try{if(ObjectUtils.isEmpty(dto.getObjNumberList())){thrownewBusinessException("编号不允许为空");}ListRespresult=o......
  • js前端通过xlsx 实现带单元格合并的excel导出
    tableToExcelWithMerge(rows){constThis=this;letjsonData=This.formatExcelData(rows);console.log("dwadwa",jsonData)//创建工作簿constwb=XLSX.utils.book_new();//转换数据为工作表constws=XLSX.utils.aoa......
  • 2713. 矩阵中严格递增的单元格数 Hard
    给你一个下标从 1 开始、大小为 mxn 的整数矩阵 mat,你可以选择任一单元格作为 起始单元格 。从起始单元格出发,你可以移动到 同一行或同一列 中的任何其他单元格,但前提是目标单元格的值 严格大于 当前单元格的值。你可以多次重复这一过程,从一个单元格移动到另一......
  • EasyExcel 无法读取图片?用poi写了一个工具类
    在平时的开发中,经常要开发Excel的导入导出功能。一般使用poi或者EasyExcel开发,使用poi做excel比较复杂,大部分开发都会使用EasyExcel因为一行代码就能实现导入和导出的功能。但是EasyExcel不支持图片的读的操作,本文操作如何实现图片的读和写的功能。在EasyExcel......
  • 【java】解决EasyExcel读取InputStream时解析不到excel文件类型的问题
    正常利用EasyExcel读取excel中sheet时会调用如下接口:publicstaticExcelReaderBuilderread(StringpathName,ReadListenerreadListener){returnread((String)pathName,(Class)null,readListener);}publicstaticExcelReaderBuilderread(Stringp......