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. 2019-2020 ACM-ICPC Brazil Subregional Programming Contest (11/13)

    \(2019-2020\ ACM-ICPC\ Brazil\ Subregional\ Programming\ Contest\) \(A.Artwork\) 并查集,把检测区域能在一起的检测器放在 ...

  2. 【洛谷 p3390】模板-矩阵快速幂(数论)

    题目:给定n*n的矩阵A,求A^k. 解法:利用矩阵乘法的定义和快速幂解答.注意用负数,但是数据太弱没有卡到我......(P.S.不要在 typedef long long  LL; 前使用 LL. ...

  3. 2019HDU多校 Round4

    08 K-th Closest Distance 题意:询问区间l,r中与数p的距离为第k大的数 求这个距离 题解:很裸的主席树 二分答案 然后可以用主席数判断在这个区间内 一段值域内出现的数 之前没 ...

  4. Codeforces Round #646 (Div. 2) E. Tree Shuffling(树上dp)

    题目链接:https://codeforces.com/contest/1363/problem/E 题意 有一棵 $n$ 个结点,根为结点 $1$ 的树,每个结点有一个选取代价 $a_i$,当前 $ ...

  5. 线段树扫描线(一、Atlantis HDU - 1542(覆盖面积) 二、覆盖的面积 HDU - 1255(重叠两次的面积))

    扫描线求周长: hdu1828 Picture(线段树+扫描线+矩形周长) 参考链接:https://blog.csdn.net/konghhhhh/java/article/details/7823 ...

  6. 通过k8s部署dubbo微服务并接入ELK架构

    需要这样一套日志收集.分析的系统: 收集 -- 能够采集多种来源的日志数据 (流式日志收集器) 传输 -- 能够稳定的把日志数据传输到中央系统 (消息队列) 存储 -- 可以将日志以结构化数据的形式存 ...

  7. MySQL 基础面试题

    请写出什么是事务? 事务是一组不可分割的 DML 语句,事务处理可以用来维护数据库的完整性,保证一组 SQL 语句要么全部执行成功,要么全部不执行,只有 InnoDB 存储引擎才支持事务 . 事务的特 ...

  8. IFIX 5.9 历史数据 曲线 (非SQL模式)

    装完 ifix 5.9 默认是没有Hist 开头的 历史数据源的,没存,至少我装的版本是这样. 那个Historian 也没有安装包,好像还要授权,自己研究不了. 1 先把数据存本地 在你的安装包里 ...

  9. Web 开发之 HTTP/2 & SPDY & HTTP 1.1 & HTTP 对比分析详解!

    1 https://zh.wikipedia.org/wiki/HTTP/2 HTTP/2 维基百科,自由的百科全书                         HTTP/2(超文本传输协议第2版 ...

  10. 24 WAYS to impress your friends

    24 WAYS to impress your friends 24 ways is the advent calendar for web geeks. For twenty-four days e ...