当前位置: 首页 > news >正文

Spring Boot Apache POI 中,用于插入图片 XSSFPicture.resize()的用法讲解

示例代码:

// 插入签名图片,固定在签名图片行的C列插入签名图片 if (signatureImageRow != null) { // 获取制表人签名图片(bmp格式) byte[] signatureImage = userService.getSignatureImage(PublicUtils.getUserName()); if (signatureImage != null && signatureImage.length > 0) { try { int pictureType = XSSFWorkbook.PICTURE_TYPE_DIB; // BMP 对应 PICTURE_TYPE_DIB int pictureIdx = workbook.addPicture(signatureImage, pictureType); XSSFDrawing drawing = (XSSFDrawing) sheet.createDrawingPatriarch(); // 锚定到C列(索引2),跨越一个单元格(C列到D列,因为C列和D列已经合并单元格了) XSSFClientAnchor anchor = new XSSFClientAnchor( 0, 0, 0, 0, 2, signatureImageRow.getRowNum(), // 起始列C,起始行 3, signatureImageRow.getRowNum() // 结束列D,结束行 ); anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE); XSSFPicture picture = drawing.createPicture(anchor, pictureIdx); picture.resize(); // 图片原始尺寸,可以再追加 picture.resize(scale); 缩小或扩大图片,但必须保留 picture.resize() 这句代码,实际测试可以显示图片原始尺寸 picture.resize(0.4); // 图片原始尺寸比例的 40%,并且必须保留 picture.resize(),不然无法显示图片,实际测试可以显示图片调整尺寸 } catch (Exception e) { log.error("插入签名图片失败", e); } } }

picture.resize(); // 图片原始尺寸,可以再追加 picture.resize(scale); 缩小或扩大图片,但必须保留 picture.resize() 这句代码,实际测试可以显示图片原始尺寸 picture.resize(0.4); // 图片原始尺寸比例的 40%,并且必须保留 picture.resize(),不然无法显示图片,实际测试可以显示图片调整尺寸 经过测试确认了。但是为什么呢?

在 Apache POI 中,XSSFPicture.resize()方法的行为设计如下:

  • 无参resize():根据图片的原始尺寸重新计算并设置锚点的dx2dy2(即图片显示区域的宽度和高度),使图片能够以原始比例完整显示。它会忽略当前锚点的已有值,直接覆盖。

  • 带参resize(double scale):此方法通常会在当前锚点已有尺寸的基础上应用缩放因子,或者先调用无参resize()获取原始尺寸,再乘以缩放因子调整。但具体实现可能依赖于锚点的初始状态。

为什么单独调用resize(0.4)不显示图片?

在你创建锚点时,dx2dy2均设为 0(因为锚点构造函数中的参数0,0,0,0表示左上角偏移为0,右下角偏移也为0,即图片显示区域大小为 0)。当直接调用resize(0.4)时,POI 内部可能:

  1. 试图基于当前锚点的dx2/dy2(均为 0)进行缩放,结果仍是 0,因此图片尺寸为 0,不可见。

  2. 或者,resize(scale)需要锚点已有一个有效的尺寸作为基础,但初始值为 0,导致计算异常。

而先调用无参resize()强制将锚点尺寸设置为图片原始大小(覆盖dx2/dy2为对应 EMU 值),此时锚点有了正确的尺寸。接着调用resize(0.4)时,POI 会基于这个有效尺寸进行缩放,最终设置新的尺寸为原始大小的 40%,图片得以正确显示。

为什么这种设计?

这种设计可能是为了保持方法调用的灵活性:无参resize()用于将图片还原为原始大小,而带参resize(scale)用于在已有尺寸基础上调整比例。如果锚点未初始化,则带参方法无法正确工作。

可靠的替代方案

既然你已验证先调用无参resize()再调用带参resize(scale)有效,可以继续使用这种方式。不过,为了更精确控制图片尺寸,推荐直接通过锚点设置固定 EMU 值(如前文所述),这样可以完全避免依赖resize的内部行为,代码也更清晰可控。例如:

java

// 创建锚点并直接指定目标尺寸(像素转 EMU) int targetWidthEmu = 80 * 9525; int targetHeightEmu = 60 * 9525; XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, targetWidthEmu, targetHeightEmu, 2, rowNum, 2, rowNum); anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE); XSSFPicture picture = drawing.createPicture(anchor, pictureIdx); // 不调用任何 resize()

这种方法不受resize内部逻辑干扰,图片会严格按照指定尺寸显示。


XSSFClientAnchor是 Apache POI 中用于在 Excel 工作表(XSSF 格式)中定位图片、图表等绘图对象的锚点类。它定义了对象的起始和结束单元格,以及相对于这些单元格的偏移量,从而精确控制对象的位置和大小。

构造函数签名

java

XSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, int col1, int row1, int col2, int row2)

参数详解

所有坐标和偏移量的单位均为EMU(English Metric Unit,英制公制单位),1 EMU = 1/9525 英寸,或约为 1/360000 厘米。在 96 DPI 的屏幕上,1 像素 ≈ 9525 EMU。POI 提供了Units.pixelToEMU(int pixels)Units.toEMU(double points)等工具方法进行转换。

参数类型含义
dx1int左上角相对于起始单元格左边框的 X 偏移量(EMU)。
dy1int左上角相对于起始单元格上边框的 Y 偏移量(EMU)。
dx2int右下角相对于结束单元格左边框的 X 偏移量(EMU)。
dy2int右下角相对于结束单元格上边框的 Y 偏移量(EMU)。
col1int起始单元格的列索引(从 0 开始)。
row1int起始单元格的行索引(从 0 开始)。
col2int结束单元格的列索引(从 0 开始)。
row2int结束单元格的行索引(从 0 开始)。

工作原理

图片的左上角位于单元格(col1, row1)的左上角,再向右偏移dx1、向下偏移dy1的位置。
图片的右下角位于单元格(col2, row2)的左上角,再向右偏移dx2、向下偏移dy2的位置。
因此,图片的实际宽度 =(col2 - col1)列的宽度之和 +(dx2 - dx1),实际高度 =(row2 - row1)行的高度之和 +(dy2 - dy1)

常见用法示例

1. 将图片放入单个单元格(不跨列行)

希望图片完全位于 B2 单元格(列索引 1,行索引 1)内,并设置图片宽 100 像素、高 80 像素:

java

int col = 1, row = 1; int widthPx = 100, heightPx = 80; int widthEmu = Units.pixelToEMU(widthPx); int heightEmu = Units.pixelToEMU(heightPx); XSSFClientAnchor anchor = new XSSFClientAnchor( 0, 0, widthEmu, heightEmu, // 左上角无偏移,右下角偏移等于图片尺寸 col, row, col, row // 起始和结束是同一个单元格 );
2. 将图片放入合并的单元格(如 C 和 D 列合并)

假设 C 列索引 2,D 列索引 3,合并后单元格占据两列。如果希望图片居中显示在合并区域内,可以设置起始列和结束列覆盖合并范围,并适当调整偏移:

java

int startCol = 2, endCol = 3; // 跨越两列 int startRow = 2, endRow = 2; // 单行 int widthEmu = Units.pixelToEMU(150); int heightEmu = Units.pixelToEMU(100); // 将图片放在合并单元格的左上角,尺寸固定 XSSFClientAnchor anchor = new XSSFClientAnchor( 0, 0, widthEmu, heightEmu, startCol, startRow, endCol, endRow );
3. 设置图片随单元格移动和缩放

通过anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE)可以使图片在单元格移动或调整大小时自动适应。其他可选类型:

  • MOVE_ONLY:只随单元格移动,不缩放。

  • DONT_MOVE_AND_RESIZE:既不移动也不缩放。

注意事项

  • 偏移量dx1, dy1, dx2, dy2必须是相对单元格的左上角计算,而不是单元格内部的其他位置。

  • 如果希望图片完全填充单元格(不保持比例),可以将dx2dy2设为对应单元格的宽高(可通过sheet.getColumnWidthInPixels(col)row.getHeightInPoints()计算),但这样可能导致图片变形。

  • 使用picture.resize()会自动调整锚点尺寸以匹配图片原始比例,但会覆盖你手动设置的dx2, dy2。如果希望精确控制尺寸,建议不要调用resize(),而是直接通过锚点指定尺寸。

  • EMU 转换:Units.pixelToEMU(pixels)将像素转换为 EMU,Units.EMUToPixel(emu)反之。POI 4.0+ 提供这些方法。

结合picture.resize()的注意事项

如果你先创建了锚点(dx2,dy2 可能为 0),然后调用picture.resize(),它会将锚点尺寸设置为图片原始尺寸(覆盖 dx2,dy2)。如果之后再调用picture.resize(scale),会在当前锚点尺寸基础上缩放。这就是为什么你的代码中需要先resize()resize(0.4)才能生效:第一次设置原始尺寸,第二次缩放。

理解这些参数后,你可以灵活控制图片在工作表中的位置和大小。

http://www.jsqmd.com/news/414661/

相关文章:

  • 分析昆明受欢迎的柠檬撒撇店,哪家能满足你的味蕾需求? - 工业品牌热点
  • 五大实力人力外包品牌盘点,全品类服务赋能企业高效运营 - 包罗万闻
  • Linux DMA(一)
  • 2026年工业溶气气浮机厂家推荐:平流/浅层/沉淀式气浮设备供应商精选 - 品牌推荐官
  • 2026工业压力变送器优质厂家推荐指南:智能电磁流量计、检测密度计、水位液位计、浮子流量计、涡轮流量计选择指南 - 优质品牌商家
  • 2026靠谱水果店加盟品牌推荐 - 优质品牌商家
  • OpenClaw 在严肃场景下的实践:迁移 Ingress NGINX
  • 2026北京留学中介排名:主流机构服务实力对比分析 - 品牌排行榜
  • 天猫超市卡回收靠谱平台推荐 - 京顺回收
  • 2026年酒店易耗品价格排名,邦亿客宾馆易耗品价格合理吗 - 工业品网
  • 2026上海留学中介排名及服务能力深度解析 - 品牌排行榜
  • 双头车床、管螺纹车床、龙门铣床采购全指南:行业趋势 + 三大平台对比 + 精准选购建议 - 品牌推荐大师1
  • 西南靠谱水果店加盟品牌推荐:一站式水果加盟扶持、中高端水果店加盟、低风险水果实体店加盟、全国水果加盟品牌哪家好选择指南 - 优质品牌商家
  • 北京海关纳税争议解决律师怎么选,口碑好的在这里 - 工业推荐榜
  • 探讨质成新材料的产品效果,各地区靠谱企业怎么收费 - mypinpai
  • 解读2026年驻马店定制衣柜优质生产商,哪家排名靠前 - 工业设备
  • 2026年比较可靠的留学机构有哪些?这份详细指南请收好 - 品牌排行榜
  • 2026年校园招聘岗位哪个性价比高,为你揭晓答案 - 工业品牌热点
  • 2026最新PVC发泡板十一大厂家实力排行榜:聚焦全屋健康,基于环保性能与市场口碑的权威推荐榜单 - 十大品牌榜
  • 2026年天津家庭全屋墙面用乳胶漆刷新品牌推荐,哪家性价比高 - 工业品牌热点
  • 金三银四春招来袭,三天吃透Java面试八股文(2026最新整理)
  • 细聊2026年廊坊靠谱的整屋全包专业公司,哪家性价比高 - myqiye
  • 2026深圳留学机构推荐:聚焦服务与资源的选择指南 - 品牌排行榜
  • 2026老年智慧食堂厂家推荐榜,带你了解优质厂商,可视验收秤/智慧食堂系统/食堂称重系统,智慧食堂工厂联系方式 - 品牌推荐师
  • Hugging Face 直跑3万+ LoRA模型的技术实现
  • 盘点昆明假期补课服务,滇云教育性价比高,推荐假期初中补课班 - myqiye
  • 2026年九江可靠的兵器类国防特色专业学校,分享优质院校 - 工业推荐榜
  • Prompt Engineering(提示词工程)
  • 2026年汽车零部件清洗机公司权威推荐:通过式超声波清洗机、高压清洗机、高压清洗机、五金模具清洗机选择指南 - 优质品牌商家
  • 基于国密GB35114协议的国标GB28181平台EasyGBS视频联网安全能力解析