excel poi 实现图片导出

引入excel   poi的依赖

<dependency>
   <groupId>org.apache.poi</groupId>
   <artifactId>poi</artifactId>
   <version>3.14</version>
</dependency>

/**
     * int MOVE_AND_RESIZE = 0;//跟随单元格扩大或者缩小,就是你拖动单元格的时候,图片大小也在变
     *     int MOVE_DONT_RESIZE = 2;//图片固定在该单元格在左上角,并且随着单元格移动
     *     int DONT_MOVE_AND_RESIZE = 3;//固定在Excel某个位置,像牛皮广告一样不会动
     * @param pumpName
     * @param year
     * @param response
     */
public void exportPumpWaterTankCleaningReport(String pumpName, String year, HttpServletResponse response){
        OutputStream ouputStream = null;
        HSSFWorkbook sheets = new HSSFWorkbook();
        String fileName = DateUtils.getDate()+"水箱清洗记录报表数据.xlsx";
        ByteArrayOutputStream byteArrayOut =null;
        try{
            response.setHeader("Content-Disposition", "attachment; filename=".concat(new String(fileName.getBytes("GB2312"), "ISO8859-1")));
            response.setHeader("Connection", "close");
            response.setHeader("Content-Type", "application/vnd.ms-excel");
            ouputStream = response.getOutputStream();

            //创建sheet页名称
            HSSFSheet hssfSheet = sheets.createSheet("水箱清洗记录报表数据");

            HSSFPatriarch patriarch = hssfSheet.createDrawingPatriarch();//导出图片使用

            //单元格合并
            hssfSheet.addMergedRegion(new CellRangeAddress(0, 1, 0, 0));//序号
            hssfSheet.addMergedRegion(new CellRangeAddress(0, 1, 1, 1));//泵房名称
            hssfSheet.addMergedRegion(new CellRangeAddress(0, 0, 2, 6));//上半年清洗
            hssfSheet.addMergedRegion(new CellRangeAddress(0, 0, 7, 11));//下半年清洗

            // Sheet样式
            HSSFCellStyle titleStyle =sheets.createCellStyle();
            // 背景色的设定
            titleStyle.setFillBackgroundColor(HSSFColor.GREY_50_PERCENT.index);
            // 前景色的设定
            titleStyle.setFillForegroundColor(HSSFColor.GREY_50_PERCENT.index);
            // 填充模式
            titleStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);

            titleStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
            titleStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);

            //创建标题行
            HSSFRow titleRow = hssfSheet.createRow(0);
            titleRow.setHeight((short) (25 * 20));
            HSSFCell oneCell = titleRow.createCell(0);
            oneCell.setCellValue("序号");
            oneCell.setCellStyle(titleStyle);
            HSSFCell twoCell = titleRow.createCell(1);
            twoCell.setCellValue("泵房名称");
            twoCell.setCellStyle(titleStyle);
            HSSFCell threeCell = titleRow.createCell(2);
            threeCell.setCellValue("上半年清洗");
            threeCell.setCellStyle(titleStyle);
            HSSFCell fourCell = titleRow.createCell(7);
            fourCell.setCellValue("下半年清洗");
            fourCell.setCellStyle(titleStyle);

            titleRow = hssfSheet.createRow(1);
            titleRow.setHeight((short) (25 * 20));
            HSSFCell titleCell = titleRow.createCell(2);
            hssfSheet.setColumnWidth(2,10*300);
            titleCell.setCellValue("清洗日期");
            titleCell = titleRow.createCell(3);
            hssfSheet.setColumnWidth(3,10*300);
            titleCell.setCellValue("清洗时间");
            titleCell = titleRow.createCell(4);
            hssfSheet.setColumnWidth(4,10*300);
            titleCell.setCellValue("清洗人员");
            titleCell = titleRow.createCell(5);
            hssfSheet.setColumnWidth(5,10*400);
            titleCell.setCellValue("清洗前照片");
            titleCell = titleRow.createCell(6);
            hssfSheet.setColumnWidth(6,10*400);
            titleCell.setCellValue("清洗后照片");
            titleCell = titleRow.createCell(7);
            hssfSheet.setColumnWidth(7,10*300);
            titleCell.setCellValue("清洗日期");
            titleCell = titleRow.createCell(8);
            hssfSheet.setColumnWidth(8,10*300);
            titleCell.setCellValue("清洗时间");
            titleCell = titleRow.createCell(9);
            hssfSheet.setColumnWidth(9,10*300);
            titleCell.setCellValue("清洗人员");
            titleCell = titleRow.createCell(10);
            hssfSheet.setColumnWidth(10,10*400);
            titleCell.setCellValue("清洗前照片");
            titleCell = titleRow.createCell(11);
            hssfSheet.setColumnWidth(11,10*400);
            titleCell.setCellValue("清洗后照片");

            //往excel填充数据
            int serialNumber = 1;
            HSSFRow dataRow = null;
            List<BufferedImage> images = new ArrayList<>();
            List<String> pictureList = new ArrayList<>();
            List<List<TicketReport>> lists = this.queryPumpWaterTankCleaningReport(pumpName, year);
            String exportPrePictureUrl = Global.getConfig("exportPrePictureUrl");
            String exportSuPictureUrl = Global.getConfig("exportSuPictureUrl");
            String filePath = null;
            if(lists.size() >0){
                for(List<TicketReport> list:lists){
                    int num=2;
                    dataRow = hssfSheet.createRow(hssfSheet.getLastRowNum() + 1);
                    for(int i = 1; i <= list.size(); i++){
                        TicketReport ticketReport = list.get(i-1);
                        if(null == ticketReport.getPumpName()) {
                            continue;
                        }
                        if(ticketReport.getPeriod() == 2 && num==2){//表示该泵房还未填充数据,只有下半年的数据
                            num = num+5;//上半年和下半年之间相差5列
                            dataRow.createCell(0).setCellValue(serialNumber);//序号
                            dataRow.createCell(1).setCellValue(ticketReport.getPumpName());//泵房名称
                        }else if(ticketReport.getPeriod() == 1){//表示上半年数据填充,单元格向前移动
                            num=2;
                            dataRow.createCell(0).setCellValue(serialNumber);//序号
                            dataRow.createCell(1).setCellValue(ticketReport.getPumpName());//泵房名称
                        }
                        dataRow.setHeight((short)1600);
                        dataRow.createCell(num).setCellValue(ticketReport.getCompleteDate());//清洗日期
                        dataRow.createCell(num+1).setCellValue(null == ticketReport.getProjectOperationTime()?"":ticketReport.getProjectOperationTime());//清洗时间
                        dataRow.createCell(num+2).setCellValue(null == ticketReport.getOperationUserName()?"":ticketReport.getOperationUserName());//清洗人员
                        String beforePicture = ticketReport.getBeforePicture();
                        images = new ArrayList<>();
                        if(null != beforePicture && !"".equals(beforePicture)){
                            pictureList = Arrays.asList(beforePicture.split(","));
                            for(String picture:pictureList){
                                filePath = exportPrePictureUrl+ticketReport.getTicketId()+exportSuPictureUrl+ticketReport.getId()+"/"+picture;
//                                images.add(ImageIO.read(new File(filePath)));
                                images.add(toBufferedImage(Toolkit.getDefaultToolkit().getImage(filePath)));//解决ImageIO.read方法造成图片失真问题
                            }
                        }else{
                            dataRow.createCell(num+3).setCellValue("");//清洗前照片
                        }

                        int rowNum = hssfSheet.getLastRowNum();
                        int cellNum1 = num+3;
                        int cellNum2 = num+4;
                        for (BufferedImage image : images) {
                            byteArrayOut = new ByteArrayOutputStream();
                            ImageIO.write(image, "jpg", byteArrayOut);
                            HSSFClientAnchor anchor = new HSSFClientAnchor(10, 10, 0, 0, (short) cellNum1, rowNum, (short) cellNum2, rowNum+1);
                            anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
                            // 插入图片
                            patriarch.createPicture(anchor, sheets.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG));
                        }

                        String afterPicture = ticketReport.getAfterPicture();
                        images = new ArrayList<>();
                        if(null != afterPicture && !"".equals(afterPicture)){
                            pictureList = Arrays.asList(afterPicture.split(","));
                            for(String picture:pictureList){
                                filePath = exportPrePictureUrl+ticketReport.getTicketId()+exportSuPictureUrl+ticketReport.getId()+"/"+picture;
//                                images.add(ImageIO.read(new File(filePath)));
                                images.add(toBufferedImage(Toolkit.getDefaultToolkit().getImage(filePath)));
                            }
                        }else{
                            dataRow.createCell(num+4).setCellValue("");//清洗后照片
                        }

                        cellNum1 = num+4;
                        cellNum2 = num+5;
                        for (BufferedImage image : images) {
                            byteArrayOut = new ByteArrayOutputStream();
                            ImageIO.write(image, "jpg", byteArrayOut);
                            HSSFClientAnchor anchor = new HSSFClientAnchor(10, 10, 0, 0, (short) cellNum1, rowNum, (short) cellNum2, rowNum+1);
                            anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
                            // 插入图片
                            patriarch.createPicture(anchor, sheets.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG));
                        }


//                        dataRow.createCell(num+4).setCellValue(serialNumber);//清洗后照片
                        num = num+5;//上半年和下半年之间相差5列
                    }
                    serialNumber = serialNumber+1;
                }
            }

            sheets.write(ouputStream);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                if(null != ouputStream){
                    ouputStream.close();
                    sheets.close();
                }
                if(byteArrayOut != null){
                    try {
                        byteArrayOut.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

上面代码中和图片相关的代码如下:

hssfSheet.setColumnWidth(6,10*400);
hssfSheet.setColumnWidth(7,10*300);
hssfSheet.setColumnWidth(10,10*400);
hssfSheet.setColumnWidth(11,10*400);
dataRow.setHeight((short)1600);
String beforePicture = ticketReport.getBeforePicture();
                        images = new ArrayList<>();
                        if(null != beforePicture && !"".equals(beforePicture)){
                            pictureList = Arrays.asList(beforePicture.split(","));
                            for(String picture:pictureList){
                                filePath = exportPrePictureUrl+ticketReport.getTicketId()+exportSuPictureUrl+ticketReport.getId()+"/"+picture;
//                                images.add(ImageIO.read(new File(filePath)));
                                images.add(toBufferedImage(Toolkit.getDefaultToolkit().getImage(filePath)));//解决ImageIO.read方法造成图片失真问题
                            }
                        }else{
                            dataRow.createCell(num+3).setCellValue("");//清洗前照片
                        }

                        int rowNum = hssfSheet.getLastRowNum();
                        int cellNum1 = num+3;
                        int cellNum2 = num+4;
                        for (BufferedImage image : images) {
                            byteArrayOut = new ByteArrayOutputStream();
                            ImageIO.write(image, "jpg", byteArrayOut);
                            HSSFClientAnchor anchor = new HSSFClientAnchor(10, 10, 0, 0, (short) cellNum1, rowNum, (short) cellNum2, rowNum+1);
                            anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
                            // 插入图片
                            patriarch.createPicture(anchor, sheets.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG));
                        }

                        String afterPicture = ticketReport.getAfterPicture();
                        images = new ArrayList<>();
                        if(null != afterPicture && !"".equals(afterPicture)){
                            pictureList = Arrays.asList(afterPicture.split(","));
                            for(String picture:pictureList){
                                filePath = exportPrePictureUrl+ticketReport.getTicketId()+exportSuPictureUrl+ticketReport.getId()+"/"+picture;
//                                images.add(ImageIO.read(new File(filePath)));
                                images.add(toBufferedImage(Toolkit.getDefaultToolkit().getImage(filePath)));
                            }
                        }else{
                            dataRow.createCell(num+4).setCellValue("");//清洗后照片
                        }

                        cellNum1 = num+4;
                        cellNum2 = num+5;
                        for (BufferedImage image : images) {
                            byteArrayOut = new ByteArrayOutputStream();
                            ImageIO.write(image, "jpg", byteArrayOut);
                            HSSFClientAnchor anchor = new HSSFClientAnchor(10, 10, 0, 0, (short) cellNum1, rowNum, (short) cellNum2, rowNum+1);
                            anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
                            // 插入图片
                            patriarch.createPicture(anchor, sheets.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG));
                        }

以上需要注意的是:

1:setColumnWidth方法和setHeight方法可以将导出的图片放大到需要的大小

2:HSSFClientAnchor anchor = new HSSFClientAnchor(10, 10, 0, 0, (short) cellNum1, rowNum, (short) cellNum2, rowNum+1);这段代码,这将会决定你的图片生成到excel单元格的位置,该方法在源码中的接口如下:
public HSSFClientAnchor(int dx1,int dy1,int dx2,int dy2,short col1,int row1,short col2,int row2)

dx1:第一个单元格的开始X坐标
dy1:第一个单元格的开始y坐标
dx2:第二个单元格的开始X坐标
dy2:第二个单元格的开始y坐标

col1 图片的左上角放在第几个列cell,决定图片在哪一列 
row1 图片的左上角放在第几个行cell,决定图片在哪一行
col2 图片的右下角放在第几个列cell, 
row2 图片的右下角放在第几个行cell

下面放一张导出的效果:

上面代码涉及到的方法:

public static BufferedImage toBufferedImage(Image image) {
        if (image instanceof BufferedImage) {
            return (BufferedImage)image;
        }

        // This code ensures that all the pixels in the image are loaded
        image = new ImageIcon(image).getImage();

        // Determine if the image has transparent pixels; for this method's
        // implementation, see e661 Determining If an Image Has Transparent Pixels
        //boolean hasAlpha = hasAlpha(image);

        // Create a buffered image with a format that's compatible with the screen
        BufferedImage bimage = null;
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        try {
            // Determine the type of transparency of the new buffered image
            int transparency = Transparency.OPAQUE;
           /* if (hasAlpha) {
                 transparency = Transparency.BITMASK;
             }*/

            // Create the buffered image
            GraphicsDevice gs = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gs.getDefaultConfiguration();
            bimage = gc.createCompatibleImage(
                    image.getWidth(null), image.getHeight(null), transparency);
        } catch (HeadlessException e) {
            // The system does not have a screen
        }

        if (bimage == null) {
            // Create a buffered image using the default color model
            int type = BufferedImage.TYPE_INT_RGB;
            //int type = BufferedImage.TYPE_3BYTE_BGR;//by wang
            /*if (hasAlpha) {
                 type = BufferedImage.TYPE_INT_ARGB;
             }*/
            bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
        }

        // Copy image to buffered image
        Graphics g = bimage.createGraphics();

        // Paint the image onto the buffered image
        g.drawImage(image, 0, 0, null);
        g.dispose();

        return bimage;
    }

参考博文:https://blog.csdn.net/qq_40524941/article/details/96155733

https://www.oschina.net/question/1092_23668

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值