Jak utworzyć tabelę przestawną Excel w języku C#?
Tworzenie tabel przestawnych Excel w języku C# działa zarówno z Office Interop (wymagającym instalacji pakietu Microsoft Office), jak i nowoczesnymi bibliotekami, takimi jak IronXL, które działają niezależnie, przy czym IronXL oferuje większą elastyczność wdrożenia i obsługę wielu platform dla środowisk DevOps.
Programowe generowanie tabel przestawnych wymaga albo C# Interop z zależnościami Office, albo nowoczesnych bibliotek, takich jak IronXL, które działają niezależnie. W tym samouczku przedstawiono oba podejścia, podkreślając, dłączego programiści coraz częściej wybierają IronXL zamiast tradycyjnych metod Interop, zwłaszcza podczas wdrażania w kontenerach Docker lub środowiskach chmurowych, takich jak Azure i AWS.
W tym artykułe dowiemy się, jak edytować, tworzyć, projektować i obliczać tabele przestawne oraz grupy z automatyczną analizą i obsługą błędów — a wszystko to przy zachowaniu prostoty wdrożenia, której wymagają inżynierowie DevOps.
Czym jest tabela przestawna w programie Excel?
Tabela przestawna jest jednym z najpotężniejszych narzędzi programu Excel. Jest to łatwy sposób na podsumowanie dużych zbiorów danych, co czyni go nieocenionym narzędziem do analizy danych w aplikacjach .NET. Tabele przestawne pozwalają w łatwy sposób wyświetlać, rozumieć i analizować dane liczbowe. Są one dostępne nie tylko w Excelu, ale także w innych programach, takich jak Arkusze Google, Apple Numbers i eksporty CSV. Zapewniają one rozwiązanie umożliwiające przegląd danych — działają jak konsola danych, pozwalając użytkownikom przeglądać informacje w przejrzysty sposób.
W przypadku aplikacji kontenerowych programowe tworzenie tabel przestawnych eliminuje konieczność instalowania programu Excel w obrazach Docker, co znacznie zmniejsza rozmiar kontenera i złożoność wdrożenia. Takie podejście idealnie wpisuje się w nowoczesne procesy CI/CD oraz strategie wdrażania kontenerów.
Przyjrzyjmy się najpierw niewłaściwemu sposobowi tworzenia tabeli przestawnej, a następnie poznajmy właściwy sposób w języku C#:
Jak utworzyć tabelę przestawną w Excelu przy użyciu C# Interop?
C# Excel Interop zapewnia bezpośredni dostęp do funkcji tabel przestawnych programu Excel poprzez automatyzację COM. Oto tradycyjne podejście, z którym spotyka się wielu programistów, szukając narzędzi do generowania tabel przestawnych w języku C#:
Dłączego to podejście jest uważane za przestarzałe w .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);
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)
Ten przykład Interop tworzy natywną tabelę przestawną programu Excel z produktami w wierszach, regionami w kolumnach i sumą sprzedaży w obszarze danych. Chociaż podejście to jest funkcjonalne, wymaga instalacji pakietu Microsoft Office oraz starannego zarządzania obiektami COM. Dokumentacja Microsoftu wyjaśnia, dłączego takie podejście nie jest nowoczesne. Z punktu widzenia DevOps podejście to jest szczególnie problematyczne, ponieważ nie można go skutecznie konteneryzować — nie można zainstalować pakietu Microsoft Office w kontenerze Docker w systemie Linux ani wdrożyć go w środowiskach bezserwerowych.
Jakie problemy powoduje C# Interop?
Podejście Interop wiąże się z kilkoma istotnymi wyzwaniami, które sprawiają, że nie nadaje się ono do nowoczesnych praktyk DevOps i wdrożeń natywnych dla chmury.
Niestety, Stack Overflow i inne serwisy programistyczne nadal to zalecają, ponieważ są one zablokowane w czasie na wątkach z początku XXI wieku.
Wymagania dotyczące wdrożenia: Wymaga zainstalowania pakietu Microsoft Office na każdym komputerze, na którym uruchamiany jest kod źródłowy, w tym na serwerach produkcyjnych. Powoduje to wzrost kosztów licencji i zwiększa złożoność wdrożenia.
Zarządzanie pamięcią: Obiekty COM muszą być wyraźnie zwalniane za pomocą funkcji Marshal.ReleaseComObject(). Brak nawet jednego obiektu powoduje zawieszenie się procesów Excela w pamięci, co zostało obszernie udokumentówane na Stack Overflow. Rozważmy pamięć podręczną pivot.
Ograniczenia platformy: To rozwiązanie działa wyłącznie w systemie Windows z zainstalowanym pakietem Office. Może to działać niezwykle wolno i prowadzić do wycieków pamięci. Brak obsługi systemów Linux, macOS, kontenerów Docker oraz platform chmurowych, takich jak Azure Functions. To poważnie ogranicza opcje wdrażania i uniemożliwia korzystanie z nowoczesnych platform do orkiestracji kontenerów.
Problemy z wydajnością: Uruchamianie instancji aplikacji Excel jest powolne i wymaga dużych zasobów, zwłaszcza w przypadku przetwarzania po stronie serwera.
Kompatybilność wersji: Różne wersje pakietu Office mogą mieć różne interfejsy COM, co powoduje problemy z kompatybilnością w różnych środowiskach.
W jaki sposób IronXL tworzy tabelę przestawną programowo bez użycia Interop?
IronXL ma inne podejście do tworzenia tabel przestawnych, wykorzystując kod zarządzany bez zależności COM. Chociaż nie tworzy natywnych tabel przestawnych programu Excel, zapewnia zaawansowane możliwości agregacji, idealne do wdrożeń kontenerowych i architektur natywnych dla chmury. Optymalizacje wydajności biblioteki obejmują 40-krotny wzrost prędkości oraz zmniejszenie zużycia pamięci z 19,5 GB do poniżej 1 GB, co czyni ją idealną dla środowisk kontenerowych o ograniczonych zasobach.
Co sprawia, że to podejście jest nowoczesne w przypadku plików XLSX lub 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");
}
}
Imports IronXL
Imports System.Linq
Imports System.Data ' Keep this namespace
Imports static System.Data.DataTableExtensions ' Use 'using static' for DataTableExtensions
Module Program
Sub Main(args As String())
' Load Excel file - no Office required
Dim workbook As WorkBook = WorkBook.Load("SalesData.xlsx")
Dim dataSheet As WorkSheet = workbook.WorkSheets(0)
' Convert to DataTable for powerful manipulation
Dim dataTable = dataSheet.ToDataTable(True) ' true = use first row as column headers
' Create pivot-style aggregation using LINQ
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 pivot report worksheet
Dim pivotSheet As WorkSheet = workbook.CreateWorkSheet("PivotReport")
' Build cross-tabulation structure
Dim products = pivotData.Select(Function(p) p.Product).Distinct().OrderBy(Function(p) p)
Dim regions = pivotData.Select(Function(p) p.Region).Distinct().OrderBy(Function(r) r)
' Create headers
pivotSheet("A1").Value = "Product/Region"
Dim col As Integer = 2
For Each region In regions
pivotSheet($"{ChrW(AscW("A"c) + col - 1)}1").Value = region ' string
col += 1
Next
' Populate pivot data
Dim row As Integer = 2
For Each product In products
pivotSheet($"A{row}").Value = product
col = 2
For Each region In regions
Dim sales = pivotData _
.Where(Function(p) p.Product = product AndAlso p.Region = region) _
.Select(Function(p) p.TotalSales) _
.FirstOrDefault()
pivotSheet($"{ChrW(AscW("A"c) + col - 1)}{row}").Value = sales
col += 1
Next
row += 1
Next
' Add totals using Excel formulas
pivotSheet($"A{row}").Value = "Total" ' grand totals
For c As Integer = 2 To regions.Count() + 1
pivotSheet($"{ChrW(AscW("A"c) + c - 1)}{row}").Formula = $"=SUM({ChrW(AscW("A"c) + c - 1)}2:{ChrW(AscW("A"c) + c - 1)}{row - 1})"
Next
' Proceeding to apply formatting
Dim dataRange = pivotSheet($"B2:{ChrW(AscW("A"c) + regions.Count())}{row}")
dataRange.FormatString = "$#,##0.00"
workbook.SaveAs("PivotReport.xlsx")
End Sub
End Module
Oto jak tworzyć tabele przestawne w sposób przyjazny dla kontenerów. To podejście działa płynnie w kontenerach Docker, podach Kubernetes i funkcjach bezserwerowych bez żadnych zewnętrznych zależności. Całą aplikację można spakować do lekkiego obrazu kontenera, który działa wszędzie tam, gdzie obsługiwane jest środowisko .NET.
Jak wygląda wynik tabeli przestawnej?

Wynik pokazuje, w jaki sposób IronXL przekształca surowe dane sprzedażowe w ustrukturyzowany raport przestawny bez konieczności instalowania programu Excel, co czyni go idealnym rozwiązaniem do automatycznego raportowania w potokach CI/CD.
Jak tworzyć dynamiczne podsumowania za pomocą formuł IronXL?
W scenariuszach wymagających dynamicznych aktualizacji, podobnych do funkcji odświeżania tabeli przestawnej, IronXL może wykorzystać wbudowane formuły programu Excel. To podejście jest preferowane — dane są przetwarzane w znacznie bardziej nowoczesny i elegancki sposób. Kod jest łatwy do zrozumieniuiuiuiuia i skonfigurowania bez konieczności kontaktowania się z pomocą techniczną lub czytania instrukcji. Takie podejście jest szczególnie cenne w środowiskach kontenerowych, gdzie potrzebne są obliczenia oparte na formułach, które aktualizują się automatycznie.
W jaki sposób podsumowania oparte na formułach aktualizują się automatycznie?
// 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
Imports System.Data
Imports System.Linq
' Load the workbook
Dim workbook As WorkBook = WorkBook.Load(inputPath)
' Rename the first worksheet so formulas reference correctly
Dim dataSheet As WorkSheet = workbook.WorkSheets(0)
dataSheet.Name = "DataSheet"
' Convert worksheet to DataTable
Dim dataTable As DataTable = dataSheet.ToDataTable(True)
' Create new summary worksheet
Dim summarySheet As WorkSheet = workbook.CreateWorkSheet("DynamicSummary")
' Get unique product-region combinations
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)
' Add header row
summarySheet("A1").Value = "Product"
summarySheet("B1").Value = "Region"
summarySheet("C1").Value = "Total Sales"
summarySheet("D1").Value = "Count"
' Populate rows with formulas
Dim rowIndex As Integer = 2
For Each 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 += 1
Next
' 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
Formuły te utrzymują aktywne połączenia z danymi źródłowymi, automatycznie aktualizując się w przypadku zmian w arkuszu danych — podobnie jak w przypadku odświeżania tabeli przestawnej, ale bez zależności Interop. Takie podejście jest idealne dla mikrousług w kontenerach, które muszą generować dynamiczne raporty bez zewnętrznych zależności.
Jakich wyników można oczekiwać od dynamicznych streszczeń?
Jeśli zastosujemy ten kod do przykładowego pliku Excel z poprzedniego przykładu, otrzymamy następujący wynik:

Podejście oparte na dynamicznym podsumowaniu zapewnia obliczenia w czasie rzeczywistym, które aktualizują się automatycznie wraz ze zmianami danych źródłowych, co czyni je idealnym rozwiązaniem dla zautomatyzowanych procesów raportowania w środowiskach kontenerowych. Eliminuje to potrzebę planowego odświeżania tabel przestawnych i działa płynnie w aplikacjach .NET MAUI i Blazor.
Jak porównać C# Interop z IronXL w kontekście tabel przestawnych?
|
Aspect |
C# Interop |
IronXL |
|---|---|---|
|
Wymagane biuro |
Tak – pełna instalacja |
Nie – biblioteka samodzielna |
|
Obsługa platform |
Tylko dla systemu Windows |
Windows, Linux, macOS, Docker |
|
Zarządzanie pamięcią |
Wymagane ręczne czyszczenie COM |
Automatyczne zbieranie śmieći w .NET |
|
Wdrożenie |
Złożone — licencjonowanie pakietu Office |
Proste — pojedyncza biblioteka DLL |
|
Wydajność |
Powolne uruchamianie programu Excel |
Szybkość — obliczenia w pamięci |
|
Kompatybilność z chmurą |
Nie – ograniczenia platformy Azure |
Tak — obsługa funkcji Azure |
|
Natywne tabele przestawne |
Tak |
Nie – alternatywne rozwiązania agregacyjne |
|
Szybkość rozwoju |
Powolność – złożoność COM |
Szybki – intuicyjny interfejs API |
|
Obsługa kontenerów |
Nie – nie można konteneryzować pakietu Office |
Tak – gotowe do użycia w Dockerze |
|
Kontrola poprawności |
Trudne — monitorowanie procesów COM |
Łatwe - Monitorowanie .NET Standard |
Z perspektywy DevOps architektura IronXL zapewnia znaczące korzyści w nowoczesnych scenariuszach wdrażania. Możliwość uruchamiania biblioteki w kontenerach bez zewnętrznych zależności oznacza, że można tworzyć lekkie obrazy Docker, które szybko się wdrażają i efektywnie skalują. Kontrole stanu można wdrożyć przy użyciu standardowych wzorców .NET Standard, a funkcje bezpieczeństwa biblioteki obejmują certyfikację DigiCert oraz brak interfejsów COM, co ogranicza wektory ataku.
Które podejście wybrać?
Kiedy należy używać C# Interop?
Wybierz C# Interop, gdy:
- Niezbędne jest zachowanie natywnych obiektów tabel przestawnych programu Excel
- Praca wyłącznie w systemie Windows z zainstalowanym pakietem Office
- Wdrażanie wyłącznie na systemach stacjonarnych, którymi zarządzasz
- Istniejący kod legacy opiera się na Interop
- Korzystanie ze starszych wersji .NET Framework
- Nie planujesz konteneryzacji ani przejścia do chmury
Kiedy IronXL zapewnia lepsze wyniki?
Wybierz IronXL, gdy:
- Wdrażanie na serwerach lub w środowiskach chmurowych (Azure, AWS)
- Tworzenie aplikacji wielopłatformowych działających w kontenerach
- Wymagająca lepszej wydajności dzięki 40-krotnemu przyspieszeniu
- Unikanie kosztów licencji Office i złożoności wdrożenia
- Potrzeba prostszego kodu z automatycznym Zarządzaniem kluczami licencyjnymi
- Obsługa systemów Mac, iOS, Android i Linux
- Praca w nowoczesnym środowisku .NET Core i .NET 5-10
- Programowe konfigurowanie pól tabeli przestawnej
- Tworzenie mikrousług eksportujących dane do różnych formatów
- Wdrażanie automatycznego raportowania w potokach CI/CD
- Tworzenie punktów końcowych kontroli stanu dla orkiestracji kontenerów
- Konwersja między różnymi formatami arkuszy kalkulacyjnych
Czego dowiedzieliśmy się o tworzeniu tabel przestawnych w języku C#?
Chociaż C# Excel Interop umożliwia tworzenie natywnych tabel przestawnych, ograniczenia związane z wdrażaniem oraz złożoność tej technologii sprawiają, że staje się ona coraz mniej praktyczna w nowoczesnych aplikacjach, zwłaszcza w środowiskach kontenerowych. IronXL zapewnia potężne alternatywy dzięki agregacji danych i podsumowaniom opartym na formułach, eliminując zależność od pakietu Office przy jednoczesnym zachowaniu możliwości analitycznych.
Dla programistów i inżynierów poszukujących alternatyw dla tworzenia tabel przestawnych bez Interop, IronXL oferuje doskonałe rozwiązanie, które pozwala uniknąć komplikacji związanych z COM, działa na wszystkich platformach i upraszcza wdrażanie. Brak natywnych obiektów tabeli krzyżowej rekompensuje większa elastyczność, lepsza wydajność oraz brak konieczności posiadania licencji na pakiet Office. Co najważniejsze dla zespołów DevOps, IronXL umożliwia prawdziwą infrastrukturę jako kod dzięki wdrożeniom kontenerowym, automatycznemu skalowaniu i płynnej integracji z nowoczesnymi potokami CI/CD.
Kompleksowy zestaw funkcji biblioteki obejmuje formatowanie warunkówe, stylizację komórek, obsługę formuł oraz walidację danych, co czyni ją kompletnym rozwiązaniem do automatyzacji Excela w nowoczesnych aplikacjach .NET. Niezależnie od tego, czy pracujesz z plikami CSV, zarządzasz arkuszami kalkulacyjnymi, czy wdrażasz złożone transformacje danych, IronXL zapewnia spójny, przyjazny dla wdrożeń interfejs API.
Chcesz zmodernizować automatyzację w Excelu i tworzyć kod tabel przestawnych w nowoczesnym języku C#?
IronXL można wdrożyć w aplikacjach C# w ciągu kilku sekund za pomocą menedżera pakietów NuGet. Wypróbuj bezpłatną wersję próbną, aby wyeliminować zależności Interop w swoich aplikacjach produkcyjnych i uprościć wdrażanie kontenerów.
Często Zadawane Pytania
Czym jest tabela przestawna w programie Excel?
Tabela przestawna w programie Excel to potężne narzędzie służące do podsumowywania, analizowania, przeglądania i prezentowania danych. Pozwala użytkownikom przekształcać kolumny w wiersze i odwrotnie, umożliwiając dynamiczną analizę danych.
Dlaczego warto używać IronXL do tworzenia tabel przestawnych Excel w języku C#?
IronXL pozwala programistom tworzyć tabele przestawne Excel w języku C# bez konieczności korzystania z Office Interop, co eliminuje potrzebę instalacji programu Excel i zmniejsza zależności, czyniąc go nowoczesnym i wydajnym wyborem.
Jak IronXL wypada w porównaniu z C# Interop w zakresie operacji w programie Excel?
IronXL oferuje bardziej usprawnione i niezależne podejście w porównaniu z C# Interop, które wymaga instalacji pakietu Office. IronXL upraszcza tworzenie tabel przestawnych i innych operacji w programie Excel bez komplikacji związanych z Interop.
Czy mogę generować tabele przestawne bez zainstalowanego programu Excel?
Tak, korzystając z IronXL, można generować tabele przestawne w aplikacjach C# bez konieczności instalowania programu Excel, ponieważ działa on niezależnie od pakietu Microsoft Office.
Czy IronXL nadaje się do dużych zbiorów danych?
IronXL został zaprojektowany do wydajnej obsługi dużych zbiorów danych, dzięki czemu nadaje się do zastosowań wymagających solidnej manipulacji danymi i generowania tabel przestawnych.
Jakie są zalety korzystania z IronXL w porównaniu z tradycyjnymi metodami?
IronXL stanowi nowoczesną, niezależną od innych bibliotek alternatywę dla tradycyjnych metod, takich jak C# Interop, oferując łatwość użytkowania, elastyczność oraz obsługę złożonych operacji na danych bez konieczności instalowania programu Excel.
Czy muszę nauczyć się języka VBA, aby korzystać z IronXL do tworzenia tabel przestawnych?
Nie, IronXL pozwala programistom pracować bezpośrednio w języku C# w celu tworzenia tabel przestawnych i zarządzania nimi, eliminując konieczność nauki języka VBA lub innych języków programowania specyficznych dla programu Excel.




