IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 【Apache poi】读取【Excel】内图片及所在位置 -> 正文阅读

[Java知识库]【Apache poi】读取【Excel】内图片及所在位置

需求是这样的,给你固定一个excel,里面有id和插入的图片,大概200M-1G左右。

读取后将图片写入文件存储服务器内,获取静态地址,再将静态地址更新到对应id上。

难点:这个你很难定位到图片的横纵坐标,因为图片并不是真的在单元格内(业务那边给定的模板就是如此)。

excel结构大概为:

?找了网上的代码,简单修修改改。

package com.main.util;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFPicture;
import org.apache.poi.xssf.usermodel.XSSFShape;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * created by rock-ayl on 2022-2-23
 * 解析excel内的图片所在单元格
 */
public class ExcelImageUtils {

    private final static Logger LOG = LoggerFactory.getLogger(ExcelImageUtils.class);

    /**
     * 根据文件解析excel内图片
     *
     * @param file       文件对象
     * @param sheetIndex 第几个sheet
     * @return
     */
    public static Map<String, Map<Integer, PictureData>> parseSheetPic(File file, int sheetIndex) {
        try {
            //文件流
            InputStream input = new FileInputStream(file);
            //文件后缀
            String fileExt = FilenameUtils.getExtension(file.getName());
            //实现并返回
            return parseSheetPic(input, fileExt, sheetIndex);
        } catch (Exception e) {
            LOG.error("parseSheetPic fail , file error={}", e);
        }
        //默认
        return new HashMap<>();
    }

    /**
     * 根据文件流及文件类型解析excel内图片
     *
     * @param inputStream 文件流
     * @param fileExt     文件后缀 xls,xlsx
     * @param sheetIndex  第几个sheet
     * @return
     */
    public static Map<String, Map<Integer, PictureData>> parseSheetPic(InputStream inputStream, String fileExt, int sheetIndex) {
        try {
            //初始化
            Workbook workbook = WorkbookFactory.create(inputStream);
            //获取sheet
            Sheet sheet = workbook.getSheetAt(sheetIndex);
            //第一行作为key
            Map<Integer, String> keyMap = new HashMap<>();
            //第一行的迭代器
            Iterator<Cell> iterator = sheet.getRow(0).cellIterator();
            //指针
            int p = 0;
            //如果存在
            while (iterator.hasNext()) {
                //获取值
                String value = iterator.next().getStringCellValue();
                //如果存在
                if (StringUtils.isNotBlank(value)) {
                    //记录该key
                    keyMap.put(p, value);
                }
                //无论如何+1o
                p++;
            }
            //根据类型解析
            switch (fileExt) {
                case "xls":
                    return parseSheetPicForXLS((HSSFWorkbook) workbook, sheetIndex, keyMap);
                case "xlsx":
                    return parseSheetPicForXLSX((XSSFWorkbook) workbook, sheetIndex, keyMap);
            }
        } catch (Exception e) {
            LOG.error("parseSheetPic fail , inputStream error={}", e);
        }
        //默认
        return new HashMap<>();
    }

    /**
     * 解析XLS的图片
     *
     * @param workbook   workbook
     * @param sheetIndex 第几页sheet的图片
     * @return
     */
    private static Map<String, Map<Integer, PictureData>> parseSheetPicForXLS(HSSFWorkbook workbook, int sheetIndex, Map<Integer, String> keyMap) {
        //初始化结果
        Map<String, Map<Integer, PictureData>> result = new HashMap<>();
        //获取workbook所有图片列表
        List<HSSFPictureData> pictures = workbook.getAllPictures();
        //获取对应sheet
        HSSFSheet sheet = workbook.getSheetAt(sheetIndex);
        //如果存在图片
        if (pictures.size() > 0) {
            //获取列表
            List<HSSFShape> children = sheet.getDrawingPatriarch().getChildren();
            //循环
            for (HSSFShape shape : children) {
                //获取并强转
                HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor();
                //如果是
                if (shape instanceof HSSFPicture) {
                    //强转
                    HSSFPicture pic = (HSSFPicture) shape;
                    //从workbook所有图片中找到该图片
                    HSSFPictureData picData = pictures.get(pic.getPictureIndex() - 1);
                    //如果存在改key
                    if (keyMap.containsKey(anchor.getCol1())) {
                        //获取key
                        String key = keyMap.get(anchor.getCol1());
                        //尝试获取mep
                        Map<Integer, PictureData> map = result.getOrDefault(key, new HashMap<>());
                        //组装
                        map.put(anchor.getRow1() - 1, picData);
                        result.put(key, map);
                    }
                }
            }

        }
        //返回
        return result;
    }

    /**
     * 解析XLSX图片
     *
     * @return
     */
    private static Map<String, Map<Integer, PictureData>> parseSheetPicForXLSX(XSSFWorkbook workbook, int sheetIndex, Map<Integer, String> keyMap) {
        //初始化结果
        Map<String, Map<Integer, PictureData>> result = new HashMap<>();
        //获取列表
        List<POIXMLDocumentPart> relationList = workbook.getSheetAt(sheetIndex).getRelations();
        //循环1
        for (POIXMLDocumentPart dr : relationList) {
            //如果是类型
            if (dr instanceof XSSFDrawing) {
                //强转
                XSSFDrawing drawing = (XSSFDrawing) dr;
                //获取列表
                List<XSSFShape> shapeList = drawing.getShapes();
                //循环2
                for (XSSFShape shape : shapeList) {
                    //强转
                    XSSFPicture pic = (XSSFPicture) shape;
                    //获取其可能的表格
                    CTMarker ctMarker = pic.getPreferredSize().getFrom();
                    //如果存在改key
                    if (keyMap.containsKey(ctMarker.getCol())) {
                        //获取key
                        String key = keyMap.get(ctMarker.getCol());
                        //尝试获取结果map
                        Map<Integer, PictureData> map = result.getOrDefault(key, new HashMap<>());
                        //组装
                        map.put(ctMarker.getRow() - 1, pic.getPictureData());
                        result.put(key, map);
                    }
                }
            }
        }
        //返回
        return result;
    }

}

代码测试结果:

准确定位的概率大概是90%左右,小部分会定位到其他key上,精度不高,无法采用。

至此,该需求经过讨论,废弃。

由于需求废弃并改为了其他方式,未提交这部分代码,简单记录下,防止以后用到。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-02-24 15:08:35  更:2022-02-24 15:11:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:29:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码