java POI在excel中插入等比例缩放的图片

这个缩放的比例不是很准确,但还凑合能用,目前本人找不到其它方法,就先用这个。

先看一个关键的API方法:void org.apache.poi.ss.usermodel.Picture.resize(double scaleX, double scaleY),一定要清楚这个方法中的参数 scaleX 和 scaleY 的比例是最终图片的宽高与单元格宽高的比例,不是与原图片宽高的比例。(而且当scaleX=1时,按道理应该占满单元格,但我测试后一直占不满不知道为什么,这可能也是最后比例不准确的原因之一)

测试代码在下面,大体说明一下这个代码:根据旧的excel,生成新的excel,新的excel需要在原有基础上插入一个图片,插入图片的位置是批注为“img”的单元格,生成的图片宽是70PX(可以根据参数调整),高度是根据最终图片宽度与原图的比例调整的,如果原图的宽度小于70PX,则直接插入原图。引入需要的依赖后,创建新类复制代码,可直接测试,缩放图片的关键部分都有注释,这是写好的业务代码,不是demo,所以有些冗长,可根据自身需要删除不必要的部分。

package com.buptnu.excel;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PushbackInputStream;

import javax.imageio.ImageIO;

import org.apache.poi.POIXMLDocument;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.Comment;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Picture;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class ExcelUtils {
	
	/**
	 * 生成Excel
	 * @param targetPath 原excel文件地址
	 * @param imgPath 图片地址
	 * @param newFilePath 生成的新excel文件地址
	 * @param width 生成的新的图片宽度,单位是像素
	 */
	public static void dataExportExcel(String targetPath, String imgPath, String newFilePath, double width) {
		InputStream input = null;
		OutputStream output = null;
		Workbook workbook = null;
		try {
			input = new FileInputStream(targetPath);
			if (!input.markSupported()) {
				input = new PushbackInputStream(input, 8);
			}
			if (POIFSFileSystem.hasPOIFSHeader(input)) {
				workbook= new HSSFWorkbook(input);// excel 2003
		    } else if (POIXMLDocument.hasOOXMLHeader(input)) {
		    	workbook = new XSSFWorkbook(OPCPackage.open(input));// excel 2007
		    }
			Sheet sheet = workbook.getSheetAt(0);
			for (int i = 0; i < sheet.getLastRowNum() + 1; i++) {
				Row row = sheet.getRow(i);
				if (row == null) {
					continue;
				}
				for (int j = 0; j < row.getLastCellNum(); j++) {
					Cell cell = row.getCell(j);
					if (cell == null) {
						continue;
					}
					Comment comment = cell.getCellComment();
					if (comment == null) {
						continue;
					}
					String commentValue = comment.getString().getString().trim();
					if (commentValue.equals("img")) {
						ExcelUtils.replaceImage(workbook, sheet, cell, imgPath, j, i, width);
					}
					cell.removeCellComment();
				}
			}
			File file = new File(newFilePath);
			if (!file.exists()) {
				file.createNewFile();
			}
			output = new FileOutputStream(newFilePath);
			workbook.write(output);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (input != null) {
				try {
					input.close();
				} catch (IOException e) { }
			}
			if (output != null) {
				try {
					output.close();
				} catch (IOException e) { }
			}
		}
	}
	
	/**
	 * 替换图片
	 * @param book
	 * @param sheet
	 * @param cell
	 * @param jdImagePath
	 * @param jdcol
	 * @param jdrow
	 * @param width
	 * @return
	 * @throws Exception
	 */
	public static Workbook replaceImage(Workbook book, Sheet sheet, Cell cell, String jdImagePath, int jdcol, int jdrow, double width) throws Exception {
    	InputStream jdis;
    	byte[] jdbytes = null;
		try {
			jdis = new FileInputStream(jdImagePath);
			jdbytes = IOUtils.toByteArray(jdis);
		} catch (Exception e) {
			e.printStackTrace();
		}
    	CreationHelper helper = book.getCreationHelper();  
    	Drawing drawing  = null;
    	if (sheet instanceof XSSFSheet) {
    		XSSFSheet xSSFSheet = (XSSFSheet)sheet;
    		drawing = xSSFSheet.getDrawingPatriarch();
    	} else if (sheet instanceof HSSFSheet) {
    		HSSFSheet hSSFSheet = (HSSFSheet)sheet;
    		drawing = hSSFSheet.getDrawingPatriarch();
    	}
    	if (drawing == null) {
    		drawing = sheet.createDrawingPatriarch(); 
    	}
    	// 图片插入坐标  
    	if (-1 != jdcol && -1 != jdrow) {
    		int jdpictureIdx = book.addPicture(jdbytes, Workbook.PICTURE_TYPE_JPEG);// 根据需要调整参数,如果是PNG,就改为 Workbook.PICTURE_TYPE_PNG
    		ClientAnchor jdanchor = helper.createClientAnchor();  
	    	jdanchor.setCol1(jdcol);
	    	jdanchor.setRow1(jdrow);
	    	// 获取原图片的宽度和高度,单位都是像素
	    	File image = new File(jdImagePath);
	    	BufferedImage sourceImg = ImageIO.read(image);
	    	double imageWidth = sourceImg.getWidth();
	    	double imageHeight = sourceImg.getHeight();
	    	// 获取单元格宽度和高度,单位都是像素
	    	double cellWidth = sheet.getColumnWidthInPixels(cell.getColumnIndex());
	    	double cellHeight = cell.getRow().getHeightInPoints() / 72 * 96;// getHeightInPoints()方法获取的是点(磅),就是excel设置的行高,1英寸有72磅,一般显示屏一英寸是96个像素
	    	// 插入图片,如果原图宽度大于最终要求的图片宽度,就按比例缩小,否则展示原图
	    	Picture pict = drawing.createPicture(jdanchor, jdpictureIdx);
	    	if (imageWidth > width) {
	    		double scaleX = width / cellWidth;// 最终图片大小与单元格宽度的比例
	    		// 最终图片大小与单元格高度的比例
	    		// 说一下这个比例的计算方式吧:( imageHeight / imageWidth ) 是原图高于宽的比值,则 ( width * ( imageHeight / imageWidth ) ) 就是最终图片高的比值,
	    		// 那 ( width * ( imageHeight / imageWidth ) ) / cellHeight 就是所需比例了
		    	double scaleY = ( width * ( imageHeight / imageWidth ) ) / cellHeight;
	    		pict.resize(scaleX, scaleY);
	    	} else {
	    		pict.resize();
	    	}
    	}
    	return book;
    }
	
	public static void main(String[] args) {
		ExcelUtils.dataExportExcel("F:\\test.xlsx", "F:\\test1.jpg", "F:\\test2.xlsx", 70);
	}
	
}

maven的POI依赖:

        <dependency>
          <groupId>org.jxls</groupId> 
          <artifactId>jxls-poi</artifactId> 
          <version>1.0.9</version> 
        </dependency>

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

 

  • 11
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Java使用Apache POI可以实现向Excel插入图片。下面我将介绍一下具体实现步骤: 1. 首先需要导入POI相关的jar包。可以从官网上下载最新版本的POI,然后将poi-xxx.jar、poi-ooxml-xxx.jar、poi-ooxml-schemas-xxx.jar、ooxml-lib\dom4j-xxx.jar、ooxml-lib\xmlbeans-xxx.jar这些jar包导入到项目。 2. 创建一个工作簿对象,并在其创建一个工作表对象。 ``` Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet1"); ``` 3. 创建一个文件输入流对象,读取图片文件。 ``` InputStream inputStream = new FileInputStream("图片文件路径"); ``` 4. 将图片数据读取到一个字节数组。 ``` byte[] bytes = IOUtils.toByteArray(inputStream); ``` 5. 创建一个绘图对象,并将图片数据添加到绘图对象。 ``` Drawing<?> drawing = sheet.createDrawingPatriarch(); ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, 0, 0, 1, 1); Picture pic = drawing.createPicture(anchor, workbook.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG)); ``` 6. 将Excel文件保存到本地。 ``` FileOutputStream outputStream = new FileOutputStream("Excel文件保存路径"); workbook.write(outputStream); outputStream.close(); ``` 以上就是使用Java POIExcel插入图片的具体实现步骤。需要注意的是,这里使用的是XSSFWorkbook和XSSFClientAnchor,所以生成的Excel文件格式是xlsx。如果需要生成xls格式的文件,需要使用HSSFWorkbook和HSSFClientAnchor。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值