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

2023-11-19

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

先看一个关键的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>

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java POI在excel中插入等比例缩放的图片 的相关文章

随机推荐

  • 在WINDOW 系统下如何用批处理命令生成代码

    如图要实现一个每次编译都会自动重新生成的代码 一般是 软件版本相关的代码最适合这种自动生成 上图中需在用到编译时间和日期 来直接上代码 BEGIN COLOR 07 cls echo off ECHO ECHO 自动生成软件版本号 ECHO
  • Discuz 如何设置SSL类型的SMTP邮箱

    由于国际与国内均对垃圾邮件进行严格管控 我国 互联网信息服务管理办法 中国互联网协会反垃圾邮件规范 均对垃圾邮件进行说明与管理规范 鉴于服务器25端口被大量垃圾邮件充斥 严重影响广大用户正常使用 很多服务器不再提供25端口邮件服务 包括进站
  • QNX系统的ftp调试,连接FTP调试-QNX的PC104调试ftp

    如果你认为本系列文章对你有所帮助 请大家有钱的捧个钱场 点击此处赞助 赞助额1元起步 多少随意 锋影 e mail 174176320 qq com 板子上QNX系统ftp的调试 双网卡 IP分别为 192 192 1 10 192 192
  • Qt编程学习笔记

    新建项目 gt 其他项目 gt Empty qmake Project 添加新文件 项目 gt run gt Run in terminal 发现cin gt gt a无法向a输入数据 检查 pro文件发现缺少参数CONFIG consol
  • chrome黑暗模式设置

    1 前言 使用Chrome有很久了 但一直没发现有令人满意的黑暗模式 期间试过通过在谷歌商店中安装黑暗主题 但感觉不好 主要有以下 除了chrome的界面是黑暗模式外 打开其它的页面还是亮模式 我希望黑暗模式支持以下特性 chrome的标签
  • Android ViewPager实现导航页效果

    效果 源码地址 文章翻译自 https www cnblogs com aademeng articles 6238933 html 代码 MainActivity public class MainActivity extends App
  • mysql APPARENT DEADLOCK!!! Complete Status:Managed Threads: 3 (c3p0,druid)

    问题场景 由于在生产环境出现问题 应用挂掉 作为菜鸟运维 解决问题有点忙手忙脚 线上bug修复 重启tomcat 启动报错 错误截图在下面 根据日志分析像是死锁 使用C3P0连接池 tomcat启动完之后 还能正常运行 解决问题经过 网上有
  • v4l2在帧缓冲区预览摄像头

    在应用层通过v4l2 api将采集的摄像头数据yuv转为rgb后写到帧缓冲区达到预览摄像头的目的 程序运行后切换到tty下就可以看到 我的屏幕是bgra格式的 这点要注意 不同屏幕格式不同 不同r g b的偏移通过修改 0x00 lt lt
  • Activiti定时器事件

    定时器事件用于在特定的日期 时间或者周期触发一个事件 它们可以用做开始事件 中间事件 边界事件 边界事件可以是中断的 也可以是非中断的 默认是中断事件 即当触发定时器时 原执行实例会被删除 开始事件定时器 定时器开始事件用于在指定的时间点或
  • 专利检索工具网站分享

    当今有很多专利检索工具可供使用 以下是一些常用的专利检索工具网站 全球专利数据库 https patentscope wipo int search zh search jsf 中国专利数据库 http www pss system gov
  • 爬虫从入门到放弃——开源爬虫框架

    本文参考自知乎 供本人学习使用 作者 老夏 链接 https www zhihu com question 27042168 answer 70821088 目前主流的网络爬虫框架包括但不限于 Nutch Crawler4j WebMagi
  • java yaml配置处理,yaml格式化,yaml节点增加,删除。多yaml合并

    多环境配置文件管理 增加一个配置属性 多套环境配置文件需同时增加 如果忘记了 那么就报错 对多环境配置文件进行管理 使用yaml作为文件时 就涉及到yaml的一些解析 修改 新增操作 java管理yaml 1 环境依赖 2 snakeyam
  • C++基础3:仿函数

    系列文章目录 C 基础 开篇 C 基础1 从const关键字看变量的基础单元 类 C 基础2 构造函数 拷贝构造 赋值运算符重载 文章目录 系列文章目录 前言 一 什么是仿函数 二 实现步骤 1 定义类 2 重载 运算符 3 使用仿函数 4
  • pytorch 2.0初探:和pytorch 1.13的速度对比

    看到pytorch2 0出来了 而且宣传提速明显 一行代码即可提速43 左右 compiled model torch compile model We then measure speedups and validate accuracy
  • tex 表格中内容左对齐/居中/右对齐

    左对齐是l 右对齐是r 居中是c begin table centering caption label tab widgets Notation summary begin tabular l l 就是这里控制每一列的对齐方式 Notat
  • 史上最简单的SpringCloud教程

    在微服务架构中 需要几个基础的服务治理组件 包括服务注册与发现 服务消费 负载均衡 断路器 智能路由 配置管理等 由这几个基础组件相互协作 共同组建了一个简单的微服务系统 一个简答的微服务系统如下图 注意 A服务和B服务是可以相互调用的 作
  • 异常数据检测

    文章目录 效果一览 文章概述 部分源码 参考资料 效果一览 文章概述 信号分解算法 Matlab基于一维小波分解算法 Wavelet Decomposition 的信号分解算法 部分源码
  • 标准代码书写准则,避免屎山代码风格指南

    牛马程序员 强推 屎山代码风格指南 github 开源地址 https github com trekhleb state of the art shitcode tree master 这是一个你的项目应该遵循的标准代码书写准则的列表 把
  • centos7安装python3.x(多种方式)

    但行好事 莫问前程 有任何疑问请留言 作者有问必答哦 前言 centos系统本身默认安装有python2 x 版本x根据不同版本系统有所不同 可通过 python V 或 python version 查看系统自带的python版本 有一些
  • java POI在excel中插入等比例缩放的图片

    这个缩放的比例不是很准确 但还凑合能用 目前本人找不到其它方法 就先用这个 先看一个关键的API方法 void org apache poi ss usermodel Picture resize double scaleX double