poi导出Excel多张图片导出到一个单元格实现

今天做导出Excel的时候遇到了一个单元格中需要导出多张图片的需求。之前也做过很多的导出Excel,在网上研究了很久,总算导出成功了,但是还是有一点点的小瑕疵,就是根据图片的缩略图计算出单元格的宽高。希望有做过的能告知。需求大概是下面这样的。一个单元格最多能放三张图片。在项目得后期过程中也遇到了很多得问题,比如随着项目中数据得增多,因为每一条都会有截图,所以导致Excel非常得缓慢,以及数据量比较得大对POI小朋友进行了升级使用了SxxfWorkbook,还有就是ImageIo.read()会出现异常。

1.解决思路。目前数据量非常得大然后因为每个里面都会又对应得FileMd5加密得图片,这个目前还没有比较好得解决办法。

(控制用户那边得导出得数量)

对于数据量大,截图多得时候,采用得异步得形式去生成Excel。生成成功会往数据库里写入一条数据,或者发送一个邮件,或发送一条消息,或短信等。通过WebSocket实现服务端生成成功给前端发送一条消息,前端接收到数据调用下载Excel得形式。

最开始也是使用得Aajx  定时器得形式去轮询,但是这种形式每次轮询得时间不太好把握,其次就是占用得资源比较得大。

第一步 导入poi相应的jar

         1.导入相应的poi 对应的jar 你们自行去找相关文档,这里不做重点。

第二步 编写测试类,关键代码如下

// 起始行, 终止行, 起始列, 终止列

CellRangeAddress cra =new CellRangeAddress(i+2, i+2, 2, 4);

//设置列宽

sheet.setColumnWidth((short) i, (short) (24 * 256));

//跨行跨列边框线
CellRangeAddress cra =new CellRangeAddress(i+2, i+2, 2, 4); sheet.addMergedRegion(cra); RegionUtil.setBorderBottom(1,cra,sheet,wb); // 下边框 RegionUtil.setBorderLeft(1, cra, sheet,wb); // 左边框 RegionUtil.setBorderRight(1, cra, sheet,wb); // 有边框 RegionUtil.setBorderTop(1, cra, sheet,wb); // 上边框 fillRowValues(i,row, dataMap, columns,sheet, csData,wb);

//设置标题头部字体区域的大小 HSSFRichTextString textString = new HSSFRichTextString(headName);
//设置标题头部字体区域的大小 HSSFRichTextString textString = new HSSFRichTextString(headName); Font font = wb.createFont(); font.setFontName("微软雅黑"); font.setFontHeightInPoints((short) 14); Font font1 = wb.createFont(); font1.setFontName("微软雅黑"); font1.setFontHeightInPoints((short) 12); textString.applyFont(0,7,font); textString.applyFont(7,headName.length(),font1);

// 创建两种单元格格式
CellStyle csTitle = wb.createCellStyle();
csTitle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
csTitle.setVerticalAlignment(HSSFCellStyle.ALIGN_CENTER);
csTitle.setWrapText(true);
说明:在项目得最初得时候数据没有那么大所以还是使用得03版本得HssfWorkbook,并且ImageIo.read()读取截图得时候有时候图片转入PNG得时候会
出现异常,并且会导致整个Excel异常,所以为了防止读取异常,以及异常能进行继续执行处理。
public static void createPictureImage
(int j, String filePathList, SXSSFSheet sheet, SXSSFWorkbook wb) {
    if (StringUtils.isEmpty(filePathList)) {
        return;
    }
    Drawing drawing = sheet.createDrawingPatriarch();
    File file = new File(filePathList);
    if (file.exists()) {
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
             FileInputStream inputStream = new FileInputStream(file)) {
            IOUtils.copy(inputStream, outputStream);
            XSSFClientAnchor anchor = new XSSFClientAnchor(30, 15, 0, 0, (short) (2), j, (short) (3), j + 1);
            drawing.createPicture(anchor, wb.addPicture(outputStream.toByteArray(), SXSSFWorkbook.PICTURE_TYPE_PNG));
            outputStream.flush();
        } catch (IOException e) {
            logger.error("截图写入失败;截图地址:filePath;",filePathList);
        }
    }
}
public static boolean createPictureImage(int j,List<String> filePathList,Sheet sheet,Workbook wb){
   try {
       ByteArrayOutputStream byteArrayOut;
       HSSFPatriarch patriarch = (HSSFPatriarch) sheet.createDrawingPatriarch();
       for (int i = 0; i < filePathList.size(); i++) {
           byteArrayOut  = new ByteArrayOutputStream();
           //BufferedImage bufferImg = ImageIO.read(new File(filePathList.get(i)));
           //int height=bufferImg.getHeight();
           //int width=bufferImg.getWidth();
           ImageIO.write(bufferImg, "png", byteArrayOut);
           //30 15 0 0 代表上边距和左边距 j代表行  第一行有个标题  第二行是标题头   所以j+2开始  第一列是序号,第二列是位置,所以i+2开始  (i+2), j+2 这代表单元格的起始坐标   (short) (i+3), j+3 代表单元格终点坐标
           HSSFClientAnchor anchor = new HSSFClientAnchor(30, 15, 0, 0,   (short) (i+2), j+2, (short) (i+3), j+3);
           patriarch.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG));
           byteArrayOut.flush();
       }
   }catch (IOException e){
        return  false;
   }
    return  true;
}

主要理解

HSSFClientAnchor anchor = new HSSFClientAnchor(30, 15, 0, 0, (short) (i+2), j+2, (short) (i+3), j+3);

就是一个单元格的起始位置和终止位置  来确定你图片绘制的位置,i+2,j+2 就是你的单元格左边上部的位置   i+3,j+3 就是单元格右边下部的位置,从而两坐标确定你图片的一个区域大小,我这里是一个单元格就放一张图片,这个参数依据你的需求调整,  30 15 0 0 就是这个区域位置的一个偏移 

 

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值