1. 程式人生 > >C#專案中操作Excel檔案——使用NPOI庫

C#專案中操作Excel檔案——使用NPOI庫

實際C#專案中經常會涉及到需要對本地Excel檔案進行操作,特別是一些包含資料記錄、分析、彙總功能模組的專案。常用的操作Excel檔案的方法主要有三個:

1. OleDb:

這種方式是把整個Excel檔案當做一個數據源來進行資料的讀取操作。

優點:實現方式簡單,讀取速度快;

缺點:讀取Excel資料的過程不太靈活,對記憶體的佔用比較高,當資料量變的很大時,容易由於記憶體空間不足導致記憶體溢位異常。(不過貌似對於今天電腦的硬體配置來說,記憶體問題不大)

2. Com元件

這種方式是通過Com元件 Microsoft.Office.Interop.Excel.dll實現Excel檔案的操作。

優點:讀取Excel資料非常靈活,可以實現Excel具有的各種資料處理功能;

缺點:對資料的訪問時基於單元格方式實現的,所以讀寫資料較慢,特別是當資料量較大時,訪問效率問題更為突出。另一點是要求本機安裝了Microsoft Office元件。

3. NPOI

這種方式是通過NPOI庫實現Excel檔案操作,可以在沒有安裝微軟Office的情況下使用。

優點:讀取Excel資料速度較快,操作方式靈活;

缺點:試了再說!

NPOI支援的檔案格式處理xls、xlsx外,還包括doc、ppt、vsd等,功能強大,人稱Excel一哥。本文就準備單獨談一談NPOI對Excel的基本操作。

NPOI是什麼?

NPOI的log圖示如下:

NPOI中N指代的是.Net,POI是一個完全開源的Java寫成的庫,能夠在沒有安裝微軟Office或者相應環境的情況下讀寫Excel、Word等微軟OLE2元件文件,幾乎支援所有的Office97~Office2007的檔案格式。所以NPOI就是POI專案的.Net版本。目前NPOI的最新版本是今年5月份釋出的V2.2.1,包含了.Net Framework2和.Net Framework4兩個版本。

各個版本.Net Framework對應資訊如下:

可以在C盤——C:\Windows\Microsoft.NET\Framework 下檢視本機已經安裝的.Net Framework版本,在我的機器上安裝了以下版本:

NPOI庫下載、解壓

NPOI官網下載地址:點選開啟連結,(如不能下載,可以試試csdn下載上的這個連結: NPOI v2.2.1 ) 開啟之後,點選紅色框裡的“NPOI 2.2.1 package”即可下載:

下載完成的壓縮包大小隻有3.5MB,解壓後可以看到主要檔案其實就是5個Dll檔案(.Net 2.0和.Net 4.0):

使用的時候只要在自己的C#專案中新增這幾個動態庫檔案的引用就可以了。

在C#工程中新增NPOI動態庫引用

新建Visual Studio C# 控制檯應用程式(或Windows窗體應用程式、WPF應用程式等均可),在解決方案管理器裡專案下的“引用”上右擊“新增引用”:

在彈出的“引用管理器”對話方塊中單擊“瀏覽(B)”,選擇NPOI所在的資料夾,根據機器上.Net Framework版本,選擇Net20或Net40下的動態庫。

新增完成之後展開專案下的“引用”項,可以看到剛才所新增的動態庫。

經過簡單的“新增引用”之後就可以在自己的程式碼中使用NPOI提供的介面實現各種Excel操作了。

Excel工作簿、工作表、xls、xlsx概念

在用NPOI編碼之前,簡單明確一下Excel中工作簿、工作表、xls、xlsx的概念,行、列、單元格等很明瞭的概念就不囉嗦了。

1. 每一個Excel檔案都可以看做是一個工作簿,當開啟一個Excel檔案時,就等於打開了一個Excel工作簿。

2. 當打開了excel工作簿後在視窗底部看到的“Sheet”標籤標示的是工作表,有幾個標籤就表示有幾個工作表。

    簡單做一個類比,一個Excel檔案即一個工作簿可以看做一本書,一個工作表即一個Sheet頁面是書內的一頁,可以     有很多頁。Excel2003最多可以新增255(有強迫症的程式猿最愛的數字之一)個,Excel2007隨意加。

3. xls是Office 2003以及之前版本Excel的副檔名,xlsx是Office 2007及之後版本Excel所用的副檔名。xlsx用新的基於     XML的壓縮檔案格式取代了之前的預設檔案格式,在傳統的檔名後面添加了字面x(即.docx取代.doc、.xlsx取         代.xls,等等),使其佔用的空間更小。xlsx向下相容xls。

新建一個Excel工作表

除新增Dll檔案的引用外,還需要新增名稱空間:

using NPOI.SS.UserModel;
using NPOI.HSSF.UserModel;
using NPOI.XSSF.UserModel;

HSSF使用於2007之前的xls版本,XSSF適用於2007及其之後的xlsx版本。

以下程式新建一個Excel 2003 xls和一個2007 xlsx檔案,跟用Office建立的標準Excel格式一樣,每一個Excel檔案初始包含了3個工作表。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NPOI.SS.UserModel;
using NPOI.HSSF.UserModel;
using NPOI.XSSF.UserModel;
using System.IO;

namespace Excel_NPOI
{
    class Program
    {
        static void Main(string[] args)
        {
            HSSFWorkbook workbook2003 = new HSSFWorkbook(); //新建xls工作簿
            workbook2003.CreateSheet("Sheet1");  //新建3個Sheet工作表
            workbook2003.CreateSheet("Sheet2");
            workbook2003.CreateSheet("Sheet3");
            FileStream file2003 = new FileStream(@"E:\Excel2003.xls", FileMode.Create);
            workbook2003.Write(file2003);
            file2003.Close();  //關閉檔案流
            workbook2003.Close();

            XSSFWorkbook workbook2007 = new XSSFWorkbook();  //新建xlsx工作簿
            workbook2007.CreateSheet("Sheet1");
            workbook2007.CreateSheet("Sheet2");
            workbook2007.CreateSheet("Sheet3");
            FileStream file2007 = new FileStream(@"E:\Excel2007.xlsx", FileMode.Create);
            workbook2007.Write(file2007);
            file2007.Close();
            workbook2007.Close();
        }
    }
}

執行之後會在E盤根目錄下生成Excel2003.xls和Excel2007.xlsx兩個檔案。

寫入Excel檔案資料

以xls檔案為例,介紹把資料寫入Excel檔案的方法。

寫資料要遵循一定的順序,可以概括為:讀取(或新建一個工作簿)->獲取工作表->對工作表新增行->對每一行新增單元格->對單元格賦值

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NPOI.SS.UserModel;
using NPOI.HSSF.UserModel;
using NPOI.XSSF.UserModel;
using System.IO;

namespace Excel_NPOI
{
    class Program
    {
        static void Main(string[] args)
        {
            HSSFWorkbook workbook2003 = new HSSFWorkbook(); //新建工作簿
            workbook2003.CreateSheet("Sheet1");  //新建1個Sheet工作表            
            HSSFSheet SheetOne = (HSSFSheet)workbook2003.GetSheet("Sheet1"); //獲取名稱為Sheet1的工作表
            //對工作表先新增行,下標從0開始
            for (int i = 0; i < 10; i++)
            {
                SheetOne.CreateRow(i);   //建立10行
            }
            //對每一行建立10個單元格
            HSSFRow SheetRow = (HSSFRow)SheetOne.GetRow(0);  //獲取Sheet1工作表的首行
            HSSFCell[] SheetCell = new HSSFCell[10];
            for (int i = 0; i < 10; i++)
            {
                SheetCell[i] = (HSSFCell)SheetRow.CreateCell(i);  //為第一行建立10個單元格
            }
            //建立之後就可以賦值了
            SheetCell[0].SetCellValue(true); //賦值為bool型         
            SheetCell[1].SetCellValue(0.000001); //賦值為浮點型
            SheetCell[2].SetCellValue("Excel2003"); //賦值為字串
            SheetCell[3].SetCellValue("123456789987654321");//賦值為長字串
            for (int i = 4; i < 10; i++)
            {
                SheetCell[i].SetCellValue(i);    //迴圈賦值為整形
            }
            FileStream file2003 = new FileStream(@"E:\Excel2003.xls", FileMode.Create);
            workbook2003.Write(file2003);
            file2003.Close();
            workbook2003.Close();            
        }
    }
}

執行之後在生成的Exce2003.xls中的內容為:

讀取Excel檔案資料

HSSFWorkbook類和XSSFWorkbook類都繼承自IWorkbook類,所以在不知道所要讀取的Excel檔案時xls還是xlsx時,可以使用IWorkbook來宣告一個通用的工作簿變數,隨後根據傳入的檔名判斷是xls還是xlsx。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NPOI.SS.UserModel;
using NPOI.HSSF.UserModel;
using NPOI.XSSF.UserModel;
using System.IO;

namespace Excel_NPOI
{
    class Program
    {
        static void Main(string[] args)
        {
            IWorkbook workbook = null;  //新建IWorkbook物件
            string fileName = "E:\\Excel2003.xls";
            FileStream fileStream = new FileStream(@"E:\Excel2003.xls", FileMode.Open, FileAccess.Read);
            if (fileName.IndexOf(".xlsx") > 0) // 2007版本
            {
                workbook = new XSSFWorkbook(fileStream);  //xlsx資料讀入workbook
            }
            else if (fileName.IndexOf(".xls") > 0) // 2003版本
            {
                workbook = new HSSFWorkbook(fileStream);  //xls資料讀入workbook
            }
            ISheet sheet = workbook.GetSheetAt(0);  //獲取第一個工作表
            IRow row;// = sheet.GetRow(0);            //新建當前工作表行資料
            for (int i = 0; i < sheet.LastRowNum; i++)  //對工作表每一行
            {
                row = sheet.GetRow(i);   //row讀入第i行資料
                if (row != null)
                {
                    for (int j = 0; j < row.LastCellNum; j++)  //對工作表每一列
                    {
                        string cellValue = row.GetCell(j).ToString(); //獲取i行j列資料
                        Console.WriteLine(cellValue);
                    }
                }
            }
            Console.ReadLine();
            fileStream.Close();
            workbook.Close();
        }
    }
}

這段程式碼實現讀取一個Excel檔案內第一個工作表中的所有單元格內容,並列印輸出。

取在上段程式碼中生成的xml檔案作為輸入,執行結果為: