跳至页脚内容
使用 IRONXL

如何在未安装 Excel 的情况下使用 C# 读取 OpenOffice Excel 文件

使用正确的库,在 C# 中读取和处理 OpenDocument Spreadsheet (光学数据系统) 和 Excel 文件非常简单。 使用IronXL ,您可以通过一次方法调用将任何 XLS、XLSX、光学数据系统 或 CSV 文件加载到 WorkBook 对象中——无需安装 Microsoft Excel,无需 COM 注册,也无需 Interop 方面的烦恼。 本指南将引导您完成每个步骤:安装软件包、加载文件、提取键入的单元格值、使用命名工作表、处理合并单元格以及部署到 Linux 或容器化环境。

如何在.NET项目中安装IronXL ?

NuGet包管理器安装

通过NuGet包管理器将IronXL添加到您的项目中。 在 Visual Studio 中打开软件包管理器控制台并运行:

Install-Package IronXL
dotnet add package IronXL
Install-Package IronXL
dotnet add package IronXL
SHELL

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 方法以相同的方式处理 光学数据系统、XLS、XLSX 和 CSV 文件。 你可以传递绝对或相对文件路径,库会从文件头(而不仅仅是扩展名)检测文件格式。 这意味着将文件从 .ods 重命名为 .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 上公开了一个 Rows 集合:

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

RowCountColumnCount 属性仅返回已填充的范围——不包括空的尾随行和列。 在读取之前检查 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 字符串 空字符串 始终安全;可将任何单元格转换为文本
IntValue int 0 截断小数
DecimalValue decimal 0m 保持财务数据的精确性
DoubleValue double 0.0 用于科学或统计值
BoolValue 布尔 false 读取 Excel 中的 TRUE/FALSE 单元格
DateTimeValue DateTime? null 可空——使用前请检查

如何处理多个已命名的工作表?

按名称、索引或迭代访问

Enterprise电子表格通常包含多个命名工作表——例如,每月一个工作表、每个地区一个IronXL表或每个产品线一个工作表。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", file翻译格式: ExcelFile翻译格式.TSV) 显式指定格式。

IronXL支持的输入文件格式
翻译格式 扩展 出品方 注意事项
XLSX .xlsx Excel 2007+、LibreOffice 默认现代格式;基于 XML
XLS .xls Excel 97-2003 二进制格式;完全读/写支持
光学数据系统 .ods LibreOffice、OpenOffice OpenDocument电子表格标准
CSV .csv 任何申请 分隔符自动检测;无格式化
TSV .tsv 数据库导出 制表符分隔;明确指定格式

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

Interop、Open XML SDK 和IronXL并排使用

在.NET中, IronXL最常见的 Excel 自动化替代方案是Microsoft.Office.Interop.Excel 。 了解各种利弊有助于您为项目选择合适的工具。

Microsoft Interop 对 Excel COM 对象模型进行了封装。 这意味着必须在运行代码的每台机器上安装 Excel,包括 Web 服务器、构建代理和云虚拟机。 COM 对象生命周期管理是手动的:您必须显式释放每个 RangeWorksheetWorkbook 对象,否则 Excel 进程会在后台累积并消耗内存,直到服务器重新启动。 许可也是一个需要考虑的问题:Office EULA 在许多情况下禁止服务器端自动化。

IronXL避免了所有这些限制。 这是一个纯粹的托管库,不依赖于 COM。 WorkBook 对象是一个标准的 .NET 类; 垃圾回收器负责清理工作。你可以在开发人员的笔记本电脑、Azure 应用服务、Docker 容器或运行 Linux 的 Raspberry Pi 上运行相同的代码。

微软的Open XML SDK是另一种选择。它无需 Excel 即可直接访问 OOXML 文件格式,但它的操作层级非常低——您需要直接操作 XML 元素。 读取单个单元格值需要遍历共享字符串表、单元格引用和样式索引。 IronXL 将所有这些封装到本指南中所示的单行 sheet["A1"].StringValue 调用中。

如何在 Linux 和 Docker 上部署 Excel Processing?

在服务器部署中,IronXL 独立于 Excel 的优势体现得最为明显。 在 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 实例而无需协调。 如果您需要并行处理数千个文件(例如,在后台作业中处理用户上传的电子表格),则可以在 Parallel.ForEachTask.WhenAll 实例池中使用 WorkBook 实例,而不会有损坏的风险。

由于IronXL在初始化时只将请求的工作表加载到内存中,而不是将整个工作簿加载到内存中,因此内存使用情况保持可预测性。 对于非常大的文件,这种区别很重要:一个包含十个 50MB 工作表的簿子并不需要 500MB 的 RAM 来读取单个工作表。 IronXL性能文档涵盖了处理大容量文件处理场景的其他策略。

下一步计划是什么?

在项目中验证IronXL 的最快方法是安装NuGet包,然后针对环境中的真实文件运行本指南中的示例。 免费试用许可证可解锁所有功能,无需更改代码即可在准备投入生产时使用。

探索IronXL 的其他相关功能,这些功能可以补充文件读取功能:

使用 C# 编写和创建 Excel 文件——以编程方式构建报表和数据导出 -设置单元格、行和列的格式——通过代码应用颜色、字体和边框。 -使用 C# 处理 Excel 公式——读取和写入公式单元格 -在.NET中将 Excel 转换为 PDF -- 从电子表格数据生成 PDF 报告 IronXL API 文档——所有类和方法的完整参考 IronXL 的许可和定价——面向个人开发者和Enterprise团队的选项 IronXL NuGet页面-- 所有项目类型的安装说明

对于许可、跨平台支持或特定文件格式要求方面的问题, IronXL支持团队可通过在线聊天和电子邮件提供帮助。

立即开始使用 IronXL。
green arrow pointer

常见问题解答

如何在未安装Excel的情况下,用C#读取OpenOffice Excel文件?

您可以使用IronXL库在 C# 中读取 OpenOffice Excel 文件,而无需在服务器上安装 Excel。它允许您使用单个 WorkBook.Load 方法调用高效地加载 XLS、XLSX、ODS 和 CSV 文件。

IronXL可以处理哪些类型的Excel文件?

IronXL支持处理各种 Excel 文件格式,包括 XLS、XLSX、ODS(OpenDocument Spreadsheet)和 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,这简化了部署并降低了维护需求。IronXLIronXL在 Windows、Linux、macOS 以及 Docker 容器中运行。

IronXL是否支持处理CSV文件?

是的, IronXL完全支持使用相同的 WorkBook.Load API 读取和处理 CSV 文件以及其他 Excel 格式(如 XLS、XLSX 和 ODS)。

对于.NET开发人员来说,使用IronXL有哪些好处?

IronXL为.NET开发人员提供了一个易于使用的库,用于读取、写入和操作 Excel 文件,而无需 Microsoft Excel,通过简洁、强类型的 API 提高生产力并缩短开发时间。

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

IronXL通过消除对 Excel 软件的需求来提高效率,提供类型化的单元格值访问器、线程安全的并发处理以及直接在.NET应用程序中处理 Excel 文件的轻量级解决方案。

Curtis Chau
技术作家

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。

除了开发之外,Curtis 对物联网 (IoT) 有浓厚的兴趣,探索将硬件和软件集成的新方法。在空闲时间,他喜欢玩游戏和构建 Discord 机器人,将他对技术的热爱与创造力相结合。

钢铁支援团队

我们每周 5 天,每天 24 小时在线。
聊天
电子邮件
打电话给我