IRONXLの使用 IronXLを使って C# で Excel のピボットテーブルを作成する方法 カーティス・チャウ 更新日:2026年2月27日 IronXL をダウンロード NuGet ダウンロード DLL ダウンロード 無料トライアル LLM向けのコピー LLM向けのコピー LLM 用の Markdown としてページをコピーする ChatGPTで開く このページについてChatGPTに質問する ジェミニで開く このページについてGeminiに問い合わせる Grokで開く このページについてGrokに質問する 困惑の中で開く このページについてPerplexityに問い合わせる 共有する Facebook で共有 Xでシェア(Twitter) LinkedIn で共有 URLをコピー 記事をメールで送る Excelでピボットテーブルをプログラムで生成するには、Officeの依存関係を持つC# 相互運用性を使用するか、 IronXLのような独立して動作する最新のライブラリを使用する必要があります。このチュートリアルでは、両方のアプローチを実演し、最新の方法の方が優れている理由を具体的に示します。 サーバーサイドまたはクロスプラットフォーム for .NETコードでピボットスタイルのレポートを作成することは、これまで非常に困難でした。 従来のCOM相互運用方式では、Officeが完全にインストールされたWindowsマシンに縛られ、COMクリーンアップ呼び出しを1回でも見落とすとメモリリークが発生し、LinuxやDockerコンテナにデプロイしようとした途端に機能しなくなります。 現代的な代替手段である、 IronXLとLINQを使った集計ロジックの記述は、 .NETが動作する環境であればどこでも実行でき、Officeライセンスも不要で、簡潔で読みやすいコードが得られます。 このガイドでは、両方のテクニックについて詳しく解説します。 生のInteropアプローチを見て、それがなぜ脆弱なのかを正確に理解し、その後、 IronXLを使用してC#で同じピボットスタイルのサマリーシートを作成します。 また、Excelの数式を使用して、実際のピボットテーブルの更新のように動作する、リアルタイムで自動更新される集計表を作成する方法もご紹介します。 Excelのピボットテーブルとは何ですか? ピボットテーブルは、表計算ソフトにおける最も強力な分析ツールの1つです。 行をグループ化し、値を集計し、結果をクロス集計レイアウトに投影することで、大規模なデータセットを要約します。しかも、数式を一つも手動で記述する必要はありません。 Microsoftの公式ピボットテーブルに関するドキュメントには、Excel内部におけるこの機能の詳細な概要が記載されています。 ピボットテーブルは、Microsoft Excel、Google Sheets、Apple Numbers、その他ほとんどの表計算ソフトに搭載されています。 基本的な考え方は常に同じです。行フィールド、列フィールド、値フィールドを定義すると、ツールがサマリーマトリックスを自動的に作成します。 基となるデータが変更された場合、ピボットテーブルを更新すると、集計結果が自動的に更新されます。 C#のサーバーサイドコードでは、大きく分けて2つの選択肢があります。 C# 相互運用性 -- COM を介して実行中の Excel プロセスを自動化し、XLSX ファイル内にネイティブのピボットテーブル オブジェクトを作成します。 IronXLとLINQ集計-- ワークブックをメモリに読み込み、マネージド.NETコードで同じ集計を計算し、結果を新しいワークシートに書き込みます。 どちらの選択肢も有用な出力を生成します。 しかし、現代の導入環境で確実に動作するものは、そのうちの1つだけです。 C# 相互運用性を使用してピボットテーブルを作成するにはどうすればよいですか? C# Excel Interop を使用すると、COM オートメーションを介して Excel のネイティブなピボットテーブル機能に直接アクセスできます。 Excel.Application オブジェクトを作成し、ワークブックを開き、データ範囲を指すピボットキャッシュを定義し、行フィールド、列フィールド、およびデータフィールドを構成します。 Interopピボットテーブルコードの設定方法 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) $vbLabelText $csharpLabel この Interop の例では、Product を行に、Region を列に、Sales をデータ領域に合計した 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 SHELL サーバー、コンテナ、開発マシンにOfficeをインストールする必要はありません。IronXLは、XLSX、XLS、CSVファイルをすべてマネージド.NETメモリ内で読み書きします。 C#相互運用はどのような問題を引き起こしますか? 相互運用性(Interop)のアプローチには、実際の導入段階で急速に複雑化するいくつかの重大な課題が存在する。 Stack Overflowなどのプログラミング関連サイトが依然としてそれを推奨しているのは、多くのスレッドが2000年代初頭に書かれ、その後ロックされているため、アドバイスが時代遅れになっているからだ。 デプロイメントの依存関係- コードを実行するすべてのマシン(本番サーバーやCI/CDビルドエージェントを含む)には、ライセンス版のMicrosoft Officeがインストールされている必要があります。 これはライセンス費用と導入の複雑さを増大させるが、最新の代替手段を用いれば完全に回避できる。 メモリ管理の負担-- COM オブジェクトは Marshal.ReleaseComObject() を使用して明示的に解放する必要があります。 Stack Overflow で詳しく解説されているように、オブジェクトが 1 つでも欠落すると、Excel プロセスがメモリに永久にハングアップします。 長時間稼働するサービスやASP.NET Webアプリケーションでは、これは重大なリソースリークとなる。 プラットフォームの制限事項- Interopは、OfficeがインストールされているWindowsでのみ動作します。 Linux、macOS、Dockerコンテナ、またはAzure FunctionsやAWS Lambdaなどのサーバーレスプラットフォームでは実行できません。 これは、最新のクラウドネイティブアーキテクチャを完全に阻害します。 パフォーマンス上のボトルネック――Excelアプリケーションの起動は時間がかかり、リソースを大量に消費します。数十、数百ものレポートを生成する必要があるサーバーサイドのバッチ処理では、この起動時のオーバーヘッドが深刻なスループットの制約となります。 バージョン互換性の脆弱性― Office のバージョンによって、公開される COM インターフェイスがわずかに異なる。 Office 2019 で動作するコードが、Office 2016 や Microsoft 365 では異なる動作をする可能性があり、展開時にバージョンを固定する方法はありません。 MicrosoftのOffice相互運用アセンブリに関するドキュメントには、これらのバージョン管理上の制約が既知の制限事項として記載されています。 CI/CDの非互換性― ほとんどの継続的インテグレーション環境にはOfficeがインストールされていません。 ピボットテーブル生成コードをテストするには、COMレイヤー全体をモックするか、ライセンス付きのOfficeがインストールされた特別なWindowsエージェントを維持する必要があります。 .NET 6以降( .NET 10を含む)を対象とする新規.NETアプリケーションの場合、これらの制約により、相互運用性(Interop)は現実的な選択肢とは言えません。 IronXLはInteropを使用せずにピボットテーブルを作成するにはどうすればよいですか? 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") $vbLabelText $csharpLabel これは、Excelのネイティブなピボットテーブルから得られるものと同じクロス集計結果を生成します。 セル、数式、書式文字列のすべてをプログラムで完全に制御でき、クリーンアップする必要のあるCOMオブジェクトもありません。 今IronXLを始めましょう。 無料で始める Excelの数式を使って動的な集計表を作成するにはどうすればよいですか? 要約シートを常に最新の状態に保ち、ソースデータが変更されるたびに自動的に再計算を行いたい場合、 IronXLExcelの数式文字列をセルに直接書き込むことができます。 これにより、相互運用性への依存なしに、ピボットテーブルの自動更新と同様の動作を実現できます。 ここでの重要な機能は 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) $vbLabelText $csharpLabel これらの数式は、ソースデータとのリアルタイム接続を維持します。 誰かが DataSheet の値を更新すると、Excel は次回のオープン時または更新時に集計を自動的に再計算します。これにより、COM による自動化を必要とせずに、ネイティブのピボットテーブルの更新サイクルと同じ動作が実現されます。 これを前の例で使用したのと同じ販売データワークブックに適用すると、出力は次のようになります。 この数式ベースのアプローチでは、 IronXLのセル書式設定APIを使用して、集計セルに条件付き書式、データバー、またはアイコンセットを追加することもできます。これにより、ExcelのUIで手作業を行うことなく、レポートを視覚的に分かりやすくすることができます。 2 つのアプローチを比較するとどうなりますか? アプローチを選択する前に、それぞれのトレードオフを比較検討することが役立ちます。以下の表は、 .NET本番環境開発において最も重要な要素を網羅しています。 C# 相互運用性とIronXLによるピボットテーブル生成の比較 アスペクト C# 相互運用性 IronXL オフィス勤務必須 はい、すべてのマシンに完全インストールします。 いいえ -- スタンドアロンのNuGetパッケージ プラットフォームのサポート Windowsのみ Windows、Linux、macOS、Docker メモリ管理 手動のCOMクリーンアップが必要 自動 .NET ガベージコレクション 展開の複雑さ 高レベル - オフィスライセンスとインストール 低 - 単一のDLL参照 パフォーマンス 遅い - Excel プロセスの起動オーバーヘッド 高速 - インメモリ計算 クラウド対応 いいえ -- Azure Functions、AWS Lambdaではブロックされています はい、あらゆるクラウドプラットフォームで動作します。 ネイティブピボットテーブルオブジェクト はい -- 完全な Excel ピボット テーブル いいえ -- 集計に基づく同等のもの 開発速度 遅い - COMの複雑さ 高速で流暢なマネージドAPI IronWordを.NETプロジェクトにインストールし、Windows環境でWordドキュメントを作成・編集します。 限定的 - COM バインディングの問題 フル -- 最新 for .NETをターゲットとしています Interopが明確な優位性を持つ唯一のシナリオは、XLSXファイルに埋め込まれたネイティブのExcelピボットテーブルオブジェクトが特に必要な場合です。たとえば、下流のユーザーがExcelの組み込みピボットテーブルUIを使用して操作する必要がある場合(ドリルダウン、フィルタリング、集計関数の対話的な変更など)です。 その他のあらゆるシナリオにおいて、IronXLのアプローチは、記述が速く、展開が容易で、移植性もはるかに高い。 どのアプローチを選ぶべきか? 最適な選択は、導入環境とユーザーのニーズによって異なります。 C# 相互運用性 を選択するのは、以下の条件を満たす場合に限る。 ユーザーは、Excel UI 内で対話的に操作できるネイティブの Excel ピボットテーブルオブジェクトを必要としています。 あなたは、すべてのマシンにOfficeがインストールされていることが保証されている、閉鎖的なWindowsデスクトップ環境をターゲットにしています。 既にInteropに依存しているレガシーな.NET Frameworkコードを保守しており、現時点では書き換えは正当化されない。 IronXLを選択する場合: サーバー、コンテナ、または任意のクラウド環境(Azure、AWS、GCP)にデプロイします。 Linux、macOS、またはDockerベースのビルドに対応したクロスプラットフォームサポートが必要です。 COMライフサイクル管理なしで、クリーンで保守しやすいコードが欲しい。 .NET 5、6、7、8、9、または10をターゲットにしています サーバーインフラストラクチャにおけるMicrosoft Officeのライセンス料を回避したい ファイルごとのExcelプロセス起動なしに、多数のワークブックを高速にバッチ処理する必要があります。 現代 for .NETアプリケーションの大部分にとって、 IronXLは実用的な選択肢です。集計ベースの出力は、実際のレポート作成要件をすべて満たし、その見返りとして完全な移植性も得られます。 セル書式設定、数式評価、データ検証、グラフ生成など、その他の機能については、 IronXLのドキュメントおよびIronXLのサンプルライブラリを参照してください。 IronXLを今日から使い始めるにはどうすればいいですか? IronXLライブラリはNuGetで入手可能で、 .NETプロジェクトへの追加は1分もかかりません。 Install-Package IronXl.Excel dotnet add package IronXl.Excel Install-Package IronXl.Excel dotnet add package IronXl.Excel SHELL インストール後は、既存のワークブックを読み込んだり、新しいワークブックを作成したり、セルの値を読み書きしたり、数式を適用したり、書式文字列を設定したり、XLSX形式で保存したりすることができます。これらすべてを、分かりやすく文書化されたAPIで行うことができます。 COMもOfficeへの依存関係もなく、特別なサーバー設定も不要です。 API の完全なドキュメントについては、 IronXL入門ガイド、 C# Excel 相互運用移行ガイド、およびIronXLコード例を参照してください。 IronXLと他のExcelライブラリとの比較については、 IronXL比較記事をご覧ください。 無料トライアルライセンスを利用すれば、購入を決める前に自分のプロジェクトで全機能をテストできます。 本番環境への導入準備が整ったら、商用版のIronXLライセンスをご購入いただくと、試用版のウォーターマークが削除され、優先サポートが受けられます。 無料トライアルから始めて、クロスプラットフォームのExcel自動化がどれほど簡単になるか実感してください。 よくある質問 Interop なしで C# を使用して Excel でピボット テーブルを作成するにはどうすればよいですか? Office の依存関係に依存せずに強力なデータ操作機能を提供するIronXLを使用すると、相互運用性のない C# を使用して Excel でピボット テーブルを作成できます。 ピボット テーブルを生成するためにIronXLを使用する利点は何ですか? IronXL を使用すると、開発者は Excel Interop に依存せずにピボット テーブルを生成できるため、Office をインストールする必要がなくなり、展開の複雑さが軽減されます。 IronXLは.NETアプリケーションと互換性がありますか? はい、 IronXL は.NETアプリケーションと完全に互換性があり、ピボット テーブルの作成を含む Excel 操作用の使いやすい API を提供します。 IronXLではサーバーに Excel をインストールする必要がありますか? いいえ、 IronXLはサーバーにExcelをインストールする必要はありません。IronXLは独立して機能するため、サーバーサイドアプリケーションにシームレスに統合できます。 IronXLを使用して Excel のデータを操作できますか? はい、 IronXL は強力なデータ操作機能を提供しており、開発者はピボット テーブルの作成など、Excel データを作成、変更、分析できます。 開発者が従来の相互運用方法よりもIronXL を好むのはなぜでしょうか? 開発者は、Office への依存関係がなく、展開が簡単で、Excel 操作の機能が包括的であるため、従来の相互運用方法よりもIronXL を好む可能性があります。 IronXL はExcel データ操作にどのような機能を提供しますか? IronXL は、Excel Interop を必要とせずに、Excel ファイルの読み取りと書き込み、スプレッドシートの作成と編集、ピボット テーブルの生成などの機能を提供します。 カーティス・チャウ 今すぐエンジニアリングチームとチャット テクニカルライター Curtis Chauは、カールトン大学でコンピュータサイエンスの学士号を取得し、Node.js、TypeScript、JavaScript、およびReactに精通したフロントエンド開発を専門としています。直感的で美しいユーザーインターフェースを作成することに情熱を持ち、Curtisは現代のフレームワークを用いた開発や、構造の良い視覚的に魅力的なマニュアルの作成を楽しんでいます。開発以外にも、CurtisはIoT(Internet of Things)への強い関心を持ち、ハードウェアとソフトウェアの統合方法を模索しています。余暇には、ゲームをしたりDiscordボットを作成したりして、技術に対する愛情と創造性を組み合わせています。 関連する記事 更新日 2026年3月1日 ASP .NET C# で Excel ファイルをダウンロード: XLSX、CSV などにデータをエクスポート C#とIronXLを使用して、 ASP.NET CoreでExcelファイルをダウンロードします。MVCコントローラーからMemoryStreamとFile()を使用して、XLSX、CSV、XML形式でデータをエクスポートします。コード例も含まれています。 詳しく読む 更新日 2026年3月1日 IronXLを使用してBlazorで Excel ファイルをエクスポートする方法 IronXLを使用してBlazor Server アプリケーションから Excel にデータをエクスポートする方法を学びます。このガイドでは、プロジェクトのセットアップ、サービス設計、条件付き書式、複数シートのレポート、エラー処理について、完全な C# コード例とともに説明します。 詳しく読む 更新日 2026年2月27日 StreamReader の代わりに C# で Excel ファイルを読み取る方法 StreamReader が Excel ファイルを読み取れない理由と、 IronXL を使用して C# .NETのディスクまたはメモリ ストリームから XLSX および XLS ワークブックを読み込む方法について説明します。 詳しく読む IronXLを使って.NETで CSV ファイルを書き込む方法IronXLを使用して C# で GridVi...
更新日 2026年3月1日 ASP .NET C# で Excel ファイルをダウンロード: XLSX、CSV などにデータをエクスポート C#とIronXLを使用して、 ASP.NET CoreでExcelファイルをダウンロードします。MVCコントローラーからMemoryStreamとFile()を使用して、XLSX、CSV、XML形式でデータをエクスポートします。コード例も含まれています。 詳しく読む
更新日 2026年3月1日 IronXLを使用してBlazorで Excel ファイルをエクスポートする方法 IronXLを使用してBlazor Server アプリケーションから Excel にデータをエクスポートする方法を学びます。このガイドでは、プロジェクトのセットアップ、サービス設計、条件付き書式、複数シートのレポート、エラー処理について、完全な C# コード例とともに説明します。 詳しく読む
更新日 2026年2月27日 StreamReader の代わりに C# で Excel ファイルを読み取る方法 StreamReader が Excel ファイルを読み取れない理由と、 IronXL を使用して C# .NETのディスクまたはメモリ ストリームから XLSX および XLS ワークブックを読み込む方法について説明します。 詳しく読む