跳至頁尾內容
USING IRONXL

如何在未安裝 Excel 的情況下使用 C# 讀取 OpenOffice Excel 文件

在C#中讀取和處理OpenDocument Spreadsheet (ODS)和Excel檔案相當簡單,只要您使用正確的程式庫。 使用 IronXL,您可以將任何XLS、XLSX、ODS或CSV檔案載入到WorkBook物件中,只需調用一個方法——不需要安裝Microsoft Excel,不需要COM註冊,也不會有Interop相關問題。 本指南將引導您完成每個步驟:安裝套件、載入檔案、提取有型別的儲存格值、處理命名的工作表、處理合併儲存格,以及部署到Linux或容器化環境。

如何在.NET專案中安裝IronXL?

NuGet套件管理器安裝

通過NuGet套件管理器將IronXL新增到您的專案中。 在Visual Studio中打開Package Manager Console並運行:

Install-Package IronXL.Excel

IronXL針對.NET 8、.NET 9、.NET 10、.NET Framework 4.6.2+和.NET Standard 2.0,因此不論是現代或是舊版程式碼基礎都可以適用。安裝套件後,請在任何處理電子錶格的檔案頂部新增using IronXL;指令,然後您即可準備載入您的第一本工作簿。

對於Azure Functions、Docker容器或Linux託管的API,不需要額外的運行時配置。 該程式庫內部綑綁了其所需的一切,不會調用Excel的自動化元件。

如何在C#中載入OpenOffice或Excel檔案?

IronXL透過WorkBook.Load方法對ODS、XLS、XLSX和CSV檔案進行相同處理。 您可以傳遞一個絕對或相對的文件路徑,然後程式庫會從文件頭檢測格式——而不只是檔案擴展名。 這意味著,即使檔案從.xlsx也能正確讀取。

using IronXL;

// Load an OpenDocument Spreadsheet (.ods) produced by LibreOffice Calc or OpenOffice
WorkBook workbook = WorkBook.Load("quarterly_report.ods");

// Access the first worksheet by index
WorkSheet sheet = workbook.WorkSheets[0];

// Read a cell value
string companyName = sheet["A1"].StringValue;
int recordCount   = sheet["B1"].IntValue;

Console.WriteLine($"Company : {companyName}");
Console.WriteLine($"Records : {recordCount}");
using IronXL;

// Load an OpenDocument Spreadsheet (.ods) produced by LibreOffice Calc or OpenOffice
WorkBook workbook = WorkBook.Load("quarterly_report.ods");

// Access the first worksheet by index
WorkSheet sheet = workbook.WorkSheets[0];

// Read a cell value
string companyName = sheet["A1"].StringValue;
int recordCount   = sheet["B1"].IntValue;

Console.WriteLine($"Company : {companyName}");
Console.WriteLine($"Records : {recordCount}");
Imports IronXL

' Load an OpenDocument Spreadsheet (.ods) produced by LibreOffice Calc or OpenOffice
Dim workbook As WorkBook = WorkBook.Load("quarterly_report.ods")

' Access the first worksheet by index
Dim sheet As WorkSheet = workbook.WorkSheets(0)

' Read a cell value
Dim companyName As String = sheet("A1").StringValue
Dim recordCount As Integer = sheet("B1").IntValue

Console.WriteLine($"Company : {companyName}")
Console.WriteLine($"Records : {recordCount}")
$vbLabelText   $csharpLabel

對於XLSX和XLS檔案也是一樣的調用,只需更改路徑。 WorkBook.Load不論來源格式如何,都會返回相同的強型別物件,因此無論檔案來自Microsoft Excel、LibreOffice還是任何其他ODF符合應用程式,您其餘的程式碼都能保持一樣。

您如何讀取工作表中的每一行和每一個儲存格?

遍歷行集合

遍歷所有行和儲存格是最常見的Excel處理任務——無論您是在驗證導入資料、轉換記錄,還是供報告管道使用。IronXL在每個WorkSheet集合:

using IronXL;

WorkBook workbook  = WorkBook.Load("customers.xlsx");
WorkSheet worksheet = workbook.WorkSheets[0];

Console.WriteLine($"Total rows    : {worksheet.RowCount}");
Console.WriteLine($"Total columns : {worksheet.ColumnCount}");
Console.WriteLine();

foreach (var row in worksheet.Rows)
{
    foreach (var cell in row)
    {
        if (!cell.IsEmpty)
            Console.Write($"{cell.StringValue,-20}");
    }
    Console.WriteLine();
}
using IronXL;

WorkBook workbook  = WorkBook.Load("customers.xlsx");
WorkSheet worksheet = workbook.WorkSheets[0];

Console.WriteLine($"Total rows    : {worksheet.RowCount}");
Console.WriteLine($"Total columns : {worksheet.ColumnCount}");
Console.WriteLine();

foreach (var row in worksheet.Rows)
{
    foreach (var cell in row)
    {
        if (!cell.IsEmpty)
            Console.Write($"{cell.StringValue,-20}");
    }
    Console.WriteLine();
}
Imports IronXL

Dim workbook As WorkBook = WorkBook.Load("customers.xlsx")
Dim worksheet As WorkSheet = workbook.WorkSheets(0)

Console.WriteLine($"Total rows    : {worksheet.RowCount}")
Console.WriteLine($"Total columns : {worksheet.ColumnCount}")
Console.WriteLine()

For Each row In worksheet.Rows
    For Each cell In row
        If Not cell.IsEmpty Then
            Console.Write($"{cell.StringValue,-20}")
        End If
    Next
    Console.WriteLine()
Next
$vbLabelText   $csharpLabel

ColumnCount屬性只返回已填充的範圍——不包括空的尾行和列。 在讀取前檢查cell.IsEmpty可阻止在稀疏表上的不必要處理。

對於大型檔案,考慮使用基於範圍的存取(worksheet["A1:D500"])而不是整張表迭代。 這限制了載入記憶體的儲存格並在您僅需資料子集時加速了處理。

您如何從儲存格中提取有型別的值?

型別屬性存取器

現實世界的電子錶格中的儲存格包含字串、整數、十進位數、布林值和日期。 IronXL公開了專用的型別屬性,因此您永遠不需要手動解析原始字串:

using IronXL;

WorkBook workbook = WorkBook.Load("inventory.xlsx");
WorkSheet sheet   = workbook.GetWorkSheet("Products");

// Typed accessors handle conversion automatically
string  productName = sheet["A2"].StringValue;
int     quantity    = sheet["B2"].IntValue;
decimal unitPrice   = sheet["C2"].DecimalValue;
bool    inStock     = sheet["D2"].BoolValue;
DateTime? lastAudit = sheet["E2"].DateTimeValue;

Console.WriteLine($"Product  : {productName}");
Console.WriteLine($"Qty      : {quantity}");
Console.WriteLine($"Price    : {unitPrice:C}");
Console.WriteLine($"In Stock : {inStock}");
Console.WriteLine($"Audited  : {lastAudit?.ToString("d") ?? "Never"}");
using IronXL;

WorkBook workbook = WorkBook.Load("inventory.xlsx");
WorkSheet sheet   = workbook.GetWorkSheet("Products");

// Typed accessors handle conversion automatically
string  productName = sheet["A2"].StringValue;
int     quantity    = sheet["B2"].IntValue;
decimal unitPrice   = sheet["C2"].DecimalValue;
bool    inStock     = sheet["D2"].BoolValue;
DateTime? lastAudit = sheet["E2"].DateTimeValue;

Console.WriteLine($"Product  : {productName}");
Console.WriteLine($"Qty      : {quantity}");
Console.WriteLine($"Price    : {unitPrice:C}");
Console.WriteLine($"In Stock : {inStock}");
Console.WriteLine($"Audited  : {lastAudit?.ToString("d") ?? "Never"}");
Imports IronXL

Dim workbook As WorkBook = WorkBook.Load("inventory.xlsx")
Dim sheet As WorkSheet = workbook.GetWorkSheet("Products")

' Typed accessors handle conversion automatically
Dim productName As String = sheet("A2").StringValue
Dim quantity As Integer = sheet("B2").IntValue
Dim unitPrice As Decimal = sheet("C2").DecimalValue
Dim inStock As Boolean = sheet("D2").BoolValue
Dim lastAudit As DateTime? = sheet("E2").DateTimeValue

Console.WriteLine($"Product  : {productName}")
Console.WriteLine($"Qty      : {quantity}")
Console.WriteLine($"Price    : {unitPrice:C}")
Console.WriteLine($"In Stock : {inStock}")
Console.WriteLine($"Audited  : {If(lastAudit?.ToString("d"), "Never")}")
$vbLabelText   $csharpLabel

當儲存格包含公式時,IronXL對其進行計算並通過相同的型別屬性返回計算結果。 您不需要調用單獨的計算方法。 對於可能是空值或包含不相容型別的儲存格,程式庫會返回該型別的預設值而不拋出異常,從而簡化了輸入驗證邏輯。

IronXL儲存格值屬性及其等效的.NET型別
屬性 .NET型別 空時返回 註釋
StringValue string 空字串 總是安全的;將任何儲存格轉換為文字
IntValue int 0 截斷十進位數
DecimalValue decimal 0m 保留財務資料的精度
DoubleValue double 0.0 用於科學或統計值
BoolValue bool false 讀取Excel中的TRUE/FALSE儲存格
DateTimeValue DateTime? null 可空——使用前檢查

如何處理多個命名的工作表?

按名稱、索引或迭代存取

企業電子錶格通常包含多個命名的頁籤——每個月一個、每個區域一個或每條產品線一個。IronXL提供多種方法來存取它們:

using IronXL;

WorkBook workbook = WorkBook.Load("annual_sales.xlsx");

// Option 1: access by name (throws if the sheet does not exist)
WorkSheet januarySheet = workbook.GetWorkSheet("January");

// Option 2: iterate all sheets in the workbook
foreach (WorkSheet ws in workbook.WorkSheets)
{
    Console.WriteLine($"Sheet: {ws.Name}  |  Rows: {ws.RowCount}");

    // Read the header row from each sheet
    string header = ws["A1"].StringValue;
    Console.WriteLine($"  Header: {header}");
}

// Option 3: access by zero-based index
WorkSheet lastSheet = workbook.WorkSheets[workbook.WorkSheets.Count - 1];
Console.WriteLine($"Last sheet: {lastSheet.Name}");
using IronXL;

WorkBook workbook = WorkBook.Load("annual_sales.xlsx");

// Option 1: access by name (throws if the sheet does not exist)
WorkSheet januarySheet = workbook.GetWorkSheet("January");

// Option 2: iterate all sheets in the workbook
foreach (WorkSheet ws in workbook.WorkSheets)
{
    Console.WriteLine($"Sheet: {ws.Name}  |  Rows: {ws.RowCount}");

    // Read the header row from each sheet
    string header = ws["A1"].StringValue;
    Console.WriteLine($"  Header: {header}");
}

// Option 3: access by zero-based index
WorkSheet lastSheet = workbook.WorkSheets[workbook.WorkSheets.Count - 1];
Console.WriteLine($"Last sheet: {lastSheet.Name}");
Imports IronXL

Dim workbook As WorkBook = WorkBook.Load("annual_sales.xlsx")

' Option 1: access by name (throws if the sheet does not exist)
Dim januarySheet As WorkSheet = workbook.GetWorkSheet("January")

' Option 2: iterate all sheets in the workbook
For Each ws As WorkSheet In workbook.WorkSheets
    Console.WriteLine($"Sheet: {ws.Name}  |  Rows: {ws.RowCount}")

    ' Read the header row from each sheet
    Dim header As String = ws("A1").StringValue
    Console.WriteLine($"  Header: {header}")
Next

' Option 3: access by zero-based index
Dim lastSheet As WorkSheet = workbook.WorkSheets(workbook.WorkSheets.Count - 1)
Console.WriteLine($"Last sheet: {lastSheet.Name}")
$vbLabelText   $csharpLabel

當頁籤名稱在設計時已知時,GetWorkSheet是最明確的選擇。 對於動態處理——頁籤名稱來自使用者輸入或配置時,迭代WorkSheets集合能防止硬編碼假設,並妥善處理頁籤數量不一的工作簿。

如何處理合併儲存格及格式化區域?

報告和儀表板通常使用合併儲存格來做標題、分組標籤和摘要行。 IronXL從合併區域的左上儲存格中讀取值,正如Excel顯示的那樣:

using IronXL;

WorkBook workbook = WorkBook.Load("report_with_merges.xlsx");
WorkSheet sheet   = workbook.DefaultWorkSheet;

// The merged region A1:D1 stores its value in cell A1
string reportTitle = sheet["A1"].StringValue;
Console.WriteLine($"Report title : {reportTitle}");

// Read cell formatting metadata
var titleCell = sheet["A1"];
Console.WriteLine($"Bold         : {titleCell.Style.Font.Bold}");
Console.WriteLine($"Font size    : {titleCell.Style.Font.Height}");

// Scan an entire column for non-empty section headers
foreach (var cell in sheet["A1:A100"])
{
    if (!cell.IsEmpty && cell.Style.Font.Bold)
        Console.WriteLine($"Section header at {cell.AddressString}: {cell.StringValue}");
}
using IronXL;

WorkBook workbook = WorkBook.Load("report_with_merges.xlsx");
WorkSheet sheet   = workbook.DefaultWorkSheet;

// The merged region A1:D1 stores its value in cell A1
string reportTitle = sheet["A1"].StringValue;
Console.WriteLine($"Report title : {reportTitle}");

// Read cell formatting metadata
var titleCell = sheet["A1"];
Console.WriteLine($"Bold         : {titleCell.Style.Font.Bold}");
Console.WriteLine($"Font size    : {titleCell.Style.Font.Height}");

// Scan an entire column for non-empty section headers
foreach (var cell in sheet["A1:A100"])
{
    if (!cell.IsEmpty && cell.Style.Font.Bold)
        Console.WriteLine($"Section header at {cell.AddressString}: {cell.StringValue}");
}
Imports IronXL

Dim workbook As WorkBook = WorkBook.Load("report_with_merges.xlsx")
Dim sheet As WorkSheet = workbook.DefaultWorkSheet

' The merged region A1:D1 stores its value in cell A1
Dim reportTitle As String = sheet("A1").StringValue
Console.WriteLine($"Report title : {reportTitle}")

' Read cell formatting metadata
Dim titleCell = sheet("A1")
Console.WriteLine($"Bold         : {titleCell.Style.Font.Bold}")
Console.WriteLine($"Font size    : {titleCell.Style.Font.Height}")

' Scan an entire column for non-empty section headers
For Each cell In sheet("A1:A100")
    If Not cell.IsEmpty AndAlso cell.Style.Font.Bold Then
        Console.WriteLine($"Section header at {cell.AddressString}: {cell.StringValue}")
    End If
Next
$vbLabelText   $csharpLabel

Style屬性樹反映出OOXML SpreadsheetML規範的結構,因此如果您曾使用Open XML SDK,屬性名稱會感覺熟悉。 然而,IronXL將所有的複雜性包裝在一個乾淨的API中,您不需要進行任何XML操作。

如何使用相同的API導入CSV檔案?

由資料庫匯出、CRM系統和舊版應用程式生成的CSV檔案可以利用相同的WorkBook.Load調用讀取。 IronXL從檔案內容中推斷分隔符:

using IronXL;

// Load a comma-separated values file -- same method, same API
WorkBook csvWorkbook  = WorkBook.Load("export.csv");
WorkSheet csvSheet    = csvWorkbook.DefaultWorkSheet;

Console.WriteLine($"CSV rows loaded: {csvSheet.RowCount}");

// Process rows exactly like any other worksheet
foreach (var row in csvSheet.Rows)
{
    string id   = row[0].StringValue;
    string name = row[1].StringValue;
    Console.WriteLine($"{id,-10} {name}");
}
using IronXL;

// Load a comma-separated values file -- same method, same API
WorkBook csvWorkbook  = WorkBook.Load("export.csv");
WorkSheet csvSheet    = csvWorkbook.DefaultWorkSheet;

Console.WriteLine($"CSV rows loaded: {csvSheet.RowCount}");

// Process rows exactly like any other worksheet
foreach (var row in csvSheet.Rows)
{
    string id   = row[0].StringValue;
    string name = row[1].StringValue;
    Console.WriteLine($"{id,-10} {name}");
}
Imports IronXL

' Load a comma-separated values file -- same method, same API
Dim csvWorkbook As WorkBook = WorkBook.Load("export.csv")
Dim csvSheet As WorkSheet = csvWorkbook.DefaultWorkSheet

Console.WriteLine($"CSV rows loaded: {csvSheet.RowCount}")

' Process rows exactly like any other worksheet
For Each row In csvSheet.Rows
    Dim id As String = row(0).StringValue
    Dim name As String = row(1).StringValue
    Console.WriteLine($"{id,-10} {name}")
Next
$vbLabelText   $csharpLabel

載入後,您可以使用csvWorkbook.SaveAs("output.xlsx")將資料保存為XLSX。 這是一種常見的CSV到Excel轉換管道模式——接收CSV檔案,使用計算欄或格式進行豐富化,並將格式化的XLSX報告返回給使用者。

對於製表符分隔文件或使用者自定義分隔符,請使用WorkBook.LoadCSV("file.tsv", fileFormat: ExcelFileFormat.TSV)明確指定格式。

IronXL支持的輸入文件格式
格式 擴展名 生成者 註釋
XLSX .xlsx Excel 2007+,LibreOffice 預設現代格式;基於XML
XLS .xls Excel 97--2003 二進位格式;完全讀寫支持
ODS .ods LibreOffice,OpenOffice OpenDocument Spreadsheet標準
CSV .csv 任何應用程式 分隔符自動檢測;沒有格式
TSV .tsv 資料庫匯出 製表符分隔;顯式指定格式

IronXL與Microsoft.Office.Interop.Excel相比如何?

Interop、Open XML SDK和IronXL並排比較

最常見的IronXL替代品是用於.NET的Microsoft.Office.Interop.Excel。 了解利弊有助於您為專案選擇合適的工具。

Microsoft Interop包裹了Excel COM物件模型。 這意味著Excel必須安裝在每臺運行您的程式碼的機器上——包括網頁伺服器、構建代理和雲端VM。 COM物件生命週期管理是手動的:您必須顯式地釋放每個Workbook物件,否則Excel進程會在背景中積累並消耗記憶體,直到伺服器重啟。 許可證也是一個考慮因素:Office終端使用者許可協議在許多情況下禁止伺服器端自動化。

IronXL避免了所有這些限制。 它是純管理程式庫,無需COM依賴。 WorkBook物件是標準.NET類; 垃圾收集器處理清理。您可以在開發者筆記本電腦、Azure App Service、Docker容器,或在運行Linux的樹莓派上運行相同的程式碼。

來自Microsoft的Open XML SDK是另一個選擇。它提供對OOXML文件格式的直接存取,而無需Excel,但它操作在非常低的層次上——您需直接操控XML元素。 讀取單個儲存格值需要導航共享字串表、儲存格引用和樣式索引。 IronXL將所有這些整合成本指南中所示的單行sheet["A1"].StringValue調用。

如何將Excel處理部署到Linux和Docker?

伺服器部署中IronXL的獨立性益顯得尤為有價值。 您在Windows上編寫的程式碼,無需更改即可在Ubuntu、Alpine Linux或macOS上運行。 對於容器化部署,您的Dockerfile不需要特殊配置:

# Standard .NET runtime image -- no Office packages needed
FROM mcr.microsoft.com/dotnet/runtime:10.0
WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "ExcelProcessor.dll"]
# Standard .NET runtime image -- no Office packages needed
FROM mcr.microsoft.com/dotnet/runtime:10.0
WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "ExcelProcessor.dll"]
SHELL

對於Azure Functions和AWS Lambda,IronXL在托管運行時中工作,而不需任何額外配置。 冷啟動開銷最小,因為沒有COM初始化步驟。

執行緒安全是內建的:多個執行緒可以同時打開不同的WorkBook實例,而無需協調。 如果您需要並行處理數千個文件——例如在背景工作中處理使用者上傳的電子錶格——您可以跨Task.WhenAll,而無需擔心損壞風險。

記憶體使用保持預測性,因為IronXL僅將請求的工作表載入記憶體,而不是在初始化時將整個工作簿載入。 對於非常大的檔案,這一區別尤為重要:一本有十個50MB的工作表的工作簿並不需要500MB的RAM來讀取單個工作表。 IronXL性能文件涵蓋了其他處理高容量文件處理場景的策略。

您接下來的步驟是什麼?

驗證IronXL在您的專案中最迅速的方法是安裝NuGet套件,並在您的環境中的真實檔案上運行本指南中的範例。 一份免費試用授權解鎖所有功能,當您準備進入生產階段時無需更改程式碼。

探索補充檔案讀取的相關IronXL功能:

關於授權、跨平台支持或特定檔案格式的要求問題,IronXL支持團隊可以通過即時聊天和電子郵件提供幫助。

現在開始使用IronXL。
green arrow pointer

常見問題

我如何在未安裝Excel的情況下在C#中讀取Open Office Excel文件?

您可以使用IronXL程式庫在不需要在伺服器上安裝Excel的情況下,在C#中讀取Open Office Excel文件。它允許您通過單一的WorkBook.Load方法調用來高效載入XLS、XLSX、ODS和CSV文件。

使用IronXL可以處理哪些型別的Excel文件?

IronXL支持處理各種Excel文件格式,包括XLS、XLSX、ODS(OpenDocument電子表格)和CSV文件,使其能應對不同電子表格應用程式的需求,包括LibreOffice和OpenOffice。

為何開發人員應該使用IronXL而非Microsoft Interop來讀取Excel文件?

IronXL提供了一種更簡單和更高效的Excel文件處理方式,不需要Microsoft Excel或COM Interop,從而減少了生產伺服器上的複雜性和開銷,並支持Linux和Docker部署。

IronXL可以處理在除MS Excel外的其他電子表格應用程式中建立的文件嗎?

是的,IronXL能夠讀取和處理來自其他電子表格應用程式的文件,例如OpenOffice Calc和LibreOffice Calc,這使其成為開發人員處理ODS和ODF相容格式時的靈活工具。

在生產伺服器上使用IronXL是否需要安裝Excel?

不需要,使用IronXL時,您無需在生產伺服器上安裝Excel,從而簡化了部署並減少了維護要求。 IronXL可在Windows、Linux、macOS及Docker容器內運行。

IronXL支持處理CSV文件嗎?

是的,IronXL完全支持閱讀和處理CSV文件,以及使用相同的WorkBook.Load API載入其他Excel格式如XLS、XLSX和ODS。

對於.NET開發人員來說,使用IronXL有哪些好處?

IronXL為.NET開發者提供了一個易於使用的程式庫,允許在不需要Microsoft Excel的情況下讀寫及操作Excel文件,提高了生產力並通過清晰、強型別的API縮短了開發時間。

IronXL如何提高處理Excel文件的效率?

IronXL通過消除Excel軟體的需求,提高了效率,提供了型別化的單元格值存取器、執行緒安全的並發處理,以及直接在.NET應用程式中處理Excel文件的輕量級解決方案。

Curtis Chau
技術作家

Curtis Chau擁有Carleton大學的電腦科學學士學位,專精於前端開發,擁有Node.js、TypeScript、JavaScript和React的專業知識。Curtis熱衷於建立直觀且美觀的使用者介面,喜愛使用現代框架並建立結構良好、視覺吸引力的手冊。

除了開發,Curtis對物聯網(IoT)有濃厚的興趣,探索創新的方法來整合硬體和軟體。在空閒時間,他喜歡玩遊戲和建立Discord機器人,結合他對技術的熱愛與創造力。

Iron 支援團隊

我們線上24小時,每週5天。
聊天
電子郵件
給我打電話