自学内容网 自学内容网

Springboot——使用poi实现excel动态图片导入解析

前言

最近要实现一个导入导出的功能点,需要能将带图片的列表数据导出到excel中,且可以导入带图片的excel列表数据。

考虑到低代码平台的表头与数据的不确定性,技术框架上暂定使用Apache-POI。

依赖引入

由于POI的包很多种,为了避免引入不全导致的运行报错问题,这里使用Springboot技术,引入主要依赖如下:

<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-spring-boot-starter</artifactId>
    <version>4.1.3</version>
</dependency>

导入实现

经过查阅相关的资料、案例等,目前导入解析有两种方式。

本次自测使用的excel模板如下样式
在这里插入图片描述

方式一

该方式可以解析所有的数据,多张图片仅能解析出一张,但不能定位出图片的下标位置信息。仅用于参考。

import org.apache.commons.compress.utils.Lists;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFPictureData;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Iterator;
import java.util.List;

@RestController
@RequestMapping("/poi")
public class TestController {

    /**
     * excel上传解析,能获取数据和图片
     * 但图片多张只能拿到一张,且无法获取位置点
     * @param file
     * @return
     * @throws IOException
     */
    @PostMapping("/upload")
    public String upload(MultipartFile file) throws IOException {
        List<List<String>> data = Lists.newArrayList();
        Workbook workbook = new XSSFWorkbook(file.getInputStream());
        Sheet sheet = workbook.getSheetAt(0);
        Iterator<Row> rowIterator = sheet.iterator();
        while (rowIterator.hasNext()) {
            Row row = rowIterator.next();
            List<String> rowData = new ArrayList<>();
            Iterator<Cell> cellIterator = row.iterator();
            while (cellIterator.hasNext()) {
                Cell cell = cellIterator.next();
                rowData.add(getCellValueAsString(cell));
            }
            data.add(rowData);
        }

        // 处理图片
        List<String> imageList = new ArrayList<>();
        List<XSSFPictureData> allPictures = (List<XSSFPictureData>) workbook.getAllPictures();
        for (XSSFPictureData pictureData : allPictures) {
            byte[] bytes = pictureData.getData();
            String mimeType = pictureData.getMimeType();
            imageList.add(new String(bytes,"UTF-8"));
        }
        workbook.close();
        return "";
    }

    private String getCellValueAsString(Cell cell) {
        CellType cellType = cell.getCellType();
        switch (cellType) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                return String.valueOf(cell.getNumericCellValue());
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            default:
                return "";
        }
    }
}

断点查看导入解析的信息结果,如下所示:
在这里插入图片描述

方式二

相比方式一的逻辑,采取一种新的解析方式,迭代 sheet.getDrawingPatriarch()的结果集进行判断。

但这样只能拿到图片,数据部分可以参考方式一去取。

/**
 * excel 上传解析图片
 * 多张都能获取,且能获取位置点
 * 行 row 与 列 col 从下标 0 开始计算
 * @param file
 * @return
 * @throws IOException
 */
@PostMapping("/upload2")
public String upload2(MultipartFile file) throws IOException {
    // 多张图片,以一样的时间戳开头,行与列组成名称
    long timeMillis = System.currentTimeMillis();
    XSSFWorkbook tempWorkBook = new XSSFWorkbook(file.getInputStream());
    // 获取模板sheet页
    Sheet sheet = tempWorkBook.getSheetAt(0);
    Drawing<?> drawing = sheet.getDrawingPatriarch();
    for (Shape shape : drawing) {
        if (shape instanceof Picture) {
            System.out.println("  ");
            Picture picture = (Picture) shape;
            ClientAnchor anchor = picture.getClientAnchor();

            int row1 = anchor.getRow1();
            short col1 = anchor.getCol1();
            System.out.println("row:"+row1+" col:"+col1);

            PictureData pictureData = picture.getPictureData();
            byte[] data = pictureData.getData();
            System.out.println(Base64.getEncoder().encodeToString(data));
            String imgType = pictureData.suggestFileExtension();
            // 将图片保存到项目路径下
            OutputStream outputStream = new FileOutputStream(timeMillis+"__"+row1+"_"+col1+"_img."+imgType);
            outputStream.write(data);
            outputStream.close();
        }
    }
    tempWorkBook.close();
    return "";
}

运行后的效果如下所示:
在这里插入图片描述
通过控制台中的打印位置信息,对比excel文件,能够定位图片所在单元格。
在这里插入图片描述


原文地址:https://blog.csdn.net/qq_38322527/article/details/142774927

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!