Excel单元格插入图片,并自适应宽高——保姆级教程

Excel单元格插入图片,并自适应宽高——保姆级教程

author:陈镇坤27

日期:2022年3月22日

创作不易,转载请注明来源

摘要:计算图片高宽像素,将Excel单元格高宽单位转化为以像素为单位,按目的坐标插入图片。

特别说明:示例为:XSSFSheet


——————————————————————————————

需求

市场需求,要在excel中和word文档中插入定制化的公司logo。

word文档中,logo图案要和标题同行且位于两侧,左侧的居左对齐,右侧的居右对齐。

这种需求,要么方案一:做表格,要么就是计量空字符,在居左对其的标题右边,按空格数插入图片,使图片居右对齐。

表格虽然可以设置无边框,但电子版会产生虚线,因此被否。

计量空格又没有达到产品的自适应居右对齐,最后也被否决。

最终,word文档取消了标题和logo同行的需求。

excel的话,要求在合并的单元格中,拆分出一列,来存放居右对齐的logo图案。当拉动边框时,logo会自适应列宽伸缩。

效果图

在这里插入图片描述

问题

如何将图片居右对齐,插入合并后的单元格中,并且保证logo图案等比缩小放大。

知识准备

需要知道的是,要手术级操作excel单元格,必须深入掌握excel相关知识。首先要了解的便是不同excel版本、字体大小对列宽的影响。本文远远达不到该程度,仅作为通识学习所用

一个比较清晰的单位解释文章地址:https://zhuanlan.zhihu.com/p/78307080?from_voters_page=true

1、excel的单元格高和宽的计量单位不一致。

高以point(点)计,宽以字符计。

2、当没有全局指定列宽时,列宽默认设置8个字符宽度。

3、sheet指定列设置列宽的方法,第二个列宽参数单位是1/256个字符。

sheet1.SetColumnWidth(1, 100 * 256);

4、sheet指定列设置高度的两个方法:

void setHeight(short height);	//	入参单位缇,是1/20 points
 void setHeightInPoints(float height);	//入参单位为1 points

5、excel单元格操作方法的入参和出参,有时候是标准单位,有时候又是百分比的标准单位。要根据api源码注释来判断。

6、1 inch = 72 point = 96 px

7、sheet提供的查询指定列宽值,并以px为单位表示的方法如下:

float getColumnWidthInPixels(int columnIndex);

8、合并单元格,是合并了“区域”,但单元格本身依然存在。

9、excel操作单元格的宽度,是对该单元格所处列的调整,因此在计算距离插入图片时,若图片设置了自适应,则必须注意后面的excel单元格生成时对该单元格的宽度的影响是否会导致图片被压缩。

10、sheet添加图片的方法:

Picture createPicture(ClientAnchor anchor, int pictureIndex);

11、anchor是“单元格锚”(理解成船锚),指示图片所处的位置,设置坐标时,需要知道图片所处的第一个单元格的左下角坐标和图片所处的最后一个单元格的右上角坐标。中心点为单元格的左下角。——这一块是我的理解,源码并没有对此做很多解释。

12、EMUs用于基于矢量的绘图和嵌入图片中的坐标。它是厘米与英尺间的一个虚拟单位。

Units的一个转化px为EMUs的方法

 /**
     * Converts pixels to EMUs
     * @param pixels pixels
     * @return EMUs
     */
    public static int pixelToEMU(int pixels) {
        return pixels*EMU_PER_PIXEL;
    }

代码

private void fillExcelLogo(XSSFWorkbook book, String waterMarkCompanyLogo, Sheet sheet1, Cell finalCell,Row row,int leftTopCellNum) {
        if (StringUtils.isBlank(waterMarkCompanyLogo)) {
            return;
        }

        Cell cell1 = null;
        Cell cell2 = finalCell;
        HttpURLConnection conn = null;
        InputStream inputStream = null;
        BufferedImage image = null;
        try {

            URL url = new URL(waterMarkCompanyLogo);
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(20 * 1000);
            ByteArrayOutputStream output = new ByteArrayOutputStream();

            inputStream = conn.getInputStream();
            IOUtils.copy(inputStream, output);
            //  必须准备两份资源!!!
            ByteArrayInputStream inputStreamPic = new ByteArrayInputStream(output.toByteArray());
            ByteArrayInputStream imageStream = new ByteArrayInputStream(output.toByteArray());
            image = ImageIO.read(imageStream);
			
            //	添加图片,并获得图片全局序号
            int pictureIdx = book.addPicture(inputStreamPic, Workbook.PICTURE_TYPE_JPEG);
            
            //	计算获得图片在文档中的初始化高宽
            float initWith = 0;
            float initHigh = 0;
            //  1 inch = 72 point = 96 px 
            float v = row.getHeightInPoints() / 72f;
            initHigh = v * 96f;
            float highScaler = initHigh/(float) image.getHeight();
            initWith = (float)image.getWidth() * highScaler;
		   //	由于图片向右顶格,则锚的最后一个单元格为最右边的单元格。
            //	因为表格中列宽不一,因此需计算所处图片第一个单元格位置。
            int i1 = cell2.getColumnIndex() + 1 - leftTopCellNum;
            int allColumWithInPx = 0;
            for (int i = 0; i < i1; i++) {
                allColumWithInPx = allColumWithInPx + Math.round(sheet1.getColumnWidthInPixels(row.getCell(leftTopCellNum+i).getColumnIndex()));
            }
            int columWidthInPx = allColumWithInPx / i1;
            int i = Math.round(initWith) / columWidthInPx;
            if (i > 0 && i < (finalCell.getColumnIndex() - leftTopCellNum)) {
                cell1 = row.getCell(cell2.getColumnIndex() - i);
            } else if (i >= (finalCell.getColumnIndex() - leftTopCellNum)) {
                cell1 = row.getCell(leftTopCellNum);
            } else {
                cell1 = cell2;
            }

            CreationHelper helper = sheet1.getWorkbook().getCreationHelper();
            ClientAnchor anchor = helper.createClientAnchor();
            //  图像右上角所在单元格的图像右上角坐标
            anchor.setDx2(Units.pixelToEMU(columWidthInPx));
            anchor.setDy2(Units.toEMU(row.getHeightInPoints())); //
            //  图像左下角所在单元格的图像左下角坐标
            anchor.setDx1(0); // TODO: 2022/3/18 理应事实计算,为方便直接左下角顶格处理即可
            anchor.setDy1(0);
            //  图像左下角所处单元格与图像右上角所处单元格
            anchor.setCol1(cell1.getColumnIndex());
            anchor.setRow1(cell1.getRowIndex());
            anchor.setCol2(cell2.getColumnIndex());
            anchor.setRow2(cell2.getRowIndex());

            //  边框自适应(拉动单元格时,图片追随)
            anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
            //  最终插入图片
            Drawing drawing = sheet1.createDrawingPatriarch();
            drawing.createPicture(anchor, pictureIdx);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //	这是一个我自己封装的关闭资源的代码。不做分享。
            ResourceCloseUtil.closeJDBCResource2(inputStream);
        }
    }
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Excel中,你可以通过以下步骤将图片插入单元格中: 1. 首先,确保你的照片已经进行了预处理,使其大小适合插入单元格。这可以通过调整照片的尺寸来实现。 2. 然后,确保你的数据表中的“名称”列已经按照升序排序。这是因为在文件夹中,照片默认按照名称进行排序。 3. 在目标单元格上右击,选择“添加批注”。 4. 在批注输入框中删除所有文字。 5. 将鼠标移动到批注输入框的边线上,当指针变成十字箭头时,单击鼠标右键。 6. 选择“设置批注格式”,然后选择“颜色与线条”。 7. 在“填充效果”选项卡中,选择“图片”。 8. 单击“选择图片”按钮,选择要插入的图片。 这样,你就可以将图片插入到Excel单元格中了。请注意,这些步骤中的引用内容\[1\]\[2\]提供了详细的操作说明。 #### 引用[.reference_title] - *1* [【知识兔Excel教程】怎么批量插入大量图片Excel表格里?](https://blog.csdn.net/zhishitu0/article/details/124892348)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [在excel中添加图片](https://blog.csdn.net/knxw0001/article/details/6908301)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈镇坤27

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值