您好,想问一下怎么嵌入图片到单元格

使用问题 · 84 次浏览
zdf153 创建于 23天22小时前

您好,想问一下怎么嵌入图片到单元格


回复内容
CL 23天16小时前
#1

需要直接使用NPOI类库。

下面是AI的回复,可以参考:

在 NPOI 中插入图片并让它根据单元格大小自动缩放,一般思路是:

  1. 把图片读入 byte[]

  2. 将图片添加到工作簿,拿到 pictureIndex

  3. 在 Sheet 上创建一个 DrawingPatriarch

  4. 用 ClientAnchor 定位到目标单元格

  5. 创建 Picture

  6. 取出目标单元格的像素宽高,算出缩放比例

  7. 调用 picture.Resize(scaleX, scaleY)

下面给出一个针对 XSSF(.xlsx)和 HSSF(.xls)的示例代码,你可以根据自己用的格式稍作调整。

using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;    // 如果是 .xlsx
using NPOI.HSSF.UserModel;    // 如果是 .xls
using NPOI.SS.Util;
using NPOI.SS.usermodel;
using System.IO;

// ...

// 1. 读图片
byte[] bytes = File.ReadAllBytes("logo.png");

// 2. 新建工作簿(XSSFWorkbook 或 HSSFWorkbook)
IWorkbook workbook = new XSSFWorkbook(); // or new HSSFWorkbook();

// 3. 添加图片到工作簿,得到索引
int pictureIdx = workbook.AddPicture(bytes, PictureType.PNG);

// 4. 取 Sheet、Row、Cell
ISheet sheet = workbook.CreateSheet("Sheet1");
int rowIndex = 2, colIndex = 1; // 比如要放在 C3 (零基:row=2, col=1)
IRow row = sheet.CreateRow(rowIndex);
// 可先给行高、列宽设置好
row.HeightInPoints = 80;              // 行高 80 磅
sheet.SetColumnWidth(colIndex, 30*256); // 列宽 30 字符

// 5. 创建绘图容器
IDrawing drawing = sheet.CreateDrawingPatriarch();

// 6. 定位:ClientAnchor(col1, row1, col2, row2, dx1, dy1, dx2, dy2)
//    这里我们起始和结束都指定在同一个单元格(所以最后四个参数都用 0)
IClientAnchor anchor;
if (workbook is XSSFWorkbook)
{
    anchor = new XSSFClientAnchor(0, 0, 0, 0, colIndex, rowIndex, colIndex+1, rowIndex+1);
}
else
{
    anchor = new HSSFClientAnchor(0, 0, 0, 0, colIndex, rowIndex, colIndex+1, rowIndex+1);
}

// 7. 创建 Picture
IPicture pict = drawing.CreatePicture(anchor, pictureIdx);

// 8. 计算目标单元格的像素宽高
//    列宽:GetColumnWidth 单位是 1/256 个字符宽。转换为像素大致:pixels = width * 256 / 256 * 字符宽(px)
//             经验值:Excel 默认一个字符约 7px,这里直接用 NPOI 提供方法更准确
float cellWidthPx = sheet.GetColumnWidthInPixels(colIndex);
float cellHeightPx = row.HeightInPoints * (96f/72f); // 磅 -> 像素(假设 96 DPI)

// 9. 取得图片本身像素(需要额外解析 image)
using (var ms = new MemoryStream(bytes))
using (var img = System.Drawing.Image.FromStream(ms))
{
    float imgW = img.Width;
    float imgH = img.Height;
    // 取最小缩放比,保证图片完整显示且不超出单元格
    float scaleX = cellWidthPx / imgW;
    float scaleY = cellHeightPx / imgH;
    float scale = Math.Min(scaleX, scaleY);

    // 10. 缩放
    // XSSF 支持两个参数;HSSF 只有无参 Resize(),会按原图比例填充到锚指定的跨单元格区域
    if (pict is XSSFClientAnchor) // 或者 workbook is XSSFWorkbook
    {
        ((XSSFPicture)pict).Resize(scale, scale);
    }
    else
    {
        // HSSF 只能自动填充整个单元格区域:
        pict.Resize();
    }
}

// 11. 保存
using (var fs = new FileStream("output.xlsx", FileMode.Create, FileAccess.Write))
    workbook.Write(fs);

关键点说明

  • AddPicture:将图片二进制加入到 IWorkbook 中,并返回一个索引,用于后续绘图。

  • CreateDrawingPatriarch:在 Sheet 上创建绘图上下文,所有图形(图片、图表)都要走它。

  • ClientAnchor:定义图片的起止单元格(col1,row1 -> col2,row2),也可以用偏移量控制更精细的位置。在这里只占一个单元格区域。

  • 获取单元格像素尺寸

    • 列宽可以用 sheet.GetColumnWidthInPixels(colIndex)(NPOI 对于 XSSF/HSSF 都支持)。

    • 行高从 row.HeightInPoints 得到的是“磅”,再用 (96/72) 换算成像素(通常 Windows 显示 96 DPI)。

  • 缩放比例:取宽高的最小缩放比,保证图片既不变形(按比例缩放),又能完整显示在单元格内。

  • Resize(scaleX, scaleY):只有 XSSF 支持两个参数的精确缩放。HSSF 里无参数 Resize() 会把图片按原比例尽量填满你锚定的单元格区域。

这样就能让图片“贴”在某个单元格里,并自动按照单元格的实际尺寸做等比缩放了。

zdf153 回复 CL 23天5小时前 :

谢谢,按你的那个子程序改好了

回复主贴