(解决)easypoi图片导出只占用一个单元格

前提

本解决方案来源于网络,因解决自己需求,因此自行记录起来,如有侵权请联系我。

依赖环境

easypoi——依赖版本3.1.0

问题原因

easypoi源代码中创建图片的方法中,没有对图片合并单元格后计算单元格合并,仅仅是计算图片所在的一个单元格位置,因此只填充一个单元格。

/**
 * 图片类型的Cell
 */
public void createImageCell(Cell cell, double height,
                            String imagePath, byte[] data) throws Exception {
    if (height > cell.getRow().getHeight()) {
        cell.getRow().setHeight((short) height);
    }
    ClientAnchor anchor;
    if (type.equals(ExcelType.HSSF)) {
        anchor = new HSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1),
                cell.getRow().getRowNum() + 1);
    } else {
        anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1),
                cell.getRow().getRowNum() + 1);
    }
    if (StringUtils.isNotEmpty(imagePath)) {
        data = ImageCache.getImage(imagePath);
    }
    if (data != null) {
        PoiExcelGraphDataUtil.getDrawingPatriarch(cell.getSheet()).createPicture(anchor,
                cell.getSheet().getWorkbook().addPicture(data, getImageType(data)));
    }
}

解决方案

对上述代码进行重写

/**
     * 图片类型的Cell
     */
public void createImageCell(Cell cell, double height,
                                String imagePath, byte[] data) throws Exception {
    if (height > cell.getRow().getHeight()) {
        cell.getRow().setHeight((short) height);
    }
    
    //重写部分开始
    //获取当前单元格所在的sheet
    Sheet sheet = cell.getRow().getSheet();
    //获取当前sheet页中的所有合并单元格信息
    List<CellRangeAddress> mergedRegions = sheet.getMergedRegions();
    //获取当前单元格的开始列号
    int firstColumn = (short)cell.getColumnIndex();
    //获取当前单元格的开始行号
    int firstRow = cell.getRow().getRowNum();
    //获取当前单元格的结束列号
    int lastColumn = (short)(cell.getColumnIndex());
    //获取当前单元格的结束行号
    int lastRow = cell.getRow().getRowNum();
    for(CellRangeAddress mergedRegion : mergedRegions){
        //判断当前单元格是否包含合并行或和并列 当前单元格的所有行号和列号都包含在合并域内 则认为当前单元格存在合并行或和并列
        if(cell.getColumnIndex()>=mergedRegion.getFirstColumn()
                && cell.getColumnIndex()<=mergedRegion.getLastColumn()
                && cell.getRow().getRowNum()>=mergedRegion.getFirstRow()
                && cell.getRow().getRowNum()<=mergedRegion.getLastRow()){
            //获取合并域的开始行号
            firstRow = mergedRegion.getFirstRow();
            //获取合并域的结束行号
            lastRow = mergedRegion.getLastRow();
            //获取合并域的开始列号
            firstColumn = mergedRegion.getFirstColumn();
            //获取合并域的结束列号
            lastColumn = mergedRegion.getLastColumn();
            break;
        }
    }
    //重写部分结束

    ClientAnchor anchor;

    if(this.type.equals(ExcelType.HSSF)) {
    	//重写前
    	//anchor = new HSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), cell.getRow().getRowNum() + 1);
    	//重写后
        anchor = new HSSFClientAnchor(0, 0, 0, 0, (short)firstColumn, firstRow, (short)(lastColumn+1), lastRow+1);
    } else {
    	//重写前
    	//anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), cell.getRow().getRowNum() + 1);
    	//重写后
        anchor = new XSSFClientAnchor(0, 0, 0, 0, (short)firstColumn, firstRow, (short)(lastColumn+1), lastRow+1);
    }

    if(StringUtils.isNotEmpty(imagePath)) {
        data = ImageCache.getImage(imagePath);
    }

    if(data != null) {
        PoiExcelGraphDataUtil.getDrawingPatriarch(cell.getSheet()).createPicture((ClientAnchor)anchor, cell.getSheet().getWorkbook().addPicture(data, this.getImageType(data)));
    }
}

重写jar中的方法

  1. 找到要重写的方法所在的包,如上述方法所在的包为
    package cn.afterturn.easypoi.excel.export.base;
  1. 在src目录下,创建新建一个同包名同类名的类
  2. 将源代码完整的复制到新创建的类
  3. 在新创建的类中,修改对应的要重写的方法中的代码(注意不要删除原有的方法以及参数,但是可以新增一些方法)

原理

编译输出的时候会优先使用我们src下面的类,而不是优先使用Jar包里面的类,这样就达到了覆盖jar包方法的目的。

原文地址:https://www.cnblogs.com/z1rar1/p/14269037.html