跳過到頁腳內容
使用 IRONXL

如何在 C# 中創建 Excel 樞紐分析表

在 Excel 中以程式方式生成樞紐分析表需要 C# Interop 及其 Office 依賴項或現代的庫,如獨立運行的IronXL。 本教程展示了這兩種方法,強調為什麼開發者越來越多地選擇 IronXL 而非傳統的 Interop 方法。

在本文中,我們將學習如何編輯、創建、設計和計算樞紐分析表和群組,具有自動分析和錯誤處理功能。

什麼是 Excel 樞紐分析表?

樞紐分析表類型是 Excel 中可以添加的最強大的工具之一。 這是一種簡單易行的方法,可以總結大型數據集。 因此,樞紐分析表允許您輕鬆顯示、理解和分析數據。 樞紐分析表不僅在 Excel 中可用,也在其他程序如 Google Sheets、Apple Numbers 和 CSV Export 中可用。 它提供了一種總覽數據的解決方案,作為數據控制台讓人們以有意義的方式看到他們的信息,連接到現實。

我們來先錯誤地創建一個樞紐分析表,然後學習如何用 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);
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

此 Interop 示例創建一個本地 XL 樞紐分析表,將產品作為行、地區作為列,並將銷售額在數據區域中求和。 雖然具有功能性,但此方法需要安裝 Microsoft Office 及小心管理 COM 對象。 參閱 Microsoft 文檔了解為什麼這種方法已不再現代。

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");
    }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

那麼在 2025 年,這就是您創建樞紐分析表的方式。

輸出

如何在 C# 中創建 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
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

這些公式維持與源數據的實時連接,當數據工作表更改時自動更新 - 類似於樞紐分析表刷新行為但不需要 Interop 依賴項。

如果我們將此代碼應用於前一個示例的 Excel 文件(XLS / XLSX),我們將得到以下字段的輸出到頁面:

如何在 C# 中創建 Excel 樞紐分析表: 圖 2 - 注意:C# 動態摘要輸出的場景上下文。

比較 C# Interop 和 IronXL 的樞紐分析表功能

方面

C# Interop

IronXL

需要 Office

是 - 完整安裝

否 - 獨立庫

平台支持

僅限 Windows

Windows, Linux, macOS, Docker

內存管理

需要手動 COM 清理

自動 .NET 垃圾收集

部署

複雜 - Office 許可

簡單 - 單一 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 許可要求而得到補償。

立即開始使用 IronXL。
green arrow pointer

準備好現代化您的 Excel 自動化並用現代 C# 創建您自己的樞紐分析表代碼了嗎?

IronXL 可以通過 NuGet 包管理器在數秒內實現到您的 C# 應用程序中。 試用免費試用版,以消除您的生產應用程序中的 Interop 依賴項。

常見問題解答

Excel 中的樞紐分析表是什麼?

Excel 中的樞紐分析表是一個用於總結、分析、探索和展示數據的強大工具。它允許用戶將列轉換為行,反之亦然,從而實現動態數據分析。

為什麼使用 IronXL 在 C# 中創建 Excel 樞紐分析表?

IronXL 允許開發者在 C# 中創建 Excel 樞紐分析表而不依賴 Office Interop,消除了需要 Excel 安裝和減少了依賴性,使其成為現代和高效的選擇。

IronXL 在 Excel 操作中與 C# Interop 相比如何?

IronXL 提供了一種比 C# Interop 更簡化和獨立的方法,C# Interop 需要安裝 Office。 IronXL 無需 Interop 的複雜性即可簡化樞紐分析表和其他 Excel 操作的創建。

我可以在沒有安裝 Excel 的情況下生成樞紐分析表嗎?

可以,使用 IronXL,你可以在 C# 應用中生成樞紐分析表,無需安裝 Excel,因為它獨立於 Microsoft Office 運行。

IronXL 適合處理大型數據集嗎?

IronXL 被設計為能有效地處理大型數據集,非常適合需要強大數據操作和樞紐分析表生成的應用。

與傳統方法相比,使用 IronXL 有什麼優勢?

IronXL 提供了一種現代且無依賴的替代方案,支持複雜數據操作而無需安裝 Excel,易於使用,靈活性高。

我需要學習 VBA 才能使用 IronXL 進行樞紐分析表嗎?

不需要,IronXL 允許開發者直接在 C# 中創建和管理樞紐分析表,無需學習 VBA 或其他 Excel 特定的編程語言。

Jordi Bardia
軟體工程師
Jordi 在 Python、C# 和 C++ 上最得心應手,當他不在 Iron Software 展現技術時,便在做遊戲編程。在分担产品测测试,产品开发和研究的责任时,Jordi 为持续的产品改进增值。他说这种多样化的经验使他受到挑战并保持参与, 而这也是他与 Iron Software 中工作一大乐趣。Jordi 在佛罗里达州迈阿密长大,曾在佛罗里达大学学习计算机科学和统计学。