IRONSOFTWAREHOME
USING IRONXL

如何在不使用互操作的情况下,使用 C# 在 Excel 中创建数据透视表

Curtis Chau
Curtis Chau
Updated: 2026年6月28日

**使用 C# 在 Excel 中创建数据透视表非常简单,只需选择合适的库即可——Excel互操作性 需要每台机器上都安装 Office,而IronXL可以在任何运行.NET 的环境中运行。**本指南将通过完整的代码示例详细介绍这两种方法,涵盖设置、数据聚合、字段配置和部署注意事项,以便您根据项目需求做出正确的选择。

如何使用C# Interop和IronXL在Excel中创建数据透视表:图像1 - IronXL

Excel互操作性 和IronXL有什么区别?

在编写任何一行代码之前,了解每种方法的底层原理会很有帮助。 Excel互操作性 使用COM(组件对象模型)直接从 C# 驱动 Microsoft Excel。 .NET进程会与正在运行的 Excel 实例通信,这意味着计算机上必须安装 Excel。您操作的每个对象(工作簿、工作表、区域、透视缓存)都是 COM 包装器,必须显式释放每个包装器,以避免进程泄漏。

IronXL采取了一条截然不同的道路。 它直接读取和写入Open XML 文件格式,完全无需启动 Excel。 最终得到的是一个标准的.NET库,它具有熟悉的对象模式、垃圾回收内存,并且不依赖于 Office 安装或许可。 这种架构使得IronXL适用于服务器端工作负载、Docker 容器、Linux 主机以及任何.NET 6、 .NET 8 或.NET 10 环境。

Excel互操作性 与IronXL对比概览
标准Excel互操作性IronXL
办公室要求
仅限 Windows否——跨平台
内存管理手动 COM 版本自动(.NET GC)
服务器部署难的直截了当
原生透视表完整的 Excel 透视表 API通过 LINQ 进行数据聚合
需要许可证办公许可证IronXL仅限授权

如何使用C# Interop和IronXL在Excel中创建数据透视表:图像2 - 跨平台

如何安装各个库?

设置 Excel互操作性

Excel互操作性 以NuGet包的形式提供。 在您的项目中运行以下任一命令:

Install-Package Microsoft.Office.Interop.Excel
dotnet add package Microsoft.Office.Interop.Excel
SHELL

请注意,仅此软件包是不够的——目标计算机必须安装匹配版本的 Microsoft Excel 并已获得正确的许可。 这种依赖关系排除了大多数服务器、容器和云场景。

如何使用C# Interop和IronXL在Excel中创建数据透视表:图像3 - Excel互操作性安装

设置IronXL

通过NuGet安装IronXL ,无需其他系统要求:

PM > Install-Package IronXL.Excel

安装完成后,您可以在任何支持.NET 的平台上立即开始读取和写入 Excel 文件。 无需Office许可证,无需COM注册,无需服务器配置。 有关其他选项,包括离线安装和项目参考设置,请参阅IronXL安装指南

如何使用C# Interop和IronXL在Excel中创建数据透视表:图像4 - 安装

第一步:
arrow pointer

如何使用C#互操作创建Excel数据透视表?

Interop数据透视表工作流遵循严格的顺序:从源范围创建数据透视缓存,然后在单独的工作表上构建PivotTable对象,然后配置字段方向。 以下示例使用与.NET 10 兼容的顶级 C# 语句:

using Excel = Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;

// Launch Excel and set up workbooks
var excelApp = new Excel.Application();
excelApp.Visible = false;
var workbook = excelApp.Workbooks.Add();
var dataSheet = (Excel.Worksheet)workbook.Worksheets[1];
dataSheet.Name = "SalesData";
var pivotSheet = (Excel.Worksheet)workbook.Worksheets.Add();
pivotSheet.Name = "Pivot";

// Populate header row
dataSheet.Cells[1, 1] = "Product";
dataSheet.Cells[1, 2] = "Region";
dataSheet.Cells[1, 3] = "Sales";

// Add sample data rows
object[,] rows = {
    { "Laptop",   "North", 1200 },
    { "Laptop",   "South", 1500 },
    { "Phone",    "North",  800 },
    { "Phone",    "South",  950 },
    { "Tablet",   "East",   600 },
    { "Tablet",   "West",   750 },
    { "Monitor",  "North",  400 },
    { "Monitor",  "South",  500 },
    { "Keyboard", "East",   300 },
};
for (int i = 0; i < rows.GetLength(0); i++)
{
    dataSheet.Cells[i + 2, 1] = rows[i, 0];
    dataSheet.Cells[i + 2, 2] = rows[i, 1];
    dataSheet.Cells[i + 2, 3] = rows[i, 2];
}

// Build pivot cache from source range
Excel.Range dataRange = dataSheet.Range["A1:C10"];
Excel.PivotCache pivotCache = workbook.PivotCaches().Create(
    Excel.XlPivotTableSourceType.xlDatabase, dataRange);

// Create the PivotTable on the pivot sheet
Excel.PivotTables pivotTables = (Excel.PivotTables)pivotSheet.PivotTables();
Excel.PivotTable pivotTable = pivotTables.Add(
    pivotCache, pivotSheet.Range["A3"], "SalesPivot");

// Assign field orientations
((Excel.PivotField)pivotTable.PivotFields("Product")).Orientation =
    Excel.XlPivotFieldOrientation.xlRowField;
((Excel.PivotField)pivotTable.PivotFields("Region")).Orientation =
    Excel.XlPivotFieldOrientation.xlColumnField;
((Excel.PivotField)pivotTable.PivotFields("Sales")).Orientation =
    Excel.XlPivotFieldOrientation.xlDataField;

// Enable grand totals
pivotTable.RowGrand = true;
pivotTable.ColumnGrand = true;

// Save and close
workbook.SaveAs(@"C:\output\pivot_interop.xlsx");
workbook.Close(false);
excelApp.Quit();

// Release every COM object -- skipping any of these causes Excel to stay in memory
Marshal.ReleaseComObject(pivotTable);
Marshal.ReleaseComObject(pivotTables);
Marshal.ReleaseComObject(pivotCache);
Marshal.ReleaseComObject(dataRange);
Marshal.ReleaseComObject(pivotSheet);
Marshal.ReleaseComObject(dataSheet);
Marshal.ReleaseComObject(workbook);
Marshal.ReleaseComObject(excelApp);

每个COM封装器需要匹配的Marshal.ReleaseComObject调用。 即使缺少一个引用,也会导致 Excel 进程在后台持续运行,消耗内存和文件句柄,直到宿主进程结束。 清理工作量会随着电子表格操作的复杂程度而增加。

如何用IronXL达到同样的效果?

IronXL不像 Interop 那样公开原生透视表 API——Open XML 透视表格式有数百个 XML 属性,大多数业务需求可以通过用纯 C# 编写的显式 LINQ 聚合更可靠地满足。 输出结果是一个干净的汇总表,当文件打开时,该汇总表能够正确地重新计算,而无需依赖 Excel 刷新数据透视表缓存。

using IronXL;
using System.Data;

// Create workbook and populate source data
WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
WorkSheet dataSheet = workbook.CreateWorkSheet("SalesData");

dataSheet["A1"].Value = "Product";
dataSheet["B1"].Value = "Region";
dataSheet["C1"].Value = "Sales";

object[,] rows = {
    { "Laptop",   "North", 1200 },
    { "Laptop",   "South", 1500 },
    { "Phone",    "North",  800 },
    { "Phone",    "South",  950 },
    { "Tablet",   "East",   600 },
    { "Tablet",   "West",   750 },
    { "Monitor",  "North",  400 },
    { "Monitor",  "South",  500 },
    { "Keyboard", "East",   300 },
};
for (int i = 0; i < rows.GetLength(0); i++)
{
    dataSheet[$"A{i + 2}"].Value = rows[i, 0];
    dataSheet[$"B{i + 2}"].Value = rows[i, 1];
    dataSheet[$"C{i + 2}"].Value = rows[i, 2];
}

// Aggregate data with LINQ -- equivalent to a pivot table row/column/value layout
DataTable table = dataSheet["A1:C10"].ToDataTable(true);
var summary = table.AsEnumerable()
    .GroupBy(row => row.Field<string>("Product"))
    .Select((group, idx) => new
    {
        Product    = group.Key,
        TotalSales = group.Sum(r => Convert.ToDecimal(r["Sales"])),
        RegionCount = group.Select(r => r.Field<string>("Region")).Distinct().Count(),
        RowIndex   = idx + 2
    })
    .OrderByDescending(x => x.TotalSales);

// Write the summary sheet
WorkSheet summarySheet = workbook.CreateWorkSheet("Summary");
summarySheet["A1"].Value = "Product";
summarySheet["B1"].Value = "Total Sales";
summarySheet["C1"].Value = "Regions";

foreach (var item in summary)
{
    summarySheet[$"A{item.RowIndex}"].Value = item.Product;
    summarySheet[$"B{item.RowIndex}"].Value = (double)item.TotalSales;
    summarySheet[$"C{item.RowIndex}"].Value = item.RegionCount;
}

// Apply currency format to the sales column
summarySheet["B:B"].FormatString = "$#,##0.00";

// Bold the header row
summarySheet["A1:C1"].Style.Font.Bold = true;

// Save -- no COM cleanup needed
workbook.SaveAs(@"C:\output\analysis_ironxl.xlsx");

无需释放 COM 对象,无需终止 Excel 进程,也无需管理 Office 许可证。 同一段代码无需修改即可在 Linux、macOS 和 Windows 上编译运行。 有关聚合 API 的更多详细信息,请访问IronXL WorkSheet 文档

输出

如何使用C# Interop和IronXL在Excel中创建数据透视表:图像6 - IronXL输出

如何使用C# Interop和IronXL在Excel中创建数据透视表:图像7 - 摘要输出

部署和维护方面的主要区别是什么?

部署要求

部署基于互操作性的应用程序需要验证目标环境是否运行 Windows,是否安装了正确的 Office 版本,以及服务器上是否配置了 COM 自动化权限。 云托管环境和容器化工作负载通常无法在不添加虚拟化 Windows 桌面基础架构的情况下满足这些要求,但这会显著增加成本和操作复杂性。

IronXL没有这样的限制。 添加NuGet包,将目标框架设置为.NET 6 或更高版本,应用程序即可部署到任何主机,包括 Linux 容器、Linux 上的 Azure 应用服务、AWS Lambda 和本地 Windows 服务器。 IronXL系统要求页面列出了完整的兼容性矩阵。

错误处理和调试

Interop失败表现为COM异常(COMException),这些异常很难映射到用户可见的信息。 已安装的 Office 版本与 Interop 程序集之间的版本不匹配会导致另一种故障模式。 调试这些问题通常需要在开发机器上重现完全相同的 Office 版本。

IronXL抛出具有描述性信息的标准System.Exception子类。 您可以将文件操作封装在 try-catch 块中,并在不了解 COM 错误代码的情况下提供有意义的反馈。 IronXL故障排除指南涵盖了常见异常及其解决方法。

内存和性能

COM 对象持有非托管内存。 如果你的代码处理很多工作表或在循环中运行,未能正确释放每个引用会导致内存随着时间的推移而增长——这个问题很难被发现,直到它导致生产事故。 由于 Interop 只驱动一个 Excel 窗口,因此它本质上也是单线程的。

IronXL使用由.NET垃圾回收器支持的托管对象。 当对象超出作用域时,内存会自动回收。 并行处理多个工作簿非常简​​单,因为没有需要用锁来保护的共享 COM 状态。

如何选择这两种方法?

选择合适的工具取决于两个限制条件:代码运行的位置,以及是否需要原生透视表 XML。

在以下情况下选择Excel互操作性:

  • 该工作负载仅在已安装 Office 的 Windows 桌面计算机上运行。
  • 输出文件必须完全符合原始数据透视表格式(切片器、分组日期字段、计算项)。
  • 您维护着现有的互操作代码库,因此没有必要进行完全重写。

在以下情况下选择IronXL:

  • 该应用程序运行在服务器、容器或云函数上
  • 需要跨平台或Linux部署
  • 您需要的是一个可使用单元测试进行测试的数据聚合逻辑,而不是依赖于 Excel 流程的逻辑。
  • 您需要大规模或并行处理 Excel 文件。

对于大多数新的.NET 10 项目而言, IronXL是实际的默认选择。 IronXL库还涵盖在C#中读取Excel文件创建图表应用单元格样式公式操作将Excel数据导出到DataTable——减少了在您的堆栈中需要多库的需求。

如何使用C# Interop和IronXL在Excel中创建数据透视表:图像8 - 功能

IronXL还有哪些功能支持数据分析?

除了基本的聚合功能外, IronXL还提供了多种功能,支持更丰富的数据分析工作流程:

数据排序和筛选

在编写汇总表之前,您可以按升序或降序对数据范围进行排序。 这样可以确保输出始终以一致的顺序呈现数据,从而使下游处理更具可预测性。 请参见IronXL排序文档,了解范围级别的排序选项。

应用条件格式

通过条件格式规则应用突出显示异常值或阈值。 例如,当销售额低于目标时,您可以将汇总表中的单元格颜色设置为红色,从而提供一目了然的视图,而无需最终用户手动配置规则。

读取现有 Excel 文件

如果源数据来自现有电子表格而不是数据库,可以使用WorkBook.Load直接加载。

using IronXL;

WorkBook existing = WorkBook.Load(@"C:\data\sales_report.xlsx");
WorkSheet sheet = existing.WorkSheets[0];

// Read column C starting at row 2
var salesValues = sheet["C2:C100"]
    .Where(cell => cell.Value != null && cell.Value.ToString() != string.Empty)
    .Select(cell => cell.DecimalValue)
    .ToList();

decimal total = salesValues.Sum();
Console.WriteLine($"Total sales from file: {total:C}");

此模式适用于.csv,以及IronXL支持的其他格式。 有关支持的格式的详细信息,请参阅IronXL文件格式文档

导出为 CSV

生成汇总工作表后,您可以将其导出为 CSV 文件,以便供不支持 Excel 的下游系统使用:

workbook.SaveAsCsv(@"C:\output\summary.csv");

这在 ETL 管道中尤其有用,因为最终使用者是数据库导入工具或数据仓库加载器。

如何免费开始使用IronXL ?

IronXL提供免费试用许可,让您无需订阅即可评估所有功能。 试用版会在输出文件上添加水印,应用正式版许可证密钥后即可移除水印。

要在代码中激活许可证密钥,请在执行任何IronXL操作之前进行设置:

IronXL.License.LicenseKey = "YOUR-LICENSE-KEY-HERE";

您也可以通过环境变量(IRONXL_LICENSEKEY)或通过在ASP.NET Core项目中使用appsettings.json设置密钥。 IronXL许可页面描述了所有可用的级别,包括团队和组织选项。

对于生产部署,请查看IronXL部署文档和更广泛的IronXL教程库,涵盖ASP.NET Core、Azure Functions和Docker的模式。

如何迈出下一步?

C# 中的 Excel 数据透视表并不一定意味着对 Office 的依赖和 COM 的复杂性。 使用IronXL,您可以编写可在任何平台上运行的纯.NET代码,自动处理内存,并自然地与单元测试框架和 CI/CD 管道集成。

下载免费的IronXL试用版,并使用本指南中的示例对您自己的数据运行该示例。 如果您遇到任何问题, IronXL社区论坛支持门户网站对试用用户和授权用户均开放。 准备部署时,请查看许可选项,找到适合您团队规模和使用量的方案。

Curtis Chau
技术作家

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

...
阅读更多

相关文章

Key in blue circle

立即获取免费的 30 天试用版密钥

Your trial license will be sent to your email address

无任何限制。100% 解锁。无需信用卡。

bullet_checked无需信用卡或创建账户无任何限制。100% 解锁。无需信用卡。
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
预约您的免费现场演示
Booking Badge

深受全球数百万工程师信赖

Iron Software 的客户徽标
获取您的无义务咨询
填写下面的表格或通过sales@ironsoftware.com
您的资料将始终保密。
深受全球数百万工程师信赖
Iron Software 的客户徽标
立即获取您的免费30 天试用密钥
无需信用卡或创建账户