如何使用 IronXL 在 Excel 中使用 C# 建立資料透視表
在 Excel 中以程式設計方式產生資料透視表需要使用 C# 互通 及其 Office 依賴項,或使用像IronXL這樣可以獨立工作的現代函式庫——本教學示範了這兩種方法,並向您展示了為什麼現代方法才是更好的選擇。
歷史上,在伺服器端或跨平台 .NET 程式碼中建立透視表一直是一件很痛苦的事情。 傳統的 COM 互通方式會將您綁定到安裝了完整 Office 的 Windows 機器上,如果您錯過一次 COM 清理調用,就會產生內存洩漏,並且一旦嘗試部署到 Linux 或 Docker 容器,就會崩潰。 現代的替代方案——使用 IronXL 和 LINQ 編寫聚合邏輯——可以在任何 .NET 運行的地方運行,不需要 Office 許可證,並且可以提供簡潔、易讀的程式碼。
本指南將詳細介紹這兩種技術。 您將看到原始的互通方法,了解它究竟脆弱在哪裡,然後使用 IronXL 在 C# 中建立相同的透視式匯總表。 您還將看到如何使用 Excel 公式實現即時、自動更新的匯總,其行為類似於真正的資料透視表刷新。
什麼是Excel資料透視表?
資料透視表是電子表格軟體中最強大的分析工具之一。 它透過對行進行分組、聚合值並將結果投影到交叉表佈局中來匯總大型資料集——所有這些都不需要您手動編寫任何公式。 微軟官方的透視表文件對 Excel 內部的透視表功能進行了全面的概述。
資料透視表出現在 Microsoft Excel、Google Sheets、Apple Numbers 和大多數其他電子表格工具中。 核心概念始終相同:您定義行字段、列字段和值字段,該工具將為您建立匯總矩陣。 當基礎資料變更時,刷新透視表,匯總資訊會自動更新。
在 C# 伺服器端程式碼中,您主要有兩種選擇:
- C# 互通-- 透過 COM 自動執行正在執行的 Excel 進程,從而在 XLSX 檔案中建立真正的原生資料透視表對象 IronXL 與 LINQ 聚合——將工作簿讀入內存,在託管的 .NET 程式碼中計算相同的摘要,並將結果寫入新的工作表。
兩種方法都能產生有用的結果。 但只有其中一種能夠在現代部署環境中可靠運作。
如何使用 C# 互通 建立資料透視表?
C# Excel Interop 可讓您透過 COM 自動化直接存取 Excel 的原生資料透視表功能。 您建立一個 Excel.Application 對象,開啟一個工作簿,定義一個指向資料範圍的透視緩存,然後配置行欄位、列欄位和資料欄位。
如何設定互通透視表程式碼
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;
// 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);
// 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;
// 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);
// 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);
Imports Excel = Microsoft.Office.Interop.Excel
Imports System.Runtime.InteropServices
' Create Excel application instance
Dim xlApp As New Excel.Application()
Dim xlWorkbook As Excel.Workbook = xlApp.Workbooks.Open("C:\Data\SalesData.xlsx")
Dim xlSheet As Excel.Worksheet = CType(xlWorkbook.Sheets(1), Excel.Worksheet)
Dim xlPivotSheet As Excel.Worksheet = CType(xlWorkbook.Sheets.Add(), Excel.Worksheet)
' Define data range for pivot table
Dim dataRange As Excel.Range = xlSheet.UsedRange
' Create pivot cache and pivot table
Dim pivotCache As Excel.PivotCache = xlWorkbook.PivotCaches().Create(Excel.XlPivotTableSourceType.xlDatabase, dataRange, Type.Missing)
Dim pivotTable As Excel.PivotTable = pivotCache.CreatePivotTable(xlPivotSheet.Cells(3, 1), "SalesPivot", Type.Missing, Type.Missing)
' Configure pivot table fields
Dim productField As Excel.PivotField = CType(pivotTable.PivotFields("Product"), Excel.PivotField)
productField.Orientation = Excel.XlPivotFieldOrientation.xlRowField
productField.Position = 1
Dim regionField As Excel.PivotField = CType(pivotTable.PivotFields("Region"), Excel.PivotField)
regionField.Orientation = Excel.XlPivotFieldOrientation.xlColumnField
regionField.Position = 1
Dim salesField As Excel.PivotField = CType(pivotTable.PivotFields("Sales"), Excel.PivotField)
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 範例建立了一個原生 Excel 資料透視表,其中產品為行,地區為列,銷售額匯總在資料區中。 雖然它確實在 XLSX 檔案中產生了一個真正的透視表對象,但這需要安裝 Microsoft Office,並且需要仔細管理 COM 對象。 錯過一次 Marshal.ReleaseComObject 調用,您會發現任務管理器中累積了大量過期的 Excel 進程。
如何在編寫任何程式碼之前安裝 IronXL
在採用 IronXL 方法之前,請先透過 NuGet 套件管理器安裝該程式庫:
Install-Package IronXL.Excel
dotnet add package IronXL.Excel
Install-Package IronXL.Excel
dotnet add package IronXL.Excel
伺服器、容器或開發機器上無需安裝 Office。 IronXL 完全在託管的 .NET 記憶體中讀取和寫入 XLSX、XLS 和 CSV 檔案。
C# 互通會帶來哪些問題?
互通性方法存在一些重大挑戰,這些挑戰在實際部署中會迅速加劇。 Stack Overflow 和其他程式設計資源仍然推薦它,因為許多貼文寫於 2000 年代初期,並且後來被鎖定——所以這些建議已經停滯不前。
部署相依性-執行您的程式碼的每台機器都必須安裝已授權的 Microsoft Office 副本,包括生產伺服器和 CI/CD 建置代理程式。 這既增加了許可成本,也增加了部署複雜性,而這些問題完全可以透過現代替代方案來避免。
記憶體管理負擔-- COM 物件必須使用 Marshal.ReleaseComObject() 明確釋放。 即使缺少一個物件也會導致 Excel 進程無限期地在記憶體中掛起, Stack Overflow 上對此有大量記錄。 對於長時間運行的服務或 ASP.NET Web 應用程式而言,這會造成嚴重的資源洩漏。
平台限制-互通功能僅適用於安裝了 Office 的 Windows 系統。 它無法在 Linux、macOS、Docker 容器或 Azure Functions 或 AWS Lambda 等無伺服器平台上運作。 這會完全阻礙你使用現代雲端原生架構。
效能瓶頸-啟動 Excel 應用程式實例速度慢且資源消耗大。對於需要產生數十甚至數百份報表的伺服器端批次處理,這種啟動開銷會成為嚴重的吞吐量瓶頸。
版本相容性脆弱-不同的 Office 版本提供的 COM 介面略有不同。 適用於 Office 2019 的程式碼在 Office 2016 或 Microsoft 365 中可能表現不同,而且您無法在部署中固定版本。 微軟關於 Office Interop 組件的文檔指出,這些版本控制限制是一個已知的限制。
CI/CD 不相容-大多數持續整合環境都沒有安裝 Office。 測試資料透視表產生程式碼需要模擬整個 COM 層,或維護一個具有已授權 Office 安裝的特殊 Windows 代理程式。
對於任何面向 .NET 6 或更高版本(包括 .NET 10)的新 .NET 應用程序,這些限制使得互通成為一種不切實際的選擇。
IronXL 如何在不使用互通的情況下建立資料透視表?
IronXL建立資料透視表的方法有所不同。 IronXL 不是透過 COM 控制外部 Excel 進程,而是將工作簿讀入託管的 .NET 內存,讓您可以直接存取單元格值、公式和工作表結構。 然後,您可以使用標準 LINQ 查詢建立透視表式聚合,並將結果寫回新的工作表。
如何使用 IronXL 和 LINQ 建立交叉表匯總
以下範例載入銷售資料工作簿,計算按地區劃分的產品交叉表,並將匯總結果寫入新工作表——所有這些都無需任何 Office 依賴項:
using IronXL;
using System.Linq;
using System.Data;
// Load Excel file -- no Office installation required
WorkBook workbook = WorkBook.Load("SalesData.xlsx");
WorkSheet dataSheet = workbook.WorkSheets[0];
// Convert to DataTable for flexible LINQ manipulation
var dataTable = dataSheet.ToDataTable(true); // true = first row as column headers
// Build pivot-style aggregation using LINQ grouping
var pivotData = dataTable.AsEnumerable()
.GroupBy(row => new {
Product = row["Product"].ToString(),
Region = row["Region"].ToString()
})
.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 the pivot report worksheet
WorkSheet pivotSheet = workbook.CreateWorkSheet("PivotReport");
// Get distinct row and column values
var products = pivotData.Select(p => p.Product).Distinct().OrderBy(p => p).ToList();
var regions = pivotData.Select(p => p.Region).Distinct().OrderBy(r => r).ToList();
// Write column headers
pivotSheet["A1"].Value = "Product / Region";
for (int c = 0; c < regions.Count; c++)
{
pivotSheet[$"{(char)('B' + c)}1"].Value = regions[c];
}
// Populate data rows
for (int r = 0; r < products.Count; r++)
{
pivotSheet[$"A{r + 2}"].Value = products[r];
for (int c = 0; c < regions.Count; c++)
{
var sales = pivotData
.Where(p => p.Product == products[r] && p.Region == regions[c])
.Select(p => p.TotalSales)
.FirstOrDefault();
pivotSheet[$"{(char)('B' + c)}{r + 2}"].Value = sales;
}
}
// Add a totals row using Excel SUM formulas
int totalRow = products.Count + 2;
pivotSheet[$"A{totalRow}"].Value = "Total";
for (int c = 0; c < regions.Count; c++)
{
char col = (char)('B' + c);
pivotSheet[$"{col}{totalRow}"].Formula = $"=SUM({col}2:{col}{totalRow - 1})";
}
// Apply currency formatting to the data range
var dataRange = pivotSheet[$"B2:{(char)('B' + regions.Count - 1)}{totalRow}"];
dataRange.FormatString = "$#,##0.00";
workbook.SaveAs("PivotReport.xlsx");
using IronXL;
using System.Linq;
using System.Data;
// Load Excel file -- no Office installation required
WorkBook workbook = WorkBook.Load("SalesData.xlsx");
WorkSheet dataSheet = workbook.WorkSheets[0];
// Convert to DataTable for flexible LINQ manipulation
var dataTable = dataSheet.ToDataTable(true); // true = first row as column headers
// Build pivot-style aggregation using LINQ grouping
var pivotData = dataTable.AsEnumerable()
.GroupBy(row => new {
Product = row["Product"].ToString(),
Region = row["Region"].ToString()
})
.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 the pivot report worksheet
WorkSheet pivotSheet = workbook.CreateWorkSheet("PivotReport");
// Get distinct row and column values
var products = pivotData.Select(p => p.Product).Distinct().OrderBy(p => p).ToList();
var regions = pivotData.Select(p => p.Region).Distinct().OrderBy(r => r).ToList();
// Write column headers
pivotSheet["A1"].Value = "Product / Region";
for (int c = 0; c < regions.Count; c++)
{
pivotSheet[$"{(char)('B' + c)}1"].Value = regions[c];
}
// Populate data rows
for (int r = 0; r < products.Count; r++)
{
pivotSheet[$"A{r + 2}"].Value = products[r];
for (int c = 0; c < regions.Count; c++)
{
var sales = pivotData
.Where(p => p.Product == products[r] && p.Region == regions[c])
.Select(p => p.TotalSales)
.FirstOrDefault();
pivotSheet[$"{(char)('B' + c)}{r + 2}"].Value = sales;
}
}
// Add a totals row using Excel SUM formulas
int totalRow = products.Count + 2;
pivotSheet[$"A{totalRow}"].Value = "Total";
for (int c = 0; c < regions.Count; c++)
{
char col = (char)('B' + c);
pivotSheet[$"{col}{totalRow}"].Formula = $"=SUM({col}2:{col}{totalRow - 1})";
}
// Apply currency formatting to the data range
var dataRange = pivotSheet[$"B2:{(char)('B' + regions.Count - 1)}{totalRow}"];
dataRange.FormatString = "$#,##0.00";
workbook.SaveAs("PivotReport.xlsx");
Imports IronXL
Imports System.Linq
Imports System.Data
' Load Excel file -- no Office installation required
Dim workbook As WorkBook = WorkBook.Load("SalesData.xlsx")
Dim dataSheet As WorkSheet = workbook.WorkSheets(0)
' Convert to DataTable for flexible LINQ manipulation
Dim dataTable As DataTable = dataSheet.ToDataTable(True) ' True = first row as column headers
' Build pivot-style aggregation using LINQ grouping
Dim pivotData = dataTable.AsEnumerable() _
.GroupBy(Function(row) New With {
Key .Product = row("Product").ToString(),
Key .Region = row("Region").ToString()
}) _
.Select(Function(g) New With {
Key .Product = g.Key.Product,
Key .Region = g.Key.Region,
Key .TotalSales = g.Sum(Function(row) Convert.ToDecimal(row("Sales"))),
Key .AverageSale = g.Average(Function(row) Convert.ToDecimal(row("Sales"))),
Key .Count = g.Count()
})
' Create the pivot report worksheet
Dim pivotSheet As WorkSheet = workbook.CreateWorkSheet("PivotReport")
' Get distinct row and column values
Dim products = pivotData.Select(Function(p) p.Product).Distinct().OrderBy(Function(p) p).ToList()
Dim regions = pivotData.Select(Function(p) p.Region).Distinct().OrderBy(Function(r) r).ToList()
' Write column headers
pivotSheet("A1").Value = "Product / Region"
For c As Integer = 0 To regions.Count - 1
pivotSheet($"{ChrW(AscW("B"c) + c)}1").Value = regions(c)
Next
' Populate data rows
For r As Integer = 0 To products.Count - 1
pivotSheet($"A{r + 2}").Value = products(r)
For c As Integer = 0 To regions.Count - 1
Dim sales = pivotData _
.Where(Function(p) p.Product = products(r) AndAlso p.Region = regions(c)) _
.Select(Function(p) p.TotalSales) _
.FirstOrDefault()
pivotSheet($"{ChrW(AscW("B"c) + c)}{r + 2}").Value = sales
Next
Next
' Add a totals row using Excel SUM formulas
Dim totalRow As Integer = products.Count + 2
pivotSheet($"A{totalRow}").Value = "Total"
For c As Integer = 0 To regions.Count - 1
Dim col As Char = ChrW(AscW("B"c) + c)
pivotSheet($"{col}{totalRow}").Formula = $"=SUM({col}2:{col}{totalRow - 1})"
Next
' Apply currency formatting to the data range
Dim dataRange = pivotSheet($"B2:{ChrW(AscW("B"c) + regions.Count - 1)}{totalRow}")
dataRange.FormatString = "$#,##0.00"
workbook.SaveAs("PivotReport.xlsx")
這樣就能產生與 Excel 原生資料透視表相同的交叉匯總表。 您可以完全透過程式控制每個儲存格、公式和格式字串,而無需清理 COM 物件。
如何使用 C# 互通 與 IronXL 在 Excel 中建立資料透視表:圖 1 - 原始 Excel 檔案與建立的資料透視表對比,顯示了儲存格。
!{--01001100010010010100001001010010010000010101001001011001010111110100011101000101010101 01000101111101010011010101000100000101010010010101000100010101000100010111110101011101001000110 1010101000100100001011111010100000101001001001111010001000101010101010000110101010100101010101011 10101010001010010010010010010000010100110001011111010000100100110001001111101000011010010111111010000110100101110--
如何使用Excel公式建立動態匯總?
如果您希望匯總表保持即時更新(即來源資料變更時自動重新計算),IronXL 可讓您直接在儲存格中寫入 Excel 公式字串。 這樣就能實現類似透視表自動刷新的功能,而無需任何 Interop 依賴。
這裡的關鍵功能是 SUMIFS 和 COUNTIFS。 SUMIFS 根據多個條件列對範圍求和; COUNTIFS 統計匹配的行數。 兩者都接受已命名工作表的引用,因此您可以按名稱將總計表直接指向來源資料表。
如何使用 IronXL 編寫基於公式的聚合
using IronXL;
using System.Data;
string inputPath = "SalesData.xlsx";
string outputPath = "DynamicSummary.xlsx";
WorkBook workbook = WorkBook.Load(inputPath);
WorkSheet dataSheet = workbook.WorkSheets[0];
// Name the data sheet so formula references are stable
dataSheet.Name = "DataSheet";
// Convert to DataTable to enumerate unique product/region combinations
DataTable dataTable = dataSheet.ToDataTable(true);
WorkSheet summarySheet = workbook.CreateWorkSheet("DynamicSummary");
// Get unique product-region pairs
var uniqueCombos = dataTable.AsEnumerable()
.Select(row => new {
Product = row["Product"].ToString(),
Region = row["Region"].ToString()
})
.Distinct()
.OrderBy(x => x.Product)
.ThenBy(x => x.Region)
.ToList();
// Header row
summarySheet["A1"].Value = "Product";
summarySheet["B1"].Value = "Region";
summarySheet["C1"].Value = "Total Sales";
summarySheet["D1"].Value = "Count";
// Populate rows with live SUMIFS / COUNTIFS formulas
for (int i = 0; i < uniqueCombos.Count; i++)
{
int rowIndex = i + 2;
var combo = uniqueCombos[i];
summarySheet[$"A{rowIndex}"].Value = combo.Product;
summarySheet[$"B{rowIndex}"].Value = combo.Region;
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}\")";
}
// Grand total row
int totalRow = uniqueCombos.Count + 2;
summarySheet[$"A{totalRow}"].Value = "Total";
summarySheet[$"C{totalRow}"].Formula = $"=SUM(C2:C{totalRow - 1})";
summarySheet[$"D{totalRow}"].Formula = $"=SUM(D2:D{totalRow - 1})";
workbook.SaveAs(outputPath);
using IronXL;
using System.Data;
string inputPath = "SalesData.xlsx";
string outputPath = "DynamicSummary.xlsx";
WorkBook workbook = WorkBook.Load(inputPath);
WorkSheet dataSheet = workbook.WorkSheets[0];
// Name the data sheet so formula references are stable
dataSheet.Name = "DataSheet";
// Convert to DataTable to enumerate unique product/region combinations
DataTable dataTable = dataSheet.ToDataTable(true);
WorkSheet summarySheet = workbook.CreateWorkSheet("DynamicSummary");
// Get unique product-region pairs
var uniqueCombos = dataTable.AsEnumerable()
.Select(row => new {
Product = row["Product"].ToString(),
Region = row["Region"].ToString()
})
.Distinct()
.OrderBy(x => x.Product)
.ThenBy(x => x.Region)
.ToList();
// Header row
summarySheet["A1"].Value = "Product";
summarySheet["B1"].Value = "Region";
summarySheet["C1"].Value = "Total Sales";
summarySheet["D1"].Value = "Count";
// Populate rows with live SUMIFS / COUNTIFS formulas
for (int i = 0; i < uniqueCombos.Count; i++)
{
int rowIndex = i + 2;
var combo = uniqueCombos[i];
summarySheet[$"A{rowIndex}"].Value = combo.Product;
summarySheet[$"B{rowIndex}"].Value = combo.Region;
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}\")";
}
// Grand total row
int totalRow = uniqueCombos.Count + 2;
summarySheet[$"A{totalRow}"].Value = "Total";
summarySheet[$"C{totalRow}"].Formula = $"=SUM(C2:C{totalRow - 1})";
summarySheet[$"D{totalRow}"].Formula = $"=SUM(D2:D{totalRow - 1})";
workbook.SaveAs(outputPath);
Imports IronXL
Imports System.Data
Imports System.Linq
Dim inputPath As String = "SalesData.xlsx"
Dim outputPath As String = "DynamicSummary.xlsx"
Dim workbook As WorkBook = WorkBook.Load(inputPath)
Dim dataSheet As WorkSheet = workbook.WorkSheets(0)
' Name the data sheet so formula references are stable
dataSheet.Name = "DataSheet"
' Convert to DataTable to enumerate unique product/region combinations
Dim dataTable As DataTable = dataSheet.ToDataTable(True)
Dim summarySheet As WorkSheet = workbook.CreateWorkSheet("DynamicSummary")
' Get unique product-region pairs
Dim uniqueCombos = dataTable.AsEnumerable() _
.Select(Function(row) New With {
.Product = row("Product").ToString(),
.Region = row("Region").ToString()
}) _
.Distinct() _
.OrderBy(Function(x) x.Product) _
.ThenBy(Function(x) x.Region) _
.ToList()
' Header row
summarySheet("A1").Value = "Product"
summarySheet("B1").Value = "Region"
summarySheet("C1").Value = "Total Sales"
summarySheet("D1").Value = "Count"
' Populate rows with live SUMIFS / COUNTIFS formulas
For i As Integer = 0 To uniqueCombos.Count - 1
Dim rowIndex As Integer = i + 2
Dim combo = uniqueCombos(i)
summarySheet($"A{rowIndex}").Value = combo.Product
summarySheet($"B{rowIndex}").Value = combo.Region
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}"")"
Next
' Grand total row
Dim totalRow As Integer = uniqueCombos.Count + 2
summarySheet($"A{totalRow}").Value = "Total"
summarySheet($"C{totalRow}").Formula = $"=SUM(C2:C{totalRow - 1})"
summarySheet($"D{totalRow}").Formula = $"=SUM(D2:D{totalRow - 1})"
workbook.SaveAs(outputPath)
這些公式與來源資料保持即時連接。 當有人更新 DataSheet 中的值時,Excel 會在下次開啟或刷新時自動重新計算匯總資訊——這為您提供了與原生資料透視表刷新週期相同的行為,而無需 COM 自動化。
將此方法應用於上例中使用的相同銷售資料工作簿時,輸出結果如下所示:
如何在 Excel 中使用 C# 互通 與 IronXL 建立資料透視表:圖 2 - C# 動態匯總輸出的上下文顯示。
這種基於公式的方法還允許您使用IronXL 的單元格格式 API向匯總單元格添加條件格式、資料條或圖示集,從而使您的報告在視覺上清晰明了,而無需在 Excel 使用者介面中進行任何手動操作。
這兩種方法有何異同?
在選擇方法之前,權衡利弊很有幫助。下表涵蓋了生產環境 .NET 開發中最重要的幾個面向:
| 範疇 | C# 互通 | IronXL |
|---|---|---|
| 辦公室要求 | 是的——每台機器都要完整安裝。 | 否——獨立的 NuGet 套件 |
| 平台支援 | 僅限 Windows | Windows、Linux、macOS、Docker |
| 記憶體管理 | 需要手動清理 COM 對象 | 自動 .NET 垃圾回收 |
| 部署複雜性 | 高價 -- 辦公室軟體許可 + 安裝 | 低——單一 DLL 引用 |
| 表現 | 速度慢-Excel進程啟動開銷 | 快速——記憶體內計算 |
| 雲端相容 | 否-在 Azure Functions 和 AWS Lambda 上均已封鎖 | 是的——可在任何雲端平台上運行 |
| 原生透視表對象 | 是的-完整的Excel資料透視表 | 否——基於聚合的等效項 |
| 發展速度 | 速度慢——COM 複雜性 | 快速流暢的託管 API |
| .NET 10 支援 | 有限的 COM 綁定問題 | 完整版-面向現代 .NET |
Interop 唯一具有明顯優勢的情況是,當您特別需要將原生 Excel 資料透視表物件嵌入到 XLSX 檔案中時—例如,如果下游使用者必須使用 Excel 內建的資料透視表 UI 與之互動(向下鑽取、篩選、互動式地更改聚合函數)。 在其他所有情況下,IronXL 的方法編寫速度更快、部署更容易、可移植性也更強。
你該選擇哪一種方法?
正確的選擇取決於您的部署環境和使用者需求。
僅在以下情況選擇C# 互通:
您的使用者需要能夠在 Excel 使用者介面中互動式操作的原生 Excel 資料透視表物件。 您的目標是一個封閉的 Windows 桌面環境,其中每台機器都保證安裝了 Office。 您維護的舊版 .NET Framework 程式碼已經依賴 Interop,目前重寫並不合理。
選擇IronXL 的情況:
- 你要部署到伺服器、容器或任何雲端環境(Azure、AWS、GCP) 你需要對Linux、macOS或基於Docker的建置提供跨平台支援。 您想要簡潔、易於維護的程式碼,而無需 COM 生命週期管理。
- 您面對的是 .NET 5、6、7、8、9 或 10。 您希望避免在伺服器基礎架構上支付 Microsoft Office 授權費用 您需要快速批次處理多個工作簿,而無需逐一啟動 Excel 進程。
對於絕大多數現代 .NET 應用程式而言,IronXL 是切實可行的選擇。它基於聚合的輸出能夠滿足所有實際的報表需求,並且還能帶來完全的可移植性。
您可以在IronXL 文件和IronXL 範例庫中探索更多功能,包括儲存格格式設定、公式計算、資料驗證和圖表生成。
如何立即開始使用 IronXL?
IronXL 庫可在 NuGet 上取得,只需不到一分鐘即可新增至任何 .NET 專案:
Install-Package IronXL.Excel
dotnet add package IronXL.Excel
Install-Package IronXL.Excel
dotnet add package IronXL.Excel
安裝完成後,您可以使用簡潔、文件齊全的 API 載入現有工作簿或建立新工作簿,讀取和寫入儲存格值,套用公式,設定格式字串,並儲存為 XLSX。 它不依賴 COM,不依賴 Office,也不需要特殊的伺服器設定。
有關完整的 API 文檔,請參閱IronXL 入門指南、 C# Excel 互通遷移指南和IronXL 程式碼範例。 您也可以透過IronXL 比較文章將 IronXL 與其他 Excel 庫進行比較。
免費試用許可證可讓您在正式提交之前,在自己的專案中測試所有功能。 當您準備部署到生產環境時,商業版 IronXL 授權將移除試用浮水印並包含優先支援。 首先體驗免費試用版,看看跨平台 Excel 自動化可以變得多麼簡單。
常見問題解答
如何在不使用 Interop 的情況下,透過 C# 在 Excel 中建立樞紐分析表?
您可透過 IronXL.Excel 在 Excel 中使用 C# 建立樞紐分析表,無需依賴 Interop。IronXL 提供強大的資料處理功能,且不受 Office 依賴項的限制。
使用 IronXL 生成樞紐分析表有哪些優勢?
IronXL 讓開發人員無需依賴 Excel Interop 即可建立樞紐分析表,省去了安裝 Office 的需求,並降低了部署的複雜度。
IronXL 與 .NET 應用程式相容嗎?
是的,IronXL 與 .NET 應用程式完全相容,並提供易於使用的 API 來執行 Excel 操作,包括建立樞紐分析表。
IronXL 是否需要在伺服器上安裝 Excel?
不,IronXL 無需在伺服器上安裝 Excel。它可獨立運作,並能無縫整合至伺服器端應用程式中。
我可以使用 IronXL 在 Excel 中處理資料嗎?
是的,IronXL 提供強大的資料處理功能,讓開發人員能夠建立、修改及分析 Excel 資料,包括建立樞紐分析表。
開發人員為何會偏好 IronXL 而非傳統的 Interop 方法?
開發人員可能會偏好 IronXL 而非傳統的 Interop 方法,因為它不依賴 Office、部署更簡單,且具備全面的 Excel 操作功能。
IronXL 針對 Excel 資料處理提供了哪些功能?
IronXL 提供讀寫 Excel 檔案、建立與編輯試算表,以及產生樞紐分析表等功能,且完全無需使用 Excel Interop。


