如何使用 C# Interop 与 IronXL.Excel 在 Excel 中创建透视表
在Excel中以编程方式生成数据透视表需要使用C# Interop及其Office依赖项,或者使用像IronXL这样的现代库,它们可以独立工作。 本教程演示了这两种方法,强调了为什么开发人员越来越倾向于选择IronXL而不是传统的Interop方法。
在本文中,我们将学习如何编辑、创建、设计和计算数据透视表和分组,进行自动分析和错误处理。
什么是Excel数据透视表?
数据透视类型是您可以在Excel中添加的最强大的工具之一。 它是一种简单易用的方法来总结大型数据集。 因此,数据透视表允许您轻松显示、理解和分析数值数据。 数据透视表不仅在Excel中可用,还在其他程序中可用,如Google Sheets、Apple Numbers和CSV导出。 它提供了一种概述数据的解决方案 - 作为一个数据控制台,让人们以有意义的方式查看他们的信息 - 与现实相联系。
让我们先以错误的方式制作一个数据透视表,然后学习如何用C#制作一个正确的数据透视表:
如何使用C# Interop在Excel表格中创建数据透视表?
C# Excel Interop通过COM自动化提供对Excel数据透视表功能的直接访问。 这是许多开发人员在寻找工具以在C#中生成数据透视表时发现的传统方法:(不推荐)
如何用传统方式在.NET中创建数据透视表
using Excel = Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
// Create Excel application instance
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(@"C:\Data\SalesData.xlsx");
Excel.Worksheet xlSheet = (Excel.Worksheet)xlWorkbook.Sheets[1];
Excel.Worksheet xlPivotSheet = (Excel.Worksheet)xlWorkbook.Sheets.Add();
// Define data range for pivot table
Excel.Range dataRange = xlSheet.UsedRange;
// Row area and column area
// Create pivot cache and pivot table
Excel.PivotCache pivotCache = xlWorkbook.PivotCaches().Create(
Excel.XlPivotTableSourceType.xlDatabase,
dataRange,
Type.Missing);
Excel.PivotTable pivotTable = pivotCache.CreatePivotTable(
xlPivotSheet.Cells[3, 1],
"SalesPivot",
Type.Missing,
Type.Missing); // fields by field
// Configure pivot table fields
Excel.PivotField productField = (Excel.PivotField)pivotTable.PivotFields("Product");
productField.Orientation = Excel.XlPivotFieldOrientation.xlRowField;
productField.Position = 1;
Excel.PivotField regionField = (Excel.PivotField)pivotTable.PivotFields("Region");
regionField.Orientation = Excel.XlPivotFieldOrientation.xlColumnField;
regionField.Position = 1;
Excel.PivotField salesField = (Excel.PivotField)pivotTable.PivotFields("Sales");
pivotTable.AddDataField(salesField, "Sum of Sales", Excel.XlConsolidationFunction.xlSum);
// Save and cleanup
xlWorkbook.SaveAs(@"C:\Data\PivotReport.xlsx");
xlWorkbook.Close();
xlApp.Quit();
// Release COM objects to prevent memory leaks
Marshal.ReleaseComObject(pivotTable);
Marshal.ReleaseComObject(pivotCache);
Marshal.ReleaseComObject(xlPivotSheet);
Marshal.ReleaseComObject(xlSheet);
Marshal.ReleaseComObject(xlWorkbook);
Marshal.ReleaseComObject(xlApp);using Excel = Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
// Create Excel application instance
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(@"C:\Data\SalesData.xlsx");
Excel.Worksheet xlSheet = (Excel.Worksheet)xlWorkbook.Sheets[1];
Excel.Worksheet xlPivotSheet = (Excel.Worksheet)xlWorkbook.Sheets.Add();
// Define data range for pivot table
Excel.Range dataRange = xlSheet.UsedRange;
// Row area and column area
// Create pivot cache and pivot table
Excel.PivotCache pivotCache = xlWorkbook.PivotCaches().Create(
Excel.XlPivotTableSourceType.xlDatabase,
dataRange,
Type.Missing);
Excel.PivotTable pivotTable = pivotCache.CreatePivotTable(
xlPivotSheet.Cells[3, 1],
"SalesPivot",
Type.Missing,
Type.Missing); // fields by field
// Configure pivot table fields
Excel.PivotField productField = (Excel.PivotField)pivotTable.PivotFields("Product");
productField.Orientation = Excel.XlPivotFieldOrientation.xlRowField;
productField.Position = 1;
Excel.PivotField regionField = (Excel.PivotField)pivotTable.PivotFields("Region");
regionField.Orientation = Excel.XlPivotFieldOrientation.xlColumnField;
regionField.Position = 1;
Excel.PivotField salesField = (Excel.PivotField)pivotTable.PivotFields("Sales");
pivotTable.AddDataField(salesField, "Sum of Sales", Excel.XlConsolidationFunction.xlSum);
// Save and cleanup
xlWorkbook.SaveAs(@"C:\Data\PivotReport.xlsx");
xlWorkbook.Close();
xlApp.Quit();
// Release COM objects to prevent memory leaks
Marshal.ReleaseComObject(pivotTable);
Marshal.ReleaseComObject(pivotCache);
Marshal.ReleaseComObject(xlPivotSheet);
Marshal.ReleaseComObject(xlSheet);
Marshal.ReleaseComObject(xlWorkbook);
Marshal.ReleaseComObject(xlApp);/
此Interop示例创建一个本地XL数据透视表,产品作为行,地区作为列,销售额在数据区域求和。 虽然功能正常,但这种方法需要安装Microsoft Office并仔细管理COM对象。 请参阅微软文档,了解为什么不使用这种方法是现代的。
C# Interop带来了什么问题?
Interop方法面临几个重大挑战:
遗憾的是,Stack Overflow 和其他编程网站仍然推荐它,因为它们的讨论帖仍然停留在 2000 年代初期的想法上。
部署依赖性:需要在运行源代码的每台机器上(包括生产服务器)安装Microsoft Office。 这增加了许可成本和部署复杂性。
内存管理:必须使用Marshal.ReleaseComObject()显式释放COM对象。 即使遗漏一个对象也会导致Excel进程挂在内存中,如Stack Overflow上详细记录。 考虑数据透视缓存。
平台限制详情:这种老式解决方案仅适用于安装了Office的Windows。 而且可能非常慢 - 对用户来说令人困惑,并可能导致内存泄漏。 不支持Linux、macOS、Docker容器或像Azure Functions这样的云平台。
性能问题:启动Excel应用程序实例速度慢且资源密集,尤其是用于服务器端处理时。
版本兼容性:不同的Office版本可能具有不同的COM接口,导致跨环境的兼容性问题。
IronXL如何以编程方式创建数据透视表,无需Interop?
IronXL采用不同的方法来创建数据透视表,使用托管代码,无需COM依赖。 虽然它不会创建本机Excel数据透视表,但它提供了强大的聚合功能:
如何以现代方式以编程方式创建XLSX或XLS数据透视表:
using IronXL;
using System.Linq;
using System.Data; // Keep this namespace
using static System.Data.DataTableExtensions; // Use 'using static' for DataTableExtensions
class Program
{
static void Main(string[] args)
{
// Load Excel file - no Office required
WorkBook workbook = WorkBook.Load("SalesData.xlsx");
WorkSheet dataSheet = workbook.WorkSheets[0];
// Convert to DataTable for powerful manipulation
var dataTable = dataSheet.ToDataTable(true); // true = use first row as column headers
// Create pivot-style aggregation using LINQ
var pivotData = dataTable.AsEnumerable()
.GroupBy(row => new {
Product = row["Product"].ToString(),
Region = row["Region"].ToString()
}) //range
.Select(g => new {
Product = g.Key.Product,
Region = g.Key.Region,
TotalSales = g.Sum(row => Convert.ToDecimal(row["Sales"])),
AverageSale = g.Average(row => Convert.ToDecimal(row["Sales"])),
Count = g.Count()
});
// Create pivot report worksheet
WorkSheet pivotSheet = workbook.CreateWorkSheet("PivotReport");
// Build cross-tabulation structure
var products = pivotData.Select(p => p.Product).Distinct().OrderBy(p => p);
var regions = pivotData.Select(p => p.Region).Distinct().OrderBy(r => r);
// Create headers
pivotSheet["A1"].Value = "Product/Region";
int col = 2;
foreach (var region in regions)
{
pivotSheet[$"{(char)('A' + col - 1)}1"].Value = region; // string
col++;
}
// Populate pivot data
int row = 2;
foreach (var product in products)
{
pivotSheet[$"A{row}"].Value = product;
col = 2;
foreach (var region in regions)
{
var sales = pivotData
.Where(p => p.Product == product && p.Region == region)
.Select(p => p.TotalSales)
.FirstOrDefault();
pivotSheet[$"{(char)('A' + col - 1)}{row}"].Value = sales;
col++;
}
row++;
}
// Add totals using Excel formulas
pivotSheet[$"A{row}"].Value = "Total"; // grand totals
for (int c = 2; c <= regions.Count() + 1; c++)
{
pivotSheet[$"{(char)('A' + c - 1)}{row}"].Formula = $"=SUM({(char)('A' + c - 1)}2:{(char)('A' + c - 1)}{row - 1})";
}
// Proceeding to apply formatting
var dataRange = pivotSheet[$"B2:{(char)('A' + regions.Count())}{row}"];
dataRange.FormatString = "$#,##0.00";
workbook.SaveAs("PivotReport.xlsx");
}
}using IronXL;
using System.Linq;
using System.Data; // Keep this namespace
using static System.Data.DataTableExtensions; // Use 'using static' for DataTableExtensions
class Program
{
static void Main(string[] args)
{
// Load Excel file - no Office required
WorkBook workbook = WorkBook.Load("SalesData.xlsx");
WorkSheet dataSheet = workbook.WorkSheets[0];
// Convert to DataTable for powerful manipulation
var dataTable = dataSheet.ToDataTable(true); // true = use first row as column headers
// Create pivot-style aggregation using LINQ
var pivotData = dataTable.AsEnumerable()
.GroupBy(row => new {
Product = row["Product"].ToString(),
Region = row["Region"].ToString()
}) //range
.Select(g => new {
Product = g.Key.Product,
Region = g.Key.Region,
TotalSales = g.Sum(row => Convert.ToDecimal(row["Sales"])),
AverageSale = g.Average(row => Convert.ToDecimal(row["Sales"])),
Count = g.Count()
});
// Create pivot report worksheet
WorkSheet pivotSheet = workbook.CreateWorkSheet("PivotReport");
// Build cross-tabulation structure
var products = pivotData.Select(p => p.Product).Distinct().OrderBy(p => p);
var regions = pivotData.Select(p => p.Region).Distinct().OrderBy(r => r);
// Create headers
pivotSheet["A1"].Value = "Product/Region";
int col = 2;
foreach (var region in regions)
{
pivotSheet[$"{(char)('A' + col - 1)}1"].Value = region; // string
col++;
}
// Populate pivot data
int row = 2;
foreach (var product in products)
{
pivotSheet[$"A{row}"].Value = product;
col = 2;
foreach (var region in regions)
{
var sales = pivotData
.Where(p => p.Product == product && p.Region == region)
.Select(p => p.TotalSales)
.FirstOrDefault();
pivotSheet[$"{(char)('A' + col - 1)}{row}"].Value = sales;
col++;
}
row++;
}
// Add totals using Excel formulas
pivotSheet[$"A{row}"].Value = "Total"; // grand totals
for (int c = 2; c <= regions.Count() + 1; c++)
{
pivotSheet[$"{(char)('A' + c - 1)}{row}"].Formula = $"=SUM({(char)('A' + c - 1)}2:{(char)('A' + c - 1)}{row - 1})";
}
// Proceeding to apply formatting
var dataRange = pivotSheet[$"B2:{(char)('A' + regions.Count())}{row}"];
dataRange.FormatString = "$#,##0.00";
workbook.SaveAs("PivotReport.xlsx");
}
}因此,到2025年,这就是如何创建数据透视表。
输出
如何使用 C# 互操作 与IronXL在 Excel 中创建数据透视表:图 1 - 原始 Excel 文件与我们创建的数据透视表,显示了单元格。
如何使用IronXL公式创建动态摘要?
对于需要类似创建数据透视表的动态更新场景,计算数据透视表刷新功能,IronXL可以利用Excel内置公式来获得答案。 通常,这比前面的答案更可取 - 您的记录以更现代和优雅的方式被处理,通过代码,人们可以轻松理解。 易于设置,无需联系支持或阅读手册。
// Load the workbook
WorkBook workbook = WorkBook.Load(inputPath);
// Rename the first worksheet so formulas reference correctly
WorkSheet dataSheet = workbook.WorkSheets[0];
dataSheet.Name = "DataSheet";
// Convert worksheet to DataTable
DataTable dataTable = dataSheet.ToDataTable(true);
// Create new summary worksheet
WorkSheet summarySheet = workbook.CreateWorkSheet("DynamicSummary");
// Get unique product-region combinations
var uniqueCombos = dataTable.AsEnumerable()
.Select(row => new {
Product = row["Product"].ToString(),
Region = row["Region"].ToString()
})
.Distinct()
.OrderBy(x => x.Product)
.ThenBy(x => x.Region);
// Add header row
summarySheet["A1"].Value = "Product";
summarySheet["B1"].Value = "Region";
summarySheet["C1"].Value = "Total Sales";
summarySheet["D1"].Value = "Count";
// Populate rows with formulas
int rowIndex = 2;
foreach (var combo in uniqueCombos)
{
summarySheet[$"A{rowIndex}"].Value = combo.Product;
summarySheet[$"B{rowIndex}"].Value = combo.Region;
// Adjust column references if your Sales column is C (not D)
summarySheet[$"C{rowIndex}"].Formula =
$"=SUMIFS(DataSheet!C:C,DataSheet!A:A,\"{combo.Product}\",DataSheet!B:B,\"{combo.Region}\")";
summarySheet[$"D{rowIndex}"].Formula =
$"=COUNTIFS(DataSheet!A:A,\"{combo.Product}\",DataSheet!B:B,\"{combo.Region}\")";
rowIndex++;
}
// Optional: add total row
summarySheet[$"A{rowIndex}"].Value = "Total";
summarySheet[$"C{rowIndex}"].Formula = $"=SUM(C2:C{rowIndex - 1})";
summarySheet[$"D{rowIndex}"].Formula = $"=SUM(D2:D{rowIndex - 1})";
// Save output file
workbook.SaveAs(outputPath); //filename// Load the workbook
WorkBook workbook = WorkBook.Load(inputPath);
// Rename the first worksheet so formulas reference correctly
WorkSheet dataSheet = workbook.WorkSheets[0];
dataSheet.Name = "DataSheet";
// Convert worksheet to DataTable
DataTable dataTable = dataSheet.ToDataTable(true);
// Create new summary worksheet
WorkSheet summarySheet = workbook.CreateWorkSheet("DynamicSummary");
// Get unique product-region combinations
var uniqueCombos = dataTable.AsEnumerable()
.Select(row => new {
Product = row["Product"].ToString(),
Region = row["Region"].ToString()
})
.Distinct()
.OrderBy(x => x.Product)
.ThenBy(x => x.Region);
// Add header row
summarySheet["A1"].Value = "Product";
summarySheet["B1"].Value = "Region";
summarySheet["C1"].Value = "Total Sales";
summarySheet["D1"].Value = "Count";
// Populate rows with formulas
int rowIndex = 2;
foreach (var combo in uniqueCombos)
{
summarySheet[$"A{rowIndex}"].Value = combo.Product;
summarySheet[$"B{rowIndex}"].Value = combo.Region;
// Adjust column references if your Sales column is C (not D)
summarySheet[$"C{rowIndex}"].Formula =
$"=SUMIFS(DataSheet!C:C,DataSheet!A:A,\"{combo.Product}\",DataSheet!B:B,\"{combo.Region}\")";
summarySheet[$"D{rowIndex}"].Formula =
$"=COUNTIFS(DataSheet!A:A,\"{combo.Product}\",DataSheet!B:B,\"{combo.Region}\")";
rowIndex++;
}
// Optional: add total row
summarySheet[$"A{rowIndex}"].Value = "Total";
summarySheet[$"C{rowIndex}"].Formula = $"=SUM(C2:C{rowIndex - 1})";
summarySheet[$"D{rowIndex}"].Formula = $"=SUM(D2:D{rowIndex - 1})";
// Save output file
workbook.SaveAs(outputPath); //filename这些公式与源数据保持实时连接,当数据表更改时自动更新 - 类似于数据透视表刷新行为,但没有Interop依赖。
如果我们将此代码应用于前面示例中的Excel文件(XLS / XLSX),我们将获得这样的字段输出到页面:
如何在 Excel 中使用 C# 互操作 与IronXL创建数据透视表:图 2 - 注意:C# 动态汇总输出似乎在位置上下文中。
比较C# Interop与IronXL的数据透视表
|方面| C# 互操作 |IronXL| |---|---|---| | 办公室要求 | 是的 - 完全安装 | 否 - 独立库 | |平台支持|仅限 Windows| Windows、Linux、macOS、Docker | |内存管理| 需要手动清理 COM 对象 | 自动 .NET 垃圾回收 | |部署| 复杂 - 办公室许可 | 简单 - 单个 DLL | | 表现 | Excel进程启动缓慢 | 快速内存计算 | | 云端兼容 | 否 - Azure 限制 | 是的 - 支持 Azure Functions | | 原生透视表 | 是 | 无 - 聚合替代方案 | | 发展速度 | 速度慢 - COM 复杂性 | 快速直观的 API |
你应该选择哪种方法?
选择C# Interop当:
- 绝对需要本机Excel数据透视表对象
- 专门在安装了Office的Windows上工作
- 仅在您管理的桌面系统上部署
- 现有的遗留代码依赖于Interop
- 使用遗留.NET Framework版本
选择IronXL当:
- 部署到服务器或云环境和服务(Azure、AWS...)
- 构建跨平台应用程序
- 需要更好的性能和可靠性
- 避免Office授权成本
- 需要更简单、可维护的代码
- 支持Mac、iOS、Android和/或Linux系统
- 在现代.NET Framework Core和.NET 5,6,7,8,9,10中工作
- 你希望在开发控制台/IDE中完全访问配置数据范围内每个字段的透视表设置。
结论
虽然C# Excel Interop可以开发本地数据透视表,但其部署限制和复杂性使其对于现代应用程序来说越来越不现实。 IronXL通过数据聚合和基于公式的概要提供强大的替代方案,消除Office依赖,同时保持分析能力。 如果这对您有帮助,请投票、评论或订阅。
对于开发人员寻找不使用Interop开发数据透视表的替代方案,IronXL提供了一条优越的路径,避免了COM复杂性,适用于所有平台,并简化了部署。 虽然没有本机数据透视对象的权衡通过更大的灵活性、更好的性能和消除Office许可要求得以补偿。
准备好现代化您的Excel自动化并在现代C#中创建自己的数据透视表代码了吗?
IronXL可以通过NuGet包管理器在您的C#应用程序中实现于瞬间。 您可以试用免费试用版或购买IronXL许可证,以消除生产应用程序中的互操作依赖关系。
常见问题解答
如何在不使用 Interop 的情况下,使用 C# 在 Excel 中创建数据透视表?
您可以使用 C# 在 Excel 中创建数据透视表,无需 Interop,只需使用 IronXL 即可。IronXL 提供强大的数据操作功能,且不受 Office 依赖项的影响。
使用 IronXL 生成数据透视表有哪些优势?
IronXL 允许开发人员生成数据透视表,而无需依赖 Excel Interop,从而消除了安装 Office 的需要,并降低了部署的复杂性。
IronXL 兼容 .NET 应用程序吗?
是的,IronXL 与 .NET 应用程序完全兼容,提供易于使用的 Excel 操作 API,包括创建数据透视表。
IronXL是否需要在服务器上安装Excel?
不,IronXL 不需要在服务器上安装 Excel。它可以独立运行,从而可以无缝集成到服务器端应用程序中。
我可以使用 IronXL 在 Excel 中处理数据吗?
是的,IronXL 提供强大的数据处理功能,使开发人员能够创建、修改和分析 Excel 数据,包括创建数据透视表。
为什么开发人员会更喜欢 IronXL 而不是传统的互操作方法?
由于 IronXL 没有 Office 依赖项、部署更简单,并且具有全面的 Excel 操作功能,因此开发人员可能更喜欢 IronXL 而不是传统的 Interop 方法。
IronXL 为 Excel 数据处理提供了哪些功能?
IronXL 提供读取和写入 Excel 文件、创建和编辑电子表格以及生成数据透视表等功能,所有这些都不需要 Excel Interop。






