NPOI 在指定单元格导入导出图片

Intro

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

导入Excel 时解析图片

xlsxlsx 的 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.Npoi1.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]);
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!;
}

导入时会自动将 byte[] 类型的属性尝试获取对应的单元格位置的图片,如果在对应的位置找到了图片就能够读取到图片的字节数组信息映射到 model 里的字节数组属性

More

感谢 @ZeguangZhang94 童鞋提出的需求和帮忙测试~

如果你也有类似的读取指定单元格的图片或者在指定单元格插入图片的需求,可以试一下上面的方法,希望对你有帮助

References

NPOI 在指定单元格导入导出图片的更多相关文章

  1. c#在Excel指定单元格中插入图片

    方法一: /// 将图片插入到指定的单元格位置,并设置图片的宽度和高度./// 注意:图片必须是绝对物理路径/// </summary>/// <param name="R ...

  2. NPOI 修改指定单元格字体颜色

    //创建一个字体颜色 IFont font = hssfworkbook.CreateFont(); //红色 font.Color = HSSFColor.Red.Index; //样式 ICell ...

  3. NPOI扩展--判断指定单元格是否为合并单元格和输出该单元格的行列跨度(维度)

    因工作需要用到跨合并单元格获取数据,所以写了个NPOI扩展类. 主要方法如下: 1.判断指定行/列索引(单元格)是否为合并单元格. 2.获取指定列索引的实际含有数据的单元格. 3.返回指定行/列索引的 ...

  4. 27.openpyxl 向指定单元格添加图片并修改图片大小 以及修改单元格行高列宽

    openpyxl 向指定单元格添加图片并修改图片大小 以及修改单元格行高列宽 from openpyxl import Workbook,load_workbook from openpyxl.dra ...

  5. dev gridview指定单元格cell获取坐标

    DevExpress.XtraGrid.Views.Grid.ViewInfo.GridViewInfo Info2 = gvQueryResult.GetViewInfo() as DevExpre ...

  6. 使用VBA将Excel指定单元格数据、字符串或者图表对象插入到Word模板指定书签处

    准备工作: 1.首先需要提供一个word模板,并且标记好您要插入书签的位置,定义书签的命名.如图 2.模拟您要插入的Excel原始数据和图表对象 插入代码如下: Private Sub Command ...

  7. python接口自动化测试--数据分离读取Excal指定单元格数据

    上一篇博客讲了怎么批量读取Excal单元格数据,现在咱们说一下怎么读取Excal指定单元格数据. 一.首先建一个Test_Main类 #!/usr/bin/python # -*- coding: U ...

  8. VBA赋值给指定单元格

    这是一个Range对象基本操作实例,对指定单元格赋值,然后使用弹窗获取值. 代码如下: Sub test1() Worksheets( MsgBox "工作表Sheet1内单元格A5中的值为 ...

  9. DataGridView单元格显示GIF图片

    本文转载:http://home.cnblogs.com/group/topic/40730.html DataGridView单元格显示GIF图片 gifanimationindatagrid.ra ...

随机推荐

  1. 2018 ccpc吉林 The Tower

    传送门:HDU - 6559 题意 在一个三维空间,给定一个点和他的三维速度,给定一个圆锥,问这个点最早什么时候能撞上圆锥. 题解 本来一直想着怎么求圆锥的方程,然后....队友:这不是二分吗!然后问 ...

  2. Bubble Cup 13 - Finals [Online Mirror, unrated, Div. 1] K. Lonely Numbers (数学)

    题意:定义两个数\(a,b\)是朋友,如果:\(gcd(a,b)\),\(\frac{a}{gcd(a,b)}\),\(\frac{b}{gcd(a,b)}\)能构成三角形,现在给你一个正整数\(n\ ...

  3. Codeforces Round #531 (Div. 3) E. Monotonic Renumeration (构造)

    题意:给出一个长度为\(n\)的序列\(a\),根据\(a\)构造一个序列\(b\),要求: ​ 1.\(b_{1}=0\) ​ 2.对于\(i,j(i\le i,j \le n)\),若\(a_{i ...

  4. 带有Python的音频处理(附带源码)

    由于博客播放不了音频,所以音频将以视频形式展现.公众号也正在进行抽书 音频素材请点击这里进行观看 往下拉就是文章地址 有时,在进行编程时,我们需要进行一些音频处理.编程中最常用的音频处理任务包括–加载 ...

  5. UVA-10815 Andy's First Dictionary (非原创)

    10815 - Andy's First Dictionary Time limit: 3.000 seconds Problem B: Andy's First DictionaryTime lim ...

  6. Leetcode(17)-电话号码的字母组合

    给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合. 给出数字到字母的映射如下(与电话按键相同).注意 1 不对应任何字母. 示例: 输入:"23" 输出:[&quo ...

  7. Leetcode(28)-实现strStr()

    实现 strStr() 函数. 给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始).如果不存在,则返 ...

  8. R语言学习2:绘图

    本系列是一个新的系列,在此系列中,我将和大家共同学习R语言.由于我对R语言的了解也甚少,所以本系列更多以一个学习者的视角来完成. 参考教材:<R语言实战>第二版(Robert I.Kaba ...

  9. Virtualbox 安装centos7虚拟机

    Virtualbox 安装centos7虚拟机 一,下载centos7 下载地址:https://mirrors.tuna.tsinghua.edu.cn/centos/7.9.2009/isos/x ...

  10. rm -rf .git/gc.log

    rm -rf .git/gc.log ➜ test git:(abc) gp Auto packing the repository in background for optimum perform ...