深入解析C#中的第三方庫NPOI:Excel和Word檔案處理的利器

承蒙_关照發表於2024-03-18

一、引言
在.NET開發中,操作Office文件(特別是Excel和Word)是一項常見的需求。然而,在伺服器端或無Microsoft Office環境的場景下,直接使用Office Interop可能會面臨挑戰。為了解決這個問題,開源庫NPOI應運而生,它提供了無需安裝Office即可建立、讀取和修改Excel (.xls, .xlsx) 和 Word (.doc) 檔案的能力。
二、NPOI簡介
NPOI是一個基於.NET的API,用於讀寫微軟的OLE 2 Compound Document formats,如Microsoft Office Excel和Word。它是Apache POI專案的.NET移植版本,允許開發者在沒有安裝Office的情況下處理這些格式的檔案。
三、主要元件與方法
1. 安裝與引用
Install-Package NPOI
或者在Visual Studio中右鍵專案 -> 管理NuGet程式包 -> 搜尋並安裝NPOI。
2. 引用名稱空間

using NPOI.SS.UserModel; // Excel相關的介面和類
using NPOI.XSSF.UserModel; // 處理.xlsx檔案
using NPOI.HSSF.UserModel; // 處理.xls檔案
using System.IO; // 檔案操作

3. 建立/開啟工作簿

  • 建立一個新的Excel工作簿(.xlsx):
    var workbook = new XSSFWorkbook();
  • 開啟一個現有的Excel檔案(.xlsx或.xls):
FileStream file = new FileStream("path_to_your_file.xlsx", FileMode.Open, FileAccess.Read);
var workbook = new XSSFWorkbook(file); // .xlsx格式
var workbook = new HSSFWorkbook(file); // .xls格式

4. 建立/獲取工作表

  • 建立新的工作表:
    ISheet sheet = workbook.CreateSheet("Sheet1");
  • 獲取已存在的工作表:
    ISheet sheet = workbook.GetSheetAt(0); // 獲取索引為0的工作表
    5. 寫入單元格資料
  • 建立行與單元格:
IRow row = sheet.CreateRow(rowIndex);
ICell cell = row.CreateCell(columnIndex);
  • 設定單元格值:
cell.SetCellValue("文字內容"); // 文字
cell.SetCellValue(12345); // 數字

6. 合併單元格

var region = new CellRangeAddress(startRow, endRow, startColumn, endColumn);
sheet.AddMergedRegion(region);

7. 設定單元格樣式

  • 建立樣式物件:
    var style = workbook.CreateCellStyle();
  • 設定樣式屬性(如字型、顏色、對齊方式等):
style.Alignment = HorizontalAlignment.Center;
IFont font = workbook.CreateFont();
font.Boldweight = (short)FontBoldWeight.Bold;
style.SetFont(font);
  • 應用到單元格:
    cell.CellStyle = style;
    8. 儲存檔案
FileStream outputStream = new FileStream("output.xlsx", FileMode.Create);
workbook.Write(outputStream);
outputStream.Close();

9. 關閉資源

  • 確保關閉Workbook以及相關的檔案流以釋放資源:
workbook.Close();
file.Close();

四、高階功能

  • 讀取現有檔案:透過FileStream開啟並讀取Excel檔案內容。

  • 讀取公式結果:透過ICell.CachedFormulaResultType或ICell.CellFormula屬性獲取公式計算結果。

  • 操作圖表和圖片:NPOI支援插入、更新和刪除Excel中的圖表和圖片。

  • 處理Word文件:透過XWPFDocument類來建立、讀取和修改Word(.doc)檔案。

五、總結

NPOI庫憑藉其強大的功能和輕量級設計,已成為.NET環境下處理Office文件的標準工具之一。無論是在Web應用程式後臺處理使用者上傳的Excel檔案,還是在批處理任務中生成報表,NPOI都能提供高效且易於使用的解決方案。透過深入理解和熟練運用NPOI的各種方法,開發者可以輕鬆應對各種複雜的文件處理任務。

六、完整的讀取資料例子

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using System.IO;
  public void ReadExcelFile(string filePath)
    {
        // 建立一個FileStream物件來開啟Excel檔案
        using (FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            // 根據副檔名選擇合適的Workbook實現
            IWorkbook workbook;
            if (Path.GetExtension(filePath).ToLower() == ".xlsx")
            {
                workbook = new XSSFWorkbook(file);
            }
            else
            {
                workbook = new HSSFWorkbook(file); // 適用於.xls檔案
            }

            // 獲取第一個工作表(索引從0開始)
            ISheet sheet = workbook.GetSheetAt(0);

            // 遍歷所有行
            for (int rowIndex = 0; rowIndex <= sheet.LastRowNum; rowIndex++)
            {
                IRow row = sheet.GetRow(rowIndex);

                // 如果當前行不為空,則遍歷所有單元格
                if (row != null)
                {
                    for (int cellIndex = 0; cellIndex < row.LastCellNum; cellIndex++)
                    {
                        ICell cell = row.GetCell(cellIndex);

                        // 檢查單元格是否存在並獲取其資料型別和值
                        if (cell != null)
                        {
                            switch (cell.CellType)
                            {
                                case CellType.Numeric:
                                    double numericValue = cell.NumericCellValue;
                                    Console.WriteLine($"第{rowIndex + 1}行,第{cellIndex + 1}列:{numericValue}");
                                    break;
                                case CellType.String:
                                    string stringValue = cell.StringCellValue;
                                    Console.WriteLine($"第{rowIndex + 1}行,第{cellIndex + 1}列:{stringValue}");
                                    break;
                                case CellType.Formula:
                                    // 如果需要顯示公式計算結果,使用CachedFormulaResultType
                                    if (cell.CachedFormulaResultType == CellType.Numeric)
                                    {
                                        double formulaValue = cell.NumericCellValue;
                                        Console.WriteLine($"第{rowIndex + 1}行,第{cellIndex + 1}列(公式結果):{formulaValue}");
                                    }
                                    else if (cell.CachedFormulaResultType == CellType.String)
                                    {
                                        string formulaValue = cell.StringCellValue;
                                        Console.WriteLine($"第{rowIndex + 1}行,第{cellIndex + 1}列(公式結果):{formulaValue}");
                                    }
                                    // 其他型別的公式處理...
                                    break;
                                default:
                                    // 對於日期、布林值等其他型別,做相應處理
                                    break;
                            }
                        }
                        else
                        {
                            Console.WriteLine($"第{rowIndex + 1}行,第{cellIndex + 1}列:空單元格");
                        }
                    }
                }
            }

            // 關閉workbook以釋放資源
            workbook.Close();
        }
    }

在這個例子中,我們首先開啟了指定路徑下的Excel檔案,並根據檔案型別建立了相應的HSSFWorkbook或XSSFWorkbook物件。然後,我們迴圈遍歷每一行和每一列,獲取每個單元格的內容,並根據單元格型別輸出對應的值。

請確保已安裝NPOI NuGet包並在專案中引用了必要的名稱空間。

七、儲存資料例子

using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using System.IO;
 public void SaveDataToExcel(string filePath)
    {
        // 建立一個新的HSSFWorkbook(適用於.xls格式)或XSSFWorkbook(適用於.xlsx格式)
        IWorkbook workbook = new XSSFWorkbook(); // 使用.xlsx格式

        // 建立新的工作表並設定名稱
        ISheet sheet = workbook.CreateSheet("Sheet1");

        // 建立第一行資料
        IRow headerRow = sheet.CreateRow(0);
        headerRow.CreateCell(0).SetCellValue("Name");
        headerRow.CreateCell(1).SetCellValue("Age");
        headerRow.CreateCell(2).SetCellValue("City");

        // 新增三行資料
        for (int i = 1; i <= 3; i++)
        {
            IRow dataRow = sheet.CreateRow(i);

            dataRow.CreateCell(0).SetCellValue($"Person {i}");
            dataRow.CreateCell(1).SetCellValue(i * 10); // 年齡假設為i*10
            dataRow.CreateCell(2).SetCellValue($"City{i}");

            // 設定單元格樣式(可選,例如設定字型加粗和居中)
            ICellStyle style = workbook.CreateCellStyle();
            style.Alignment = HorizontalAlignment.Center;
            IFont font = workbook.CreateFont();
            font.Boldweight = (short)FontBoldWeight.Bold;
            style.SetFont(font);
            dataRow.Cells[0].CellStyle = style;
        }

        // 儲存到檔案
        using (FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
        {
            workbook.Write(fileStream);
        }

        // 關閉workbook以釋放資源
        workbook.Close();
    }

在這個例子中,我們首先建立了一個新的XSSFWorkbook物件,並在其中建立了一個名為"Sheet1"的工作表。接著,我們在表頭新增了列名,並插入了三行示例資料。為了演示單元格樣式的設定,我們將第一列的資料設定為了加粗和居中的樣式。最後,將整個工作簿內容寫入指定路徑的Excel檔案。

請注意,根據實際需求選擇建立HSSFWorkbook或XSSFWorkbook,以及調整儲存的資料和樣式。確保已安裝NPOI NuGet包並在專案中引用了必要的名稱空間。

相關文章