java poi方式读取Excel的图片

POM
​​​​

<!-- poi -->
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-spring-boot-starter</artifactId>
    <version>4.1.2</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>4.1.0</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.1.0</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml-schemas</artifactId>
    <version>4.1.0</version>
</dependency>
<dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>javax.servlet.jsp-api</artifactId>
    <version>2.3.3</version>
    <scope>provided</scope>
</dependency>


读取每一行每一列的信息
 

Map<String, Map<Integer, Map<Integer, String>>> sheetsMap = this.readExcelImageToMap(file);
Set<String> keys = sheetsMap.keySet();
List<String> sheetsNames = new ArrayList<>();
// 获取所有的key == 页名称
for (String sheetsName : keys) {
    sheetsNames.add(sheetsName);
}
// 遍历所有的列
for (int i = 0; i < sheetsMap.size(); i++) {
    // 根据页名称获取页
    String sheetsName = sheetsNames.get(i);
    Map<Integer, Map<Integer, String>> rows = sheetsMap.get(sheetsName);
    if (rows.size() > 0) {
        // 根据所有的行遍历
        for (int rowIdx = 1; rowIdx < rows.size(); rowIdx++) {
            // 遍历当前行的所有列
            Map<Integer, String> columnsTitel = rows.get(0); // 第一行的标题
            Map<Integer, String> columns = rows.get(rowIdx);
            OrderImportVO orderImportVO = new OrderImportVO();
            String offProperty = "";
            String offProductId = "";
            for (int colIdx = 0; colIdx < columnsTitel.size(); colIdx++) {
                System.out.println(columns.get(colIdx));
                String colValue = columns.get(colIdx);
                if ("图片".equals(columnsTitel.get(colIdx))) {
                    String imageUrl = StringUtils.isEmpty(columns.get(colIdx)) ? "" : colValue;
                    orderImportVO.setImage(imageUrl);
                    if (StringUtils.isEmpty(imageUrl)) {
                        throw new ServiceException("图片不能为空!");
                    }
                }
            }
        }
    }
}

    /**
     * 读取上传带图片文件转成Map
     *
     * @param file
     * @return
     * @throws IOException
     */
    private Map<String, Map<Integer, Map<Integer, String>>> readExcelImageToMap(MultipartFile file) {
        // 声明所有页的集合
        Workbook wb = readExcel(file); // 读取上传excel
        if (wb == null) {
            return Collections.emptyMap();
        }
        // 获取总页数
        int pageSize = wb.getNumberOfSheets();

        // excel 里边的sheet 有多个时 限制只取第一个。
        if (pageSize > 1) {
            pageSize = 1;
        }
        Map<String, Map<Integer, Map<Integer, String>>> mapSheet = new HashMap<>();

        for (int i = 0; i < pageSize; i++) {
            // 声明当前页的行和列
            Map<Integer, Map<Integer, String>> map = new HashMap<>();
            // 获取当前页
            Sheet sheet = wb.getSheetAt(i);

            String sheetName = sheet.getSheetName();
            // log.info("当前sheet名称:" + sheetName);
            int rowSize = sheet.getPhysicalNumberOfRows(); // 获取不为空的总行数
            // 遍历每一行
            for (int rowNum = 0; rowNum < rowSize; rowNum++) {
                Row row = sheet.getRow(rowNum);
                //int columnSize = row.getPhysicalNumberOfCells(); // 获取不为空的列个数
                int columnSize = row.getLastCellNum(); // 获取最后一个不为空的列是第几个
                // 声明当前列
                Map<Integer, String> columnMap = new HashMap<>();
                // 遍历一行中每列值
                for (int cellNum = 0; cellNum < columnSize; cellNum++) {
                    System.out.println(row.getCell(cellNum));
                    Cell cell=row.getCell(cellNum);
                    if(cell!=null){
                        cell.setCellType(CellType.STRING);
                        String value=cell.toString();
                        columnMap.put(cellNum, value);
                    }
//                    String value = (String) getCellValue(row.getCell(cellNum));
                    // 添加当前列的内容 cellNum代表第几列 value是内容

                }
                // 添加当前行的内容 rowNum 代表第几行 value是列的内容 意思是第几行第几列的内容
                map.put(rowNum, columnMap);
            }

            // 声明当前页图片的集合
            Map<String, PictureData> sheetImageMap = null;
            // 获取图片
            try {
                //2003版本的excel,用.xls结尾
                sheetImageMap = getPicturesHSS((HSSFSheet) sheet);
            } catch (Exception ex) {
                log.error(ex.getMessage());
                try {
                    //2007版本的excel,用.xlsx结尾
                    sheetImageMap = getPicturesXSS((XSSFSheet) sheet);
                } catch (Exception e) {
                    log.error(ex.getMessage());
                }
            }
            //解析图片并上传到服务器 并设置该字段的值为字符串类型添加到map中 进行数据库上传
            Object key[] = sheetImageMap.keySet().toArray();
            for (int p = 0; p < sheetImageMap.size(); p++) {
                PictureData pic = sheetImageMap.get(key[p]);
                String picName = key[p].toString();
                String ext = pic.suggestFileExtension();
                byte[] picData = pic.getData();
                try {
                    // 上传图片到服务器并返回访问路径
                    String imageUrl = uploadPicture(picData, ext);
                    if (org.apache.commons.lang3.StringUtils.isNotEmpty(imageUrl)) {
                        //按(行-列)规则解析key 并根据key 设置 某一行的某一列的 图片链接
                        String[] split = picName.split("-");
                        Integer rowIndex = Integer.parseInt(split[0].toString()), columnIndex = Integer.parseInt(split[1].toString());
                        //根据行下标 获取所有的列
                        Map<Integer, String> columns = map.get(rowIndex);
                        //根据列下标 设置图片链接值
                        columns.put(columnIndex, imageUrl);
                    }
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
            }
            // 添加当前页的所有内容
            mapSheet.put(sheetName, map);
        }
        return mapSheet;
    }
/**
 * 获取图片和位置 (xls)
 *
 * @param sheet
 * @return
 * @throws IOException
 */
public static Map<String, PictureData> getPicturesHSS(HSSFSheet sheet) {
    Map<String, PictureData> map = new HashMap<String, PictureData>();
    List<HSSFShape> list = sheet.getDrawingPatriarch().getChildren();
    for (HSSFShape shape : list) {
        if (shape instanceof HSSFPicture) {
            HSSFPicture picture = (HSSFPicture) shape;
            HSSFClientAnchor cAnchor = (HSSFClientAnchor) picture.getAnchor();
            PictureData pdata = picture.getPictureData();
            String key = cAnchor.getRow1() + "-" + cAnchor.getCol1(); // 行号-列号
            map.put(key, pdata);
        }
    }
    return map;
}
/**
 * 获取图片和位置 (xlsx)
 *
 * @param sheet
 * @return
 * @throws IOException
 */
private static Map<String, PictureData> getPicturesXSS(XSSFSheet sheet) {
    Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();
    for (POIXMLDocumentPart dr : sheet.getRelations()) {
        if (dr instanceof XSSFDrawing) {
            XSSFDrawing drawing = (XSSFDrawing) dr;
            List<XSSFShape> shapes = drawing.getShapes();
            for (XSSFShape shape : shapes) {
                XSSFPicture pic = (XSSFPicture) shape;
                //解决图片空指针报错问题   2021-12-27
                XSSFClientAnchor anchor = (XSSFClientAnchor) shape.getAnchor();
                //XSSFClientAnchor anchor = pic.getPreferredSize();
                CTMarker marker = anchor.getFrom();
                String key = marker.getRow() + "-" + marker.getCol(); // 行号-列号
                sheetIndexPicMap.put(key, pic.getPictureData());
            }
        }
    }
    return sheetIndexPicMap;
}

/**
 * 读取excel
 *
 * @param file
 * @return
 */
private static Workbook readExcel(MultipartFile file) {
    Workbook wb = null;
    ZipSecureFile.setMinInflateRatio(0);
    if (file == null) {
        return null;
    }
    String filename = file.getOriginalFilename();
    InputStream is = null;

    try {
        is = file.getInputStream();
        //2003版本的excel,用.xls结尾
        wb = new HSSFWorkbook(is);//得到工作簿
    } catch (Exception ex) {
        log.error(ex.getMessage());
        try {
            //2007版本的excel,用.xlsx结尾
            is = file.getInputStream();
            wb = new XSSFWorkbook(is);//得到工作簿
        } catch (IOException e) {
            log.error(ex.getMessage());
        }
    }

    return wb;
}
/**
 * 将图片上传,返回图片存储路径
 *
 * @param pictureData
 * @param ext
 * @return
 * @throws IOException
 */
public String uploadPicture(byte[] pictureData, String ext) throws IOException {
    //SimpleDateFormat ymd = new SimpleDateFormat("yyyyMMdd");
    //SimpleDateFormat ymdHm = new SimpleDateFormat("yyyyMMddHHmm");
    //Date nowDate = new Date();
    //String dateDir = ymd.format(nowDate);// /sysFiles/offlineOrderPicture/ 目录下的日期文件夹名称
    String fileDir = "uploadxlspic/"; // 线下图片上传所在文件夹路径
    InputStream inputStream = new ByteArrayInputStream(pictureData);
    // 获取图片哈希值
    String imageHash = null;
    try {
        imageHash = getMD5Checksum(inputStream);
    } catch (Exception e) {
        e.printStackTrace();
    }
    //String fileName = picIndexName + "_" + imageHash; // 新图片文件名是 excel图片索引+图片哈希
    String newFileName = imageHash + "." + ext; // 文件名(加后缀)
    // 将图片按路径和文件名上传到服务器
    inputStream = new ByteArrayInputStream(pictureData);
    File file = File.createTempFile(fileDir, newFileName);
    OutputStream outputStream = new FileOutputStream(file);
    IOUtils.copy(inputStream, outputStream);
    inputStream.close();
    outputStream.close();
    String savePath = upload(file, newFileName, fileDir);
    file.delete();
    return savePath;
}

public static String getMD5Checksum(InputStream is) throws NoSuchAlgorithmException, IOException {
    byte[] buffer = new byte[1024];
    MessageDigest complete = MessageDigest.getInstance("MD5");

    int numRead;
    do {
        numRead = is.read(buffer);
        if (numRead > 0) {
            complete.update(buffer, 0, numRead);
        }
    } while (numRead != -1);

    if (is != null) {
        is.close();
    }

    byte[] digest = complete.digest();
    String result = "";

    for (int i = 0; i < digest.length; ++i) {
        result = result + Integer.toString((digest[i] & 255) + 256, 16).substring(1);
    }

    return result;
}

@Value("${erp.oss.accessKeyId:}")
private String accessKeyId;
@Value("${erp.oss.accessKeySecret:}")
private String accessKeySecret;
@Value("${erp.oss.endpoint:}")
private String endpoint;
@Value("${erp.oss.bucket:}")
private String bucket;

    //OSS存储路径

public String upload(File file, String fileName, String rootPath) {
    LocalDate now = LocalDate.now();
    // 存储路径
    String path = rootPath + now.getYear() + "-" + now.getMonthValue() + "-" + now.getDayOfMonth() + "/" + fileName.replace("+", "_");
    // oss
    OSS client = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
    // 存储文件
    client.putObject(bucket, path, file);

    return "https://" + bucket + "." + endpoint + "/" + path;
}

/**
 * 利用正则表达式判断字符串是否是数字
 * @param str
 * @return
 */
public boolean isNumeric(String str){
    Pattern pattern = Pattern.compile("[0-9]*");
    Matcher isNum = pattern.matcher(str);
    if(!isNum.matches() ){
        return false;
    }
    return true;
}

//处理尺码
public String dealWithSize(String str) {
    int count = 0;
    int lCount=0;
    int sCount=0;
    //for循环遍历数组
    for (int i = 0; i < str.length(); i++) {
        //charAt方法获取数组i的值,和a比较,相等的话count+1
        if (str.charAt(i) == 'X') {
            count++;
        }
        if(count==0){
            break;
        }
        if (str.charAt(i) == 'L') {
            lCount++;
        }
        if (str.charAt(i) == 'S') {
            sCount++;
        }

    }
    String size=str;
    if(count==1&&lCount>=1){
        size="XL";
    }else if(count>1&&lCount>=1){
        size=count+"XL";
    }

    if(count==1&&sCount>=1){
        size="XS";
    }else if(count>1&&sCount>=1){
        size=count+"XS";
    }

    return size;
}
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在使用POI读取Excel时,可以通过 HSSFClientAnchor 类来获取 Excel 图片的位置和大小信息,并通过 PictureData 类来获取图片的二进制数据,然后可以将图片保存到本地或者上传到服务器。 以下是一个示例代码: ```java FileInputStream inputStream = new FileInputStream("test.xls"); Workbook workbook = new HSSFWorkbook(inputStream); Sheet sheet = workbook.getSheetAt(0); // 获取所有图片并处理 List<PictureData> pictures = new ArrayList<>(); Map<Integer, PictureData> picturesMap = new HashMap<>(); List<HSSFShape> shapes = ((HSSFSheet) sheet).getDrawingPatriarch().getChildren(); for (HSSFShape shape : shapes) { if (shape instanceof HSSFPicture) { HSSFPicture picture = (HSSFPicture) shape; PictureData pictureData = picture.getPictureData(); pictures.add(pictureData); picturesMap.put(picture.getPictureIndex(), pictureData); } } // 处理单元格图片 for (Row row : sheet) { for (Cell cell : row) { if (cell.getCellTypeEnum() == CellType.BLANK) { continue; } if (cell.getCellTypeEnum() == CellType.STRING && StringUtils.isNotBlank(cell.getStringCellValue())) { RichTextString richTextString = cell.getRichStringCellValue(); for (int i = 0; i < richTextString.numFormattingRuns(); i++) { int startIndex = richTextString.getIndexOfFormattingRun(i); int endIndex = startIndex + richTextString.getLengthOfFormattingRun(i); HSSFFont font = (HSSFFont) richTextString.getFontOfFormattingRun(i); if (font.getUnderline() == Font.U_SINGLE && font.getColor() == HSSFColor.AUTOMATIC.index) { for (int j = startIndex; j < endIndex; j++) { HSSFRichTextString hssfRichTextString = (HSSFRichTextString) richTextString; int pictureIndex = hssfRichTextString.getIndexOfFormattingRun(i) / 3; PictureData pictureData = picturesMap.get(pictureIndex); if (pictureData != null) { String fileName = UUID.randomUUID().toString() + "." + pictureData.suggestFileExtension(); byte[] data = pictureData.getData(); // 处理图片数据 } } } } } } } ``` 在上面的代码,首先获取 Excel 的所有图片,然后遍历单元格,通过 RichTextString 获取单元格的所有文本和图片,并通过 HSSFRichTextString.getIndexOfFormattingRun() 方法获取图片在文本的位置,最后可以通过 HSSFClientAnchor 类获取图片Excel 的位置和大小信息。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值