.NET Core 使用NPOI讀取Excel返回泛型List集合

来源:https://www.cnblogs.com/itsvse/archive/2019/11/08/11821503.html
-Advertisement-
Play Games

我是一名 ASP.NET 程式員,專註於 B/S 項目開發。累計文章閱讀量超過一千萬,我的博客主頁地址:https://www.itsvse.com/blog_xzz.html 網上有很多關於npoi讀取excel表格的例子,很多都是返回一個Datatable的對象,但是我需要的是一個list集合, ...


我是一名 ASP.NET 程式員,專註於 B/S 項目開發。累計文章閱讀量超過一千萬,我的博客主頁地址:https://www.itsvse.com/blog_xzz.html

 

網上有很多關於npoi讀取excel表格的例子,很多都是返回一個Datatable的對象,但是我需要的是一個list集合,這裡就需要把Datatable轉成自己需要的List集合,所以,我封裝了一個方法,傳入class對象就能返回相應的list對象。

首先先看效果圖,如下:

 

 

模板

一共有4列,有很多行,其中只有2行有數據,如下圖:

 

特性

首先,定義一個特性,意義是對象的屬性對應表格的哪一列,代碼如下:

public class ColumnAttribute: Attribute
    {
        public ColumnAttribute(int index)
        {
            Index = index;
        }
        public int Index { get; set; }
    }

  

對象模型

將表格數據讀取出來,轉換成相應的對象集合,在對象的屬性標註上面定義的特性,代碼如下:

public class TestModel
    {
        [Column(0)]
        public string Name { get; set; }
        [Column(1)]
        public string Url { get; set; }
        [Column(2)]
        public string Date { get; set; }
        [Column(3)]
        public string Remark { get; set; }
    }

  

封裝的方法

nuget安裝npoi:

Install-Package DotNetCore.NPOI -Version 1.2.2

代碼如下:

public class ExcelHelper
    {
        /// <summary>
        /// 讀取excel轉換成list集合
        /// </summary>
        /// <typeparam name="T">對象</typeparam>
        /// <param name="stream">文件流</param>
        /// <param name="startIndex">從第幾行開始讀取</param>
        /// <param name="sheetIndex">讀取第幾個sheet</param>
        /// <returns></returns>
        public static IList<T> GetList<T>(Stream stream, int startIndex, int sheetIndex = 0)
            where T : class
        {
            IList<T> ts = new List<T>();
            try
            {
                IWorkbook workbook = WorkbookFactory.Create(stream);
                var sheet = workbook.GetSheetAt(sheetIndex);
                if (sheet != null)
                {
                    IRow firstRow = sheet.GetRow(0);
                    //一行最後一個cell的編號 即總的列數
                    int cellCount = firstRow.LastCellNum;
                    //最後一列的標號
                    int rowCount = sheet.LastRowNum;
                    for (int i = startIndex; i <= rowCount; ++i)
                    {
                        //獲取行的數據
                        IRow row = sheet.GetRow(i);
                        if (row == null) continue; //沒有數據的行預設是null       
                        {
                            T model = Activator.CreateInstance<T>();
                            for (int j = row.FirstCellNum; j < cellCount; ++j)
                            {
                                if (row.GetCell(j) != null)
                                {
                                    var rowTemp = row.GetCell(j);
                                    string value = null;
                                    if (rowTemp.CellType == CellType.Numeric)
                                    {
                                        short format = rowTemp.CellStyle.DataFormat;
                                        if (format == 14 || format == 31 || format == 57 || format == 58 || format == 20)
                                            value = rowTemp.DateCellValue.ToString("yyyy-MM-dd");
                                        else
                                            value = rowTemp.NumericCellValue.ToString();
                                    }
                                    else
                                        value = rowTemp.ToString();
                                    //賦值
                                    foreach (System.Reflection.PropertyInfo item in typeof(T).GetProperties())
                                    {
                                        var column = item.GetCustomAttributes(true).First(x => x is ColumnAttribute) as ColumnAttribute;
                                        if (column.Index == j)
                                        {
                                            item.SetValue(model, value);
                                            break;
                                        }
                                    }
                                }
                            }
                            ts.Add(model);
                        }
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                if (stream != null) stream.Close();
            }
            return ts;
        }
    }

  

調用代碼:

static void Main(string[] args)
        {

            FileStream fs = new FileStream(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "/test.xlsx", FileMode.Open, FileAccess.Read);
            var temp = ExcelHelper.GetList<TestModel>(fs, 3);
            var json1 = Newtonsoft.Json.JsonConvert.SerializeObject(temp.Where(x => !string.IsNullOrWhiteSpace(x.Name)).ToList());
            Console.WriteLine(json1);
            Console.WriteLine("ok");
            Console.ReadKey();
        }

  最後,就出現了文章最開始的效果圖。

 

轉載於:https://down.itsvse.com/k/0tmhog.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 array,顧名思義,數組,就是存儲數字、處理數字的一種數據結構。今天在將list轉換為array時,遇到了一個問題,數據量比較大,剛開始怎麼都不知道問題出在哪裡。直到我用一個3 3的小數據測試時,才發現問題的本質所在。浪費了半天的時間,不過總算搞明白了。 學的不夠踏實,以此警戒所有的初學者: ...
  • Python 3最重要的新特性之一是對字元串和二進位數據流做了明確的區分。文本總是Unicode,由str類型表示,二進位數據則由bytes類型表示。Python 3不會以任意隱式的方式混用str和bytes,你不能拼接字元串和位元組流,也無法在位元組流里搜索字元串(反之亦然),也不能將字元串傳入參數為 ...
  • Python編寫類的時候,每個函數參數第一個參數都是self,一開始我不管它到底是幹嘛的,只知道必須要寫上。後來對Python漸漸熟悉了一點,再回頭看self的概念,似乎有點弄明白了。 首先明確的是self只有在類的方法中才會有,獨立的函數或方法是不必帶有self的。self在定義類的方法時是必須有 ...
  • php中有很多排序的函數,sort,rsort,ksort,krsort,asort,arsort,natcasesort,這些函數用來對數組的鍵或值進行這樣,或那樣的排序。 可以終究有時候還需要一些函數來隨機獲取數組的元素。 array_rand()函數 隨機獲取數組中的一個函數,可以通過第二個參 ...
  • 前言 最近在做智能家居平臺,考慮到家居的控制需要快速的響應於是打算使用redis緩存。一方面減少資料庫壓力另一方面又能提高響應速度。項目中使用的技術棧基本上都是大家熟悉的springboot全家桶,在springboot2.x以後操作redis的客戶端推薦使用lettuce(生菜)取代jedis。 ...
  • 2019年11月8日,近期做項目開始實行前後端分離的方式開發,前端使用vue的框架,打包發佈後,調用後端介面出現跨域的問題,網上搜索出來的都是以下的配置方式: 但是,在我的項目中,按這種方式配置沒有效果,還會出現跨域的問題,後來發現是前後端請求設置的在Headers裡面傳輸token來進行校驗,那麼 ...
  • 網上看到很多人說 NPOI 的性能不行,自己寫了一個 NPOI 的擴展庫,於是想嘗試看看 NPOI 的性能究竟怎麼樣,道聽途說始終不如自己動手一試。 ...
  • 1. 沒有在Program里配置IIS webBuilder.UseIIS(); 2. StartupProduction 里AutoFac容器註入錯誤和新版的CORS中間件已經阻止使用允許任意Origin,即 AllowAnyOrgin設置了也不會生效 3. 可以嘗試下 在網站根目錄dotnet ...
一周排行
    -Advertisement-
    Play Games
  • 前言 在我們開發過程中基本上不可或缺的用到一些敏感機密數據,比如SQL伺服器的連接串或者是OAuth2的Secret等,這些敏感數據在代碼中是不太安全的,我們不應該在源代碼中存儲密碼和其他的敏感數據,一種推薦的方式是通過Asp.Net Core的機密管理器。 機密管理器 在 ASP.NET Core ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 順序棧的介面程式 目錄順序棧的介面程式頭文件創建順序棧入棧出棧利用棧將10進位轉16進位數驗證 頭文件 #include <stdio.h> #include <stdbool.h> #include <stdlib.h> 創建順序棧 // 指的是順序棧中的元素的數據類型,用戶可以根據需要進行修改 ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • C總結與剖析:關鍵字篇 -- <<C語言深度解剖>> 目錄C總結與剖析:關鍵字篇 -- <<C語言深度解剖>>程式的本質:二進位文件變數1.變數:記憶體上的某個位置開闢的空間2.變數的初始化3.為什麼要有變數4.局部變數與全局變數5.變數的大小由類型決定6.任何一個變數,記憶體賦值都是從低地址開始往高地 ...
  • 如果讓你來做一個有狀態流式應用的故障恢復,你會如何來做呢? 單機和多機會遇到什麼不同的問題? Flink Checkpoint 是做什麼用的?原理是什麼? ...
  • C++ 多級繼承 多級繼承是一種面向對象編程(OOP)特性,允許一個類從多個基類繼承屬性和方法。它使代碼更易於組織和維護,並促進代碼重用。 多級繼承的語法 在 C++ 中,使用 : 符號來指定繼承關係。多級繼承的語法如下: class DerivedClass : public BaseClass1 ...
  • 前言 什麼是SpringCloud? Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的開發便利性簡化了分散式系統的開發,比如服務註冊、服務發現、網關、路由、鏈路追蹤等。Spring Cloud 並不是重覆造輪子,而是將市面上開發得比較好的模塊集成進去,進行封裝,從 ...
  • class_template 類模板和函數模板的定義和使用類似,我們已經進行了介紹。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同。類模板用於實現類所需數據的類型參數化 template<class NameType, class AgeType> class Person { publi ...
  • 目錄system v IPC簡介共用記憶體需要用到的函數介面shmget函數--獲取對象IDshmat函數--獲得映射空間shmctl函數--釋放資源共用記憶體實現思路註意 system v IPC簡介 消息隊列、共用記憶體和信號量統稱為system v IPC(進程間通信機制),V是羅馬數字5,是UNI ...