NPOI 在指定单元格导入导出图片
NPOI 在指定單元格導入導出圖片
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]);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 里的字節數組屬性
除此之外,還支持直接導入的時候將圖片信息 Map 到 IPictureData 屬性上,但是覺得還是字節數組更通用一些,如果對此感興趣可以參考項目源碼以及單元測試
More
感謝 @ZeguangZhang94 童鞋提出的需求和幫忙測試~
如果你也有類似的讀取指定單元格的圖片或者在指定單元格插入圖片的需求,可以試一下上面的方法,希望對你有幫助,可以直接引用我的類庫或者直接拷貝源碼到自己的項目里使用
References
https://github.com/WeihanLi/WeihanLi.Npoi
https://github.com/WeihanLi/WeihanLi.Npoi/blob/dev/src/WeihanLi.Npoi/NpoiExtensions.cs#L1143
https://stackoverflow.com/questions/24084129/read-image-from-excel-file-using-npoi
https://stackoverflow.com/questions/41138848/add-image-to-excel-xlsx-using-npoi-c-sharp
https://github.com/WeihanLi/WeihanLi.Npoi/issues/99
總結
以上是生活随笔為你收集整理的NPOI 在指定单元格导入导出图片的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何容器化你的 ASP.Net Core
- 下一篇: iNeuOS 工业互联网操作系统,在核工