• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

c# NPOI 如何在指定单元格导入导出图片

c# 搞代码 4年前 (2022-01-09) 17次浏览 已收录 0个评论

Intro

我维护了一个 NPOI 的扩展(WeihanLi.Npoi),主要用来导入导出 Excel 数据,最近有网友提出了导入 Excel 的时候解析图片的需求,于是就有了本文的探索

导入Excel 时解析图片

xls 和 xlsx 的 API 稍有不同,详细可以直接参考以下代码,实现代码如下:

public static Dictionary<CellPosition, IPictureData> GetPicturesAndPosition(this ISheet sheet)
{
  var dictionary = new Dictionary<CellPosition, IPictureData>();
  if (sheet.Workbook is HSSFWorkbook)
  {
    foreach (var shape in ((HSSFPatriarch)sheet.DrawingPatriarch).Children)
    {
      if (shape is HSSFPicture picture)
      {
        var position = new CellPosition(picture.ClientAnchor.Row1, picture.ClientAnchor.Col1);
        dictionary[position] = picture.PictureData;
      }
    }
  }
  else if (sheet.Workbook is XSSFWorkbook)
  {
    foreach (var shape in ((XSSFDrawing)sheet.DrawingPatriarch).GetShapes())
    {
      if (shape is XSSFPicture picture)
      {
        var position = new CellPosition(picture.ClientAnchor.Row1, picture.ClientAnchor.Col1);
        dictionary[position] = picture.PictureData;
      }
    }
  }
  return dictionary;
}

CellPosition 是一个自定义的结构体,表示当前单元格的位置,源码如下:

public readonly struct CellPosition : IEquatable<CellPosition>
{
  public CellPosition(int row, int col)
  {
    Row = row;
    Column = col;
  }

  public int Row { get; }
  public int Column { get; }

  public bool Equals(CellPosition other)
  {
    return Row == other.Row && Column == other.Column;
  }

  public override bool Equals(object? obj) => obj is CellPosition other && Equals(other);

  public override int GetHashCode() => $"{Row}_{Column}".GetHashCode();
}

根据上面的代码,我们就可以获取到获取到所有的图片以及图片的所在位置,这样根据单元格位置去找图片信息的时候就会很方便了

导出 Excel 时设置图片

实现代码如下:

public static bool TryAddPicture(this ISheet sheet, int row, int col, byte[] pictureBytes, PictureType pictureType = PictureType.PNG)
{
  if (sheet is null)
  {
    throw new ArgumentNullException(nameof(sheet));
  }

  try
  {
    var pictureIndex = sheet.Workbook.AddPicture(pictureBytes, pictureType);

    var clientAnchor = sheet.Workbook.GetCreationHelper().CreateClientAnchor();
    clientAnchor.Row1 = row;
    clientAnchor.Col1 = col;

    var picture = (sheet.DrawingPatriarch ?? sheet.CreateDrawingPatriarch())
      .CreatePicture(clientAnchor, pictureIndex);
    picture.Resize();
    return true;
  }
  catch (Exception e)
  {
    Debug.WriteLine(e);
  }

  return false;
}

通过上面的代码我们就可以在指定的单元格设置图片,目前没有支持单元格合并操作,有需要自己进行修改

WeihanLi.Npoi

WeihanLi.Npoi 在 1.15.0 版本中增加了图片导入导出的支持,使用示例可以参考下面的单元测试:

[Theory]
[ExcelFormatData]
public async Task ImageImportExportTest(ExcelFormat excelFormat)
{
  using var httpClient = new HttpClient();
  var imageBytes = await httpClient.GetByteArrayAsync("https://weihanli.xyz/assets/avator.jpg");
  var list = Enumerable.Range(1, 5)
    .Select(x => new ImageTest() { Id = x, Image = imageBytes })
    .ToList();
  var excelBytes = list.ToExcelBytes(excelFormat);
  var importResult = ExcelHelper.ToEntityList<ImageTest>(excelBytes, excelFormat);
  Assert.NotNull(importResult);
  Assert.Equal(list.Count, importResult.Count);
  for (var i = 0; i < list.Count; i++)
  {
    Assert.NotNull(importResult[i<b style="color:transparent">本文来源gao@!dai!ma.com搞$$代^@码网*</b>]);
    var result = importResult[i]!;
    Assert.Equal(list[i].Id, result.Id);
    Assert.NotNull(result.Image);
    Assert.True(list[i].Image.SequenceEqual(result.Image));
  }
}

private class ImageTest
{
  public int Id { get; set; }

  public byte[] Image { get; set; } = null!;
}

搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:c# NPOI 如何在指定单元格导入导出图片
喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址