java导入Excel(带图片)-暂支持浮动式图片

相关依赖

可自行剔除未使用的依赖

<!-- Apache POI - OOXML (for .docx, .pptx, .xlsx) -->
		<dependency>
			<groupId>cn.afterturn</groupId>
			<artifactId>easypoi-base</artifactId>
			<version>3.2.0</version>
		</dependency>
		<dependency>
			<groupId>cn.afterturn</groupId>
			<artifactId>easypoi-web</artifactId>
			<version>3.2.0</version>
		</dependency>
		<dependency>
			<groupId>cn.afterturn</groupId>
			<artifactId>easypoi-annotation</artifactId>
			<version>3.2.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>4.1.2</version>
		</dependency>

		<!-- xls(07) -->
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>4.1.2</version>
		</dependency>
导入工具
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.sgcloud.clp.common.file.core.FileProperties;
import com.sgcloud.clp.common.file.core.FileTemplate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.apache.poi.ss.usermodel.*;
​
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.*;
​
/**
 * Excel导入 带图片
 * 暂仅支持浮动式图片
 *
 * @param <T>
 */
@Slf4j
public class ExcelImporter<T> {
​
    private final Class<T> entityType;
    private FileTemplate fileTemplate;
    private FileProperties properties;
    private String path;
​
    public ExcelImporter(Class<T> entityType, FileTemplate fileTemplate, FileProperties properties, String path) {
        this.entityType = entityType;
        this.fileTemplate = fileTemplate;
        this.properties = properties;
        this.path = path;
    }
​
    /**
     * 从Excel文件导入数据到实体列表。
     *
     * @param is Excel文件的InputStream。
     * @return 导入的实体列表。
     */
    public List<T> importExcel(InputStream is) {
        List<T> entities = new ArrayList<>();
​
        try {
            Workbook workbook = getWorkbook(is);
​
            // 处理图片
            Map<Integer, Map<Integer, byte[]>> pictureMap = processFloatingPictures(workbook);
​
            // 处理数据
            Map<Integer, T> rowEntities = processData(workbook);
​
            // 处理数据图片关联关系
            entities.addAll(processPictures2Entity(rowEntities, pictureMap));
​
        } catch (Exception e) {
            log.error("导入Excel时出错:{}", e);
        }
​
        return entities;
    }
​
​
    private Workbook getWorkbook(InputStream is) throws IOException {
        return WorkbookFactory.create(is);
    }
​
    /**
     * 处理浮动图片
     *
     * @param workbook
     * @return 图片数据的映射,以行和列为键,字节数组为值
     */
    private Map<Integer, Map<Integer, byte[]>> processFloatingPictures(Workbook workbook) {
        Map<Integer, Map<Integer, byte[]>> pictureMap = new HashMap<>();
​
        for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
            Sheet sheet = workbook.getSheetAt(i);
            Drawing<?> drawing = sheet.getDrawingPatriarch();
​
            if (drawing != null) {
                Iterator<?> iterator = drawing.iterator();
​
                while (iterator.hasNext()) {
                    Shape shape = (Shape) iterator.next();
                    if (shape instanceof Picture) {
                        Picture picture = (Picture) shape;
                        ClientAnchor anchor = picture.getClientAnchor();
                        int row = anchor.getRow1();
                        int column = anchor.getCol1();
                        byte[] pictureByte = picture.getPictureData().getData();
​
                        pictureMap.computeIfAbsent(row, k -> new HashMap<>())
                                .put(column, pictureByte);
                    }
                }
            }
        }
​
        return pictureMap;
    }
​
    /**
     * 处理数据并关联图片
     *
     * @param workbook Excel Workbook
     * @return 实体列表
     */
    private Map<Integer, T> processData(Workbook workbook) {
        Map<Integer, T> entityMap = new HashMap<>();
​
        for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
            Sheet sheet = workbook.getSheetAt(i);
​
            for (int rowIndex = 2; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
                Row excelRow = sheet.getRow(rowIndex);
                int rowNum = excelRow.getRowNum(); // 行号
                try {
                    // 实例化实体类
                    T entity = entityType.getDeclaredConstructor().newInstance();
​
                    for (Field field : entityType.getDeclaredFields()) {
                        ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
                        if (excelProperty != null) {
                            int index = excelProperty.index();
                            Cell cell = excelRow.getCell(index);
                            // 设置实体类属性值
                            setEntityPropertyFromCell(entity, field, cell);
                        }
                    }
​
                    entityMap.put(rowNum, entity);
                } catch (Exception e) {
                    log.error("实例化实体类失败,Exception:{}", e);
                }
            }
        }
        return entityMap;
    }
​
    /**
     * 图片关联实体类
     *
     * @param entityMap
     * @param imgMap
     */
    private List<T> processPictures2Entity(Map<Integer, T> entityMap, Map<Integer, Map<Integer, byte[]>> imgMap) {
        List<T> entities = Lists.newArrayList();
​
        entityMap.keySet().forEach(k -> {
            T entity = entityMap.get(k);
            Map<Integer, byte[]> rowImg = imgMap.get(k);
            for (Field field : entityType.getDeclaredFields()) {
                ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
                if (excelProperty == null) continue;
​
                int index = excelProperty.index();    // 列号
                int type = excelProperty.type();    // 类型
​
                try {
                    if (type == 2 && index != -1) {
                        field.setAccessible(true);
                        // 根据列号设置图片
                        String url = processImageSingle(rowImg.get(index));
                        field.set(entity, url);
                    }
                } catch (IllegalAccessException e) {
                    log.error("[{}]设置属性失败, Exception:{}", field.getName(), e);
                }
            }
            entities.add(entity);
        });
​
        return entities;
    }
​
    private boolean isValidPicture(Picture picture) {
        try {
            byte[] imageData = picture.getPictureData().getData();
            return imageData != null && imageData.length > 0;
        } catch (Exception e) {
            // 记录异常信息或进行其他处理
            log.warn("验证图像有效性时出现异常:{}", e.getMessage());
            return false;
        }
    }
​
    /**
     * 设置实体其他属性
     *
     * @param entity
     * @param field
     * @param cell
     */
    private void setEntityPropertyFromCell(T entity, Field field, Cell cell) {
        try {
            if (cell != null) {
                field.setAccessible(true);
                Class<?> fieldType = field.getType();
​
                if (fieldType == String.class) {
                    field.set(entity, cell.getStringCellValue());
                } else if (fieldType == LocalDateTime.class) {
                    if (cell.getCellType() == CellType.NUMERIC) {
                        field.set(entity, cell.getLocalDateTimeCellValue());
                    } else {
                        field.set(entity, null);
                    }
                }
            }
        } catch (IllegalAccessException e) {
            log.error("设置属性失败, Exception:{}", e);
        }
    }
​
    /**
     * 单个图片处理
     *
     * @param imageValue
     */
    private String processImageSingle(byte[] imageValue) {
        // 上传图片到服务器,返回图片的URL
​
        try (InputStream inputStream = new ByteArrayInputStream(imageValue)) {
            
            return "";
        } catch (Exception e) {
            log.error("上传失败", e);
            return "error";
        }
    }
​
    /**
     * 根据rowNum colNum处理图片
     *
     * @param entity
     * @param imageIndex
     * @param imageValue
     */
    private void processImageAnnotation(T entity, int imageIndex, byte[] imageValue) {
        // 上传图片到服务器,返回图片的URL ... ...
        
        try (InputStream inputStream = new ByteArrayInputStream(imageValue)) {
            
        } catch (Exception e) {
            log.error("上传失败", e);
        }
    }
}
 
自定义注解

主要 indextype 其他可有可无

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ExcelProperty {
    String[] value() default {""};
​
    int index() default -1;
​
    int order() default Integer.MAX_VALUE;
​
    Class<? extends Converter<?>> converter() default AutoConverter.class;
​
    /** @deprecated */
    @Deprecated
    String format() default "";
​
    /**
     * 1-文本、2-图片
     */
    int type() default 1;
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值