Java使用EasyExcel导出图片(原比例大小)到Excel中

EasyExcel导出图片

又开始写Excel导出的需求了,哈哈哈......

目前的需求是将图表分析对的饼图和折线图,也就是一张完整的图片单独导出到Excel中

为了方便客户在业务报告时,可以使用数据分析图片,从而更清晰准确地展示数据趋势

因此关键点是将图片原比例尺寸大小导出,不能进行压缩

原数据是由图表📈+表格数据组成,下图所示:

现在需要将上述数据,分两个Sheet导出到Excel:图表📈Sheet +表格数据Sheet

关于表格数据导出,此处就不做展示了,往期的Excel导出有文章说明,此文只导出图表📈Sheet

步骤1:将图片保存成url

将图片转为url的形式传参

javascript 复制代码
{
  "imagePath": "http://www.echola.com/8pJTiC_1724644117200.png",
   ...... //其他参数
}

步骤2:自定义图片导出工具类

java 复制代码
@Slf4j
public class CustomImageStrategy implements CellWriteHandler {

    private final HashMap<String, List<ImageData>> 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<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        if (isHead || CollectionUtils.isEmpty(cellDataList)) {
            return;
        }
        String key = cell.getRowIndex() + "_" + cell.getColumnIndex();
        List<ImageData> imageDataList = imageDataMap.get(key);
        if (CollectionUtils.isEmpty(imageDataList)) {
            return;
        }

        // 插入图片
        for (int i = 0; i < imageDataList.size(); i++) {
            ImageData imageData = imageDataList.get(i);
            if (ObjectUtils.isEmpty(imageData)) {
                continue;
            }
            byte[] image = imageData.getImage();
            this.insertImage(writeSheetHolder.getSheet(), cell, image, i);
        }
        imageDataMap.remove(key);
    }

    private void insertImage(Sheet sheet, Cell cell, byte[] pictureData, int i) {
        // 读取图片的宽度和高度
        int pictureWidth = 0;
        int pictureHeight = 0;
        try (ByteArrayInputStream bis = new ByteArrayInputStream(pictureData)) {
            BufferedImage bufferedImage = ImageIO.read(bis);
            pictureWidth = bufferedImage.getWidth();
            pictureHeight = bufferedImage.getHeight();
        } catch (Exception e) {
            log.error("Error reading image dimensions", e);
        }

        // 将像素转换为 EMU 单位
        int emuWidth = Units.pixelToEMU(pictureWidth);
        int emuHeight = Units.pixelToEMU(pictureHeight);
        int index = sheet.getWorkbook().addPicture(pictureData, Workbook.PICTURE_TYPE_PNG);
        Drawing<?> drawing = sheet.getDrawingPatriarch();
        if (drawing == null) {
            drawing = sheet.createDrawingPatriarch();
        }
        CreationHelper helper = sheet.getWorkbook().getCreationHelper();
        ClientAnchor anchor = helper.createClientAnchor();
        // 设置图片在哪个单元格中
        anchor.setCol1(cell.getColumnIndex());
        anchor.setCol2(cell.getColumnIndex() + 1);
        anchor.setRow1(cell.getRowIndex());
        anchor.setRow2(cell.getRowIndex() + 1);

        // 设置图片在单元格中的位置
        // 横向偏移量
        anchor.setDx1(0);
        anchor.setDx2(emuWidth);
        // 纵向偏移量
        anchor.setDy1(0);
        anchor.setDy2(emuHeight);

        // 设置图片可以随着单元格移动
        anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
        drawing.createPicture(anchor, index);
        // 设置行高和列宽为图片的实际大小
        Row row = sheet.getRow(cell.getRowIndex());
        if (row == null) {
            row = sheet.createRow(cell.getRowIndex());
        }
        // 设置行高,1像素大约等于0.75点
        row.setHeightInPoints((float) (pictureHeight * 0.75));

        // 设置列宽,列宽单位是1/256个字符,1个字符大约为7像素
        sheet.setColumnWidth(cell.getColumnIndex(), pictureWidth * 37);
    }

步骤3:导出图片

java 复制代码
public void exportAnalysis(EnergyStatisticDTO param, HttpServletResponse response) {
        String fileName = "数据分析" + DateUtil.format(new Date(), DatePattern.PURE_DATE_FORMAT);
        try {
            EasyExcelUtils.setResponse(response, fileName);
            ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();
            //各用电用途趋势
            String sheetName = "数据分析图示";
            this.meterImageSheet(sheetName, param.getImagePath(), excelWriter);
            String imagePath = param.getImagePath();
            if (StringUtils.isEmpty(imagePath)) return;
            //支持多图片导出,此处只是单图片
            List<ImageDTO> imageList = new ArrayList<>();
            ImageDTO imageDTO = new ImageDTO();
            imageDTO.setImageUrl(Collections.singletonList(imagePath));
            imageList.add(imageDTO);
            WriteSheet imageSheet = EasyExcel.writerSheet(1, sheetName)
                    .registerWriteHandler(new CustomImageStrategy())
                    .build();
            excelWriter.write(imageList, imageSheet);
            excelWriter.finish();
        } catch (Exception e) {
            log.error("数据分析:{}", e.getMessage());
        }
    }

Excel导出图片效果图

可以看出和Web的图表的大小是基本一致的

撒花完结......

相关推荐
2501_930707787 小时前
使用 C# 代码读取或删除 Excel 文档属性
excel
hikktn7 小时前
Excel 日期格式统一治理:从“显示不全“到“自动兼容“的完整方案
windows·python·excel
霸道流氓气质9 小时前
Spring Boot 大数据量 Excel 导入导出功能实现指南
spring boot·后端·excel
霸道流氓气质10 小时前
Java 单元测试生成大量 Excel 测试数据实战指南
java·单元测试·excel
IT WorryFree11 小时前
FortiGate常用资产 OID 清单,配套 Excel 台账模板字段
网络·人工智能·excel
MyFreeIT11 小时前
Excel Enable Content
excel
E_ICEBLUE11 小时前
将 Excel 表格插入 Word 文档的三种实用方案(Python 自动化)
python·word·excel
俊哥工具11 小时前
027免费开源硬盘检测工具,一键查看健康度,杜绝数据丢失
pdf·电脑·word·excel·音视频
不恋水的雨1 天前
easyexcel快速填充大数据量不覆盖后面的行解决方式
java·excel·poi
靖待1 天前
【解决方法】python写Excel单元格截断长文本
python·excel·解决方法