跳過到頁腳內容
使用 IRONXL

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

在 Excel 中以程式設計方式產生資料透視表需要使用 C# 互通 及其 Office 依賴項,或使用像IronXL這樣可以獨立工作的現代函式庫。 本教學示範了這兩種方法,重點介紹了為什麼開發人員越來越多地選擇 IronXL 而不是傳統的互通方法。

本文將介紹如何編輯、建立、設計和計算資料透視表和資料透視組,並實現自動分析和錯誤處理。

什麼是Excel資料透視表?

資料透視表是Excel中最強大的工具之一。 這是一種簡單易行的匯總大型資料集的方法。 因此,資料透視表可以幫助您輕鬆顯示、理解和分析數值資料。 資料透視表不僅在 Excel 中可用,而且在其他程式中也可用,例如 Google Sheets、Apple Numbers 和 CSV Exports。 它提供了一種查看數據概覽的解決方案——充當數據控制台,讓人們以有意義的方式查看他們的資訊——與現實聯繫起來。

讓我們先用錯誤的方法建立一個資料透視表,然後再學習如何在 C# 中正確地建立資料透視表:

如何使用 C# 互通 在 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 物件管理。 請參閱微軟文檔,了解為什麼不使用這種現代方法。

C# 互通會帶來哪些問題?

互通性方法面臨幾個重大挑戰:

遺憾的是,Stack Overflow 和其他程式設計網站仍然推薦它,因為它們仍然停留在過去,討論的貼文也停留在 2000 年代初期的想法。

部署相依性:需要在執行原始碼的每台機器上安裝 Microsoft Office,包括生產伺服器。 這會增加許可成本和部署複雜性。

記憶體管理:必須使用 Marshal.ReleaseComObject() 明確釋放 COM 物件。 即使缺少一個物件也會導致 Excel 進程在記憶體中掛起, Stack Overflow 上對此有大量記錄。 考慮樞軸緩存。

平台限制詳情:此老式解決方案僅適用於安裝了 Office 的 Windows 系統。 而且速度可能非常慢——這會讓用戶感到困惑,並可能導致記憶體洩漏。 不支援 Linux、macOS、Docker 容器或 Azure Functions 等雲端平台。

效能問題:啟動 Excel 應用程式執行個體速度慢且資源消耗大,尤其是伺服器端處理。

版本相容性:不同 Office 版本可能具有不同的 COM 接口,從而導致跨環境的相容性問題。

IronXL 如何在不使用互通的情況下以程式設計方式建立資料透視表?

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

這些公式與來源資料保持即時連接,當資料表變更時自動更新—類似於資料透視表刷新行為,但沒有互通依賴性。

如果我們將這段程式碼應用到上一個範例中的範例 Excel 檔案(XLS / XLSX),我們將得到以下輸出結果:

如何在 C# 中建立 Excel 資料透視表:圖 2 - 注意:C# 動態匯總輸出似乎在位置上下文中。

比較 C# 互通 和 IronXL 在資料透視表方面的效能

範疇

C# 互通

IronXL

辦公室要求

是的 - 完全安裝

否 - 獨立庫

平台支持

僅限 Windows

Windows、Linux、macOS、Docker

內存管理

需要手動清理 COM 對象

自動 .NET 垃圾回收

部署

複雜 - 辦公室許可

簡單 - 單一 DLL

表現

Excel進程啟動緩慢

快速記憶體計算

雲端相容

否 - Azure 限制

是的 - 支援 Azure Functions

原生透視表

無 - 聚合替代方案

發展速度

速度慢 - COM 複雜性

快速直覺的 API

你該選擇哪一種方法?

選擇C# 互通的條件:

  • 必須使用 Excel 原生資料透視表對象
  • 僅在 Windows 系統上開發,且所有目標機器均已安裝 Office 辦公室軟體。
  • 僅部署到您管理的桌面系統
  • 現有遺留程式碼依賴互通性
  • 使用舊版 .NET Framework

選擇IronXL 的情況:

  • 部署到伺服器或雲端環境和服務(Azure、AWS 等)
  • 建立跨平台應用程式
  • 要求更高的性能和可靠性
  • 避免辦公室軟體授權費用 需要更簡潔、更容易維護的程式碼
  • 支援 Mac、iOS、Android 和/或 Linux 系統
  • 熟悉現代 .NET Framework Core 和 .NET 5、6、7、8、9、10。
  • 您需要在開發控制台/IDE 中擁有完全存取權限,以便根據資料範圍以程式設計方式配置透視表中每個欄位的設定。

結論

雖然 C# Excel Interop 可以開發原生透視表,但其部署限制和複雜性使其在現代應用程式中越來越不實用。 IronXL透過資料聚合和基於公式的匯總提供強大的替代方案,消除了對 Office 的依賴,同時保持了分析能力。 如果本文對您有幫助,請投票、評論或訂閱。

對於正在尋找無需 Interop 即可開發透視表的替代方案的開發人員來說,IronXL 提供了一種更優的途徑,避免了 COM 的複雜性,可在所有平台上運行,並簡化部署。 雖然沒有原生透視對象,但更大的靈活性、更好的性能以及無需 Office 許可的要求彌補了這一不足。

!{--01001100010010010100001001010010010000010101001001011001010111110100011101000101010101 01000101111101010011010101000100000101010010010101000100010101000100010111110101011101001000110 1010101000100100001011111010100000101001001001111010001000101010101010000110101010100101010101011 10101010001010010010010010010000010100110001011111010000100100110001001111101000011010010111111010000110100101110--

準備好讓您的 Excel 自動化流程現代化,並使用現代 C# 建立您自己的資料透視表程式碼了嗎?

透過 NuGet 套件管理器,可以在幾秒鐘內將 IronXL 整合到您的 C# 應用程式中。 試用免費版本,消除生產應用程式中的互通依賴。

常見問題解答

什麼是 Excel 中的透視表?

Excel 中的透視表是用於總結、分析、探索和展示資料的強大工具。它允許使用者將列轉換為行,反之亦然,從而實現動態資料分析。

為何要使用 IronXL 在 C# 中建立 Excel 資料透視表?

IronXL 可讓開發人員在不依賴 Office Interop 的情況下,以 C# 建立 Excel 資料透視表,不需要安裝 Excel 並減少依賴性,是現代化且有效率的選擇。

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

相較於需要安裝 Office 的 C# Interop,IronXL 提供了更精簡、更獨立的方法。IronXL.Excel 可簡化資料透視表和其他 Excel 作業的建立,而無需 Interop 的複雜性。

我可以在沒有安裝 Excel 的情況下產生資料透視表嗎?

是的,使用 IronXL,您可以在 C# 應用程式中產生資料透視表,而無需安裝 Excel,因為它是獨立於 Microsoft Office 運作的。

IronXL 適合大型資料集嗎?

IronXL 專為有效率地處理大型資料集而設計,因此適用於需要強大資料操作和產生資料透視表的應用程式。

與傳統方法相比,使用 IronXL 有哪些優勢?

IronXL 提供了一個現代化、無依賴性的替代方案,可取代 C# Interop 等傳統方法,提供易用性、彈性,並支援複雜的資料作業,而無需安裝 Excel。

使用 IronXL 製作透視表需要學習 VBA 嗎?

不,IronXL 可讓開發人員直接在 C# 中工作,以建立和管理資料透視表,而無需學習 VBA 或其他 Excel 專用的程式語言。

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