POI生成Excel设置图片的等比缩放并居中

POI提供了HSSF、XSSF以及SXSSF三种方式操作Excel。区别如下:
HSSF:操作Excel97-2003版本,文件扩展名为.xls。
XSSF:操作Excel2007版本开始,文件扩展名为.xlsx。
SXSSF:是在XSSF基础上,POI3.8版本开始提供的一种支持低内存占用的操作方式,扩展名为.xlsx。

下面代码适用于Excel 97-2003,文件后缀为.xls,使用的poi版本为5.1.0

		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>5.1.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>5.1.0</version>
		</dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>5.1.0</version>
   		</dependency>

HSSFClientAnchor构造方法参数的含义:
在这里插入图片描述

下面代码功能,将一张图片放在excel的某个单元格,等比例放置图片并居中,默认宽占满或者高占满单元格

package com.test.util;

import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.ClientAnchor;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
public class ExcelTest {
    public static void main(String[] args) {
        String outFilePath = "d:/test.xls";//生成的文件
        String templatePath = "D:\\material\\2022\\01\\05\\template.xls";//模板文件
        String imagePath = "D:\\material\\2022\\01\\05\\2333.png";//图片
        InputStream in = null;
        FileOutputStream out = null;
        try{
            in = new FileInputStream(templatePath);
            HSSFWorkbook wb = new HSSFWorkbook(in);
            HSSFSheet sheet = wb.getSheetAt(0);
            in.close();
            sheet.setForceFormulaRecalculation(true);

            HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
            // 将图片设置到A4单元格中:后面两个参数,0代表第1列,3代表第4行
            insertImageToCell(wb,patriarch,imagePath,(short) 0,(short)3);
            out = new FileOutputStream(outFilePath);
            // 将最新的 Excel 文件写入到文件输出流中,更新文件信息!
            wb.write(out);
            // 执行 flush 操作, 将缓存区内的信息更新到文件上
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    private static void insertImageToCell(HSSFWorkbook wb, HSSFPatriarch patriarch, String imageFile, short col1, short row1) {
        BufferedImage bufferImg;
        int maxWidth = 1023,maxHeight=255;
        //x1=12左侧预留12宽度,y1=15上方预留15宽度
        int x1=12,y1=15,x2=maxWidth,y2=maxHeight;
        // 先把读进来的图片放到一个ByteArrayOutputStream中,以便产生ByteArray
        try {
            ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
            File file = new File(imageFile);
            if (file.exists()) {
                long lenth=file.length();
                if (lenth>10) {
                    bufferImg = ImageIO.read(file);
                    /* 原始图像的宽度和高度 */
                    int width = bufferImg.getWidth();
                    int height = bufferImg.getHeight();
                    if (width>height) {//宽大于高
                        //假设左右各留出12宽度,图片宽设置为最大,占据约1000(=maxWidth-12*2)
                        double rate = (double)(maxWidth-x1*2)/width;//比例
                        int eHeight = (int)(height*rate);//等比例算出需要的高度
                        //如果图片高度+y1大于255,则设置图片的高度为255-y1=240,重新计算宽度
                        if(eHeight+y1>maxHeight) {
                            rate = (double) (maxHeight-y1)/height;//重新计算比例
                            int ewidth = (int)(width*rate);//等比例算出需要的宽度
                            y2 = (maxHeight-y1);//y2坐标
                            x2 = ewidth+x1;
                            if(x2<1012){//如果图片不居中,重新计算x1位置,使图片居中
                                x1 = (maxWidth-x2)/2;//图片居中
                                x2 = ewidth+x1;
                            }
                        }else {
                            y2 = y1+eHeight;//这里就不设置图片上下居中了(保留图片距离上方15)
                            x2 = (maxWidth-x1*2);
                        }
                    }else{//高大于宽
                        //假设上留出15宽度,图片高设置为最大,占据240(=255-15)
                        double rate = (double)(maxHeight-y1)/height;//比例
                        int ewidth = (int)(width*rate);//等比例算出需要的宽度
                        //如果图片高度>宽,高最大为240,宽最大为1012,所以宽不会超出
                        y2 = (maxHeight-y1);
                        x2 = ewidth+x1;
                        if(x2<1012){//如果图片不居中,重新计算x1位置,使图片居中
                            x1 = (maxWidth-x2)/2;//图片居中
                            x2 = ewidth+x1;
                        }
                    }
                    ImageIO.write(bufferImg, "jpg", byteArrayOut);
                    //x1,y1,x2,y2
                    HSSFClientAnchor anchor = new HSSFClientAnchor(x1, y1, x2, y2,
                            col1, row1, col1, row1);
                    anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
                    // 插入图片
                    patriarch.createPicture(anchor, wb.addPicture(
                            byteArrayOut.toByteArray(),
                            HSSFWorkbook.PICTURE_TYPE_JPEG));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

解决ImageIO.read(file);读取的图片,缩放处理后变色问题:

BufferedImage bufferImg= ImageIO.read(file);

改为

//解决图片变色问题
BufferedImage _img = ImageIO.read(file);
BufferedImage bufferImg= new BufferedImage(_img.getWidth(),_img.getHeight(),BufferedImage.TYPE_INT_RGB);
bufferImg.getGraphics().drawImage(_img, 0, 0, null);
//...
ImageIO.write(bufferImg, "jpg", byteArrayOut);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值