[alibaba/easyexcel]模板合并单元格 ,图片导出在合并单元格中,只会显示在合并单元格的第一个单元格中,跨不了单元格

2024-05-09 460 views
4
 /**
     * 生成有图片的excel
     *
     * @param demoDataList 数据列表
     * @param fileName     生成文件路径
     */
    private void genImageExcel(List<ImageDemoData> demoDataList, String fileName) {
        if (CollectionUtils.isEmpty(demoDataList)) {
            return;
        }

        //图片列最大图片数
        AtomicReference<Integer> maxImageSize = new AtomicReference<>(0);
        demoDataList.forEach(item -> {
            if (CollectionUtils.isNotEmpty(item.getImagePathList()) && item.getImagePathList().size() > maxImageSize.get()) {
                maxImageSize.set(item.getImagePathList().size());
            }
        });

        //设置列长度所用类
        AutoColumnWidthStyleStrategy longWidth = new AutoColumnWidthStyleStrategy();
        List<ImageData> imageDataListAll = new ArrayList<>();
        demoDataList.forEach(item -> {
            WriteCellData<Void> writeCellData = new WriteCellData<>();
            if (CollectionUtils.isNotEmpty(item.getImagePathList())) {
                //每张图片间距
                Integer splitWidth = 2;
                //每张图片的长度
                Integer imageWidth = 80;
                //图片列的最大长度
                Integer sumWidth = maxImageSize.get() * (imageWidth + splitWidth);

                List<ImageData> imageDataList = new ArrayList<>();
                List<String> imagePathList = item.getImagePathList();
                for (int i = 1; i <= imagePathList.size(); i++) {
                    String path = imagePathList.get(i - 1);
                    Integer left = imageWidth * (i - 1) + i * splitWidth;
                    Integer right = sumWidth - imageWidth - left;
                    ImageData imageData = new ImageData();
                    try {
                        imageData.setImage(FileUtils.readFileToByteArray(new File(path)));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    imageData.setImageType(ImageData.ImageType.PICTURE_TYPE_PNG);
                    //距离单元格顶部距离
                    imageData.setTop(1);
                    //距离单元格底部距离
                    imageData.setBottom(1);
                    //距离单元格左边距离
                    imageData.setLeft(left);
                    //距离单元格右边距离
                    imageData.setRight(right);
                    imageData.setAnchorType(ClientAnchorData.AnchorType.DONT_MOVE_DO_RESIZE);
                    imageDataList.add(imageData);
                }
                writeCellData.setImageDataList(imageDataList);
                imageDataListAll.addAll(imageDataList);
                Map<String, Integer> zdyColumnWidth = new HashMap<>();
                //图片列名称,对应导出对象的列名称,图片列长度
                zdyColumnWidth.put("上传图片", sumWidth / 6);
                longWidth.setZdyColumnWidth(zdyColumnWidth);
            }
            item.setWriteCellDataFile(writeCellData);
        });

        ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(new File("C:\\Users\\JUNSHI\\Desktop\\excelrepeat.xlsx")).build();
        FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
        WriteSheet writeSheet = EasyExcel.writerSheet(0).build();
        excelWriter.fill(new FillWrapper("data", demoDataList), fillConfig, writeSheet);
        excelWriter.finish();

    }

异常提示 请提供完整的异常提示,记住是全部异常! 建议描述

回答

2
模板导出图片Excel简单示例:

版本:EasyExcel 3.0.x以上

导出模板: Image

导出代码:

package com.alibaba.easyexcel.test.demo.fill.img;

import com.alibaba.easyexcel.test.util.TestFileUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.data.ImageData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.util.FileUtils;
import com.alibaba.excel.util.MapUtils;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
* 模板导出图片测试
*
* EasyExcel版本:3.0.x以上
*
*/
public class FillImageTest {

    /**
     * 图片导出
     * <p>
     * 1. 创建excel对应的实体对象 参照{@link com.alibaba.easyexcel.test.demo.write.WriteTest#imageWrite}
     * <p>
     * 2. 模板中写入WriteCellData类型的变量
     * <p>
     * 3. 模板导出
     */
    @Test
    public void imageWrite() throws Exception {
        // 模板文件
        String templateFileName = TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "image.xlsx";
        // 导出文件路径
        String fileName = TestFileUtil.getPath() + "imageWrite" + System.currentTimeMillis() + ".xlsx";
        // 图片路径
        String imagePath = TestFileUtil.getPath() + "converter" + File.separator + "img.jpg";

        // 设置图片数据
        File[] files = {new File(imagePath), new File(imagePath)};
        WriteCellData<Void> imageCells = this.imageCells(files);

        // 构造map
        Map<String, Object> map = MapUtils.newHashMap();
        map.put("images", imageCells);

        // 导出Excel
        EasyExcel.write(fileName)
            .withTemplate(templateFileName)
            .sheet()
            .doFill(map);

        System.out.println("导出文件位置:" + fileName);
    }

    /**
     * Excel所有图片设置
     * @param files
     * @return
     * @throws IOException
     */
    private WriteCellData<Void> imageCells(File[] files) throws IOException {
        if (files == null) {
            return null;
        }

        WriteCellData<Void> writeCellData = new WriteCellData<>();
        // 这里可以设置为 EMPTY 则代表不需要其他数据了
        //writeCellData.setType(CellDataTypeEnum.EMPTY);

        // 可以放入多个图片
        List<ImageData> imageDataList = new ArrayList<>();
        writeCellData.setImageDataList(imageDataList);

        for (int i = 0; i < files.length; i++) {
            // 限制最多3张图片
            if (i >= 3) {
                break;
            }

            ImageData imageData = new ImageData();
            imageDataList.add(imageData);
            // 设置图片
            imageData.setImage(FileUtils.readFileToByteArray(files[i]));
            // 图片类型
            //imageData.setImageType(ImageData.ImageType.PICTURE_TYPE_PNG);
            // 上 右 下 左 需要留空,这个类似于 css 的 margin;这里实测 不能设置太大 超过单元格原始大小后 打开会提示修复。暂时未找到很好的解法。
            imageData.setTop(2);
            imageData.setRight(10);
            imageData.setBottom(2);
            imageData.setLeft(10);

            // * 设置图片的位置。Relative表示相对于当前的单元格index。first是左上点,last是对角线的右下点,这样确定一个图片的位置和大小。
            // 目前填充模板的图片变量是images,index:row=7,column=0。所有图片都基于此位置来设置相对位置
            // 第1张图片相对位置
            if (i == 0) {
                imageData.setRelativeFirstRowIndex(0);
                imageData.setRelativeFirstColumnIndex(0);
                imageData.setRelativeLastRowIndex(32);
                imageData.setRelativeLastColumnIndex(3);
            } else if (i == 1) {
                // 第2张图片相对位置
                imageData.setRelativeFirstRowIndex(34);
                imageData.setRelativeFirstColumnIndex(0);
                imageData.setRelativeLastRowIndex(66);
                imageData.setRelativeLastColumnIndex(3);
            } else if (i == 2) {
                // 第3张图片相对位置
                imageData.setRelativeFirstRowIndex(68);
                imageData.setRelativeFirstColumnIndex(0);
                imageData.setRelativeLastRowIndex(100);
                imageData.setRelativeLastColumnIndex(3);
            }
        }

        return writeCellData;
    }

}

导出结果: Image

3

import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.metadata.data.ImageData; import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.util.FileUtils; import com.alibaba.excel.util.MapUtils; import org.junit.Test; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map;

/**

  • 模板导出图片测试
  • EasyExcel版本:3.0.x以上
  • */ public class FillImageTest {

    /**

    • 图片导出
      1. 创建excel对应的实体对象 参照{@link com.alibaba.easyexcel.test.demo.write.WriteTest#imageWrite}
      1. 模板中写入WriteCellData类型的变量
      1. 模板导出 */ @Test public void imageWrite() throws Exception { // 模板文件 String templateFileName = TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "image.xlsx"; // 导出文件路径 String fileName = TestFileUtil.getPath() + "imageWrite" + System.currentTimeMillis() + ".xlsx"; // 图片路径 String imagePath = TestFileUtil.getPath() + "converter" + File.separator + "img.jpg";

      // 设置图片数据 File[] files = {new File(imagePath), new File(imagePath)}; WriteCellData imageCells = this.imageCells(files);

      // 构造map Map<String, Object> map = MapUtils.newHashMap(); map.put("images", imageCells);

      // 导出Excel EasyExcel.write(fileName) .withTemplate(templateFileName) .sheet() .doFill(map);

      System.out.println("导出文件位置:" + fileName); }

    /**

    • Excel所有图片设置
    • @param files
    • @return
    • @throws IOException */ private WriteCellData imageCells(File[] files) throws IOException { if (files == null) { return null; }

      WriteCellData writeCellData = new WriteCellData<>(); // 这里可以设置为 EMPTY 则代表不需要其他数据了 //writeCellData.setType(CellDataTypeEnum.EMPTY);

      // 可以放入多个图片 List imageDataList = new ArrayList<>(); writeCellData.setImageDataList(imageDataList);

      for (int i = 0; i < files.length; i++) { // 限制最多3张图片 if (i >= 3) { break; }

      ImageData imageData = new ImageData();
      imageDataList.add(imageData);
      // 设置图片
      imageData.setImage(FileUtils.readFileToByteArray(files[i]));
      // 图片类型
      //imageData.setImageType(ImageData.ImageType.PICTURE_TYPE_PNG);
      // 上 右 下 左 需要留空,这个类似于 css 的 margin;这里实测 不能设置太大 超过单元格原始大小后 打开会提示修复。暂时未找到很好的解法。
      imageData.setTop(2);
      imageData.setRight(10);
      imageData.setBottom(2);
      imageData.setLeft(10);
      
      // * 设置图片的位置。Relative表示相对于当前的单元格index。first是左上点,last是对角线的右下点,这样确定一个图片的位置和大小。
      // 目前填充模板的图片变量是images,index:row=7,column=0。所有图片都基于此位置来设置相对位置
      // 第1张图片相对位置
      if (i == 0) {
          imageData.setRelativeFirstRowIndex(0);
          imageData.setRelativeFirstColumnIndex(0);
          imageData.setRelativeLastRowIndex(32);
          imageData.setRelativeLastColumnIndex(3);
      } else if (i == 1) {
          // 第2张图片相对位置
          imageData.setRelativeFirstRowIndex(34);
          imageData.setRelativeFirstColumnIndex(0);
          imageData.setRelativeLastRowIndex(66);
          imageData.setRelativeLastColumnIndex(3);
      } else if (i == 2) {
          // 第3张图片相对位置
          imageData.setRelativeFirstRowIndex(68);
          imageData.setRelativeFirstColumnIndex(0);
          imageData.setRelativeLastRowIndex(100);
          imageData.setRelativeLastColumnIndex(3);
      }

      }

      return writeCellData; }

}

2
模板导出图片Excel简单示例:

版本:EasyExcel 3.0.x以上

导出模板: Image

导出代码:

package com.alibaba.easyexcel.test.demo.fill.img;

import com.alibaba.easyexcel.test.util.TestFileUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.data.ImageData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.util.FileUtils;
import com.alibaba.excel.util.MapUtils;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
* 模板导出图片测试
*
* EasyExcel版本:3.0.x以上
*
*/
public class FillImageTest {

    /**
     * 图片导出
     * <p>
     * 1. 创建excel对应的实体对象 参照{@link com.alibaba.easyexcel.test.demo.write.WriteTest#imageWrite}
     * <p>
     * 2. 模板中写入WriteCellData类型的变量
     * <p>
     * 3. 模板导出
     */
    @Test
    public void imageWrite() throws Exception {
        // 模板文件
        String templateFileName = TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "image.xlsx";
        // 导出文件路径
        String fileName = TestFileUtil.getPath() + "imageWrite" + System.currentTimeMillis() + ".xlsx";
        // 图片路径
        String imagePath = TestFileUtil.getPath() + "converter" + File.separator + "img.jpg";

        // 设置图片数据
        File[] files = {new File(imagePath), new File(imagePath)};
        WriteCellData<Void> imageCells = this.imageCells(files);

        // 构造map
        Map<String, Object> map = MapUtils.newHashMap();
        map.put("images", imageCells);

        // 导出Excel
        EasyExcel.write(fileName)
            .withTemplate(templateFileName)
            .sheet()
            .doFill(map);

        System.out.println("导出文件位置:" + fileName);
    }

    /**
     * Excel所有图片设置
     * @param files
     * @return
     * @throws IOException
     */
    private WriteCellData<Void> imageCells(File[] files) throws IOException {
        if (files == null) {
            return null;
        }

        WriteCellData<Void> writeCellData = new WriteCellData<>();
        // 这里可以设置为 EMPTY 则代表不需要其他数据了
        //writeCellData.setType(CellDataTypeEnum.EMPTY);

        // 可以放入多个图片
        List<ImageData> imageDataList = new ArrayList<>();
        writeCellData.setImageDataList(imageDataList);

        for (int i = 0; i < files.length; i++) {
            // 限制最多3张图片
            if (i >= 3) {
                break;
            }

            ImageData imageData = new ImageData();
            imageDataList.add(imageData);
            // 设置图片
            imageData.setImage(FileUtils.readFileToByteArray(files[i]));
            // 图片类型
            //imageData.setImageType(ImageData.ImageType.PICTURE_TYPE_PNG);
            // 上 右 下 左 需要留空,这个类似于 css 的 margin;这里实测 不能设置太大 超过单元格原始大小后 打开会提示修复。暂时未找到很好的解法。
            imageData.setTop(2);
            imageData.setRight(10);
            imageData.setBottom(2);
            imageData.setLeft(10);

            // * 设置图片的位置。Relative表示相对于当前的单元格index。first是左上点,last是对角线的右下点,这样确定一个图片的位置和大小。
            // 目前填充模板的图片变量是images,index:row=7,column=0。所有图片都基于此位置来设置相对位置
            // 第1张图片相对位置
            if (i == 0) {
                imageData.setRelativeFirstRowIndex(0);
                imageData.setRelativeFirstColumnIndex(0);
                imageData.setRelativeLastRowIndex(32);
                imageData.setRelativeLastColumnIndex(3);
            } else if (i == 1) {
                // 第2张图片相对位置
                imageData.setRelativeFirstRowIndex(34);
                imageData.setRelativeFirstColumnIndex(0);
                imageData.setRelativeLastRowIndex(66);
                imageData.setRelativeLastColumnIndex(3);
            } else if (i == 2) {
                // 第3张图片相对位置
                imageData.setRelativeFirstRowIndex(68);
                imageData.setRelativeFirstColumnIndex(0);
                imageData.setRelativeLastRowIndex(100);
                imageData.setRelativeLastColumnIndex(3);
            }
        }

        return writeCellData;
    }

}

导出结果: Image

4

解决好了吗 @zhuangjiaju, 我也遇到这个问题了

2

在填充的时候设置起始单元格和结束单元格可以让图片跨单元格 。不过我遇到的是在合并单元格中均匀填充多张图片,一直弄不好单元格的坐标

//设置图片单元格位置
anchor.setCol1(currentColumnIndex);
anchor.setRow1(currentRowIndex);

//结束行+1
anchor.setCol2(currentColumnIndex);
anchor.setRow2(currentRowIndex + 1);

 //设置图片在单元格的坐标
anchor.setDx1(imgIndex * picWidth);
anchor.setDy1(0);

anchor.setDx2((imgIndex + 1) * picWidth);
anchor.setDy2(0);