フッターコンテンツにスキップ
IRONXLの使用

C#を使用してExcelでピボット・テーブルを作成する方法 Interop vs IronXL

Excel でピボット・テーブルをプログラムで生成するには、Office に依存する C# Interop か、独立して動作する IronXL のような最新のライブラリが必要です。 このチュートリアルでは、両方のアプローチを示し、開発者が従来のInterop方法よりもIronXLを選ぶ理由を強調します。

この記事では、ピボットテーブルとグループを編集、作成、設計、計算し、自動分析とエラー処理を行う方法を学びます。

Excelのピボットテーブルとは何ですか?

ピボットテーブルは、Excelに追加できる最も強力なツールの1つです。 それは、大量のデータセットを要約する簡単でシンプルな方法です。 したがって、ピボットテーブルを使用すると、数値データを簡単に表示、理解し、分析することができます。 ピボットテーブルは、Excelだけでなく、Google Sheets、Apple Numbers、CSVエクスポートなどの他のプログラムでも利用できます。 これは、データを概観するためのソリューションを提供するもので、人々が自分の情報を意味のある方法で見ることができるようにするデータコンソールとして機能し、現実にリンクします。

ピボットテーブルを間違った方法で作成し、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;

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

この Interop の例では、Product を行に、Region を列に、Sales をデータ領域に合計した Excel ネイティブのピボット・テーブルを作成します。 機能的ではありますが、このアプローチではMicrosoft Officeのインストールと注意深いCOMオブジェクトの管理が必要です。 最新の開発でこのアプローチを使用しない理由については、Microsoftのドキュメントを参照してください。

C#相互運用はどのような問題を引き起こしますか?

Interopアプローチは重大な課題をいくつか提示します:

悲しいことに、Stack Overflowや他のプログラミングウェブサイトは、2000年代初頭のアイデアにロックされたスレッドで時間に閉じ込められているため、それを推奨し続けている。

デプロイメント依存:本番サーバーを含め、ソースコードを実行しているすべてのマシンにMicrosoft Officeのインストールが必要です。 これにより、ライセンスコストとデプロイメントの複雑さが加わります。

メモリ管理:COM オブジェクトは、Marshal.ReleaseComObject()を使用して明示的に解放する必要があります。 一つでもオブジェクトを見逃すと、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年にはこうしてピボットテーブルを作成します。

出力

How to Create Pivot Table in Excel Using C# Interop vs IronXL: Image 1 - 元のExcelファイルと作成したピボットテーブルの比較。

IronXLの式を使用して動的なサマリーを作成する方法?

ピボットテーブルの作成、ピボットテーブルのリフレッシュ機能の計算など、動的な更新を必要とするシナリオでは、IronXLはExcelの組み込み数式を活用して回答を得ることができます。 一般的に、これは前の回答よりも望ましいです - あなたの記録は、はるかに近代的でエレガントな方法で処理され、コードで、人が簡単に理解することができます。 サポートに問い合わせたり、マニュアルを読んだりする必要がなく、セットアップが簡単であること。

// Load the workbook
WorkBook workbook = WorkBook.Load(inputPath);
// Rename the first worksheet so formulas reference correctly
WorkSheet dataSheet = workbook.WorkSheets[0];
dataSheet.Name = "DataSheet";
// Convert worksheet to DataTable
DataTable dataTable = dataSheet.ToDataTable(true);
// Create new summary worksheet
WorkSheet summarySheet = workbook.CreateWorkSheet("DynamicSummary");
// Get unique product-region combinations
var uniqueCombos = dataTable.AsEnumerable()
    .Select(row => new {
        Product = row["Product"].ToString(),
        Region = row["Region"].ToString()
    })
    .Distinct()
    .OrderBy(x => x.Product)
    .ThenBy(x => x.Region);
// Add header row
summarySheet["A1"].Value = "Product";
summarySheet["B1"].Value = "Region";
summarySheet["C1"].Value = "Total Sales";
summarySheet["D1"].Value = "Count";
// Populate rows with formulas
int rowIndex = 2;
foreach (var combo in uniqueCombos)
{
    summarySheet[$"A{rowIndex}"].Value = combo.Product;
    summarySheet[$"B{rowIndex}"].Value = combo.Region;
    // Adjust column references if your Sales column is C (not D)
    summarySheet[$"C{rowIndex}"].Formula =
        $"=SUMIFS(DataSheet!C:C,DataSheet!A:A,\"{combo.Product}\",DataSheet!B:B,\"{combo.Region}\")";
    summarySheet[$"D{rowIndex}"].Formula =
        $"=COUNTIFS(DataSheet!A:A,\"{combo.Product}\",DataSheet!B:B,\"{combo.Region}\")";
    rowIndex++;
}
// Optional: add total row
summarySheet[$"A{rowIndex}"].Value = "Total";
summarySheet[$"C{rowIndex}"].Formula = $"=SUM(C2:C{rowIndex - 1})";
summarySheet[$"D{rowIndex}"].Formula = $"=SUM(D2:D{rowIndex - 1})";
// Save output file
workbook.SaveAs(outputPath);  //filename
// Load the workbook
WorkBook workbook = WorkBook.Load(inputPath);
// Rename the first worksheet so formulas reference correctly
WorkSheet dataSheet = workbook.WorkSheets[0];
dataSheet.Name = "DataSheet";
// Convert worksheet to DataTable
DataTable dataTable = dataSheet.ToDataTable(true);
// Create new summary worksheet
WorkSheet summarySheet = workbook.CreateWorkSheet("DynamicSummary");
// Get unique product-region combinations
var uniqueCombos = dataTable.AsEnumerable()
    .Select(row => new {
        Product = row["Product"].ToString(),
        Region = row["Region"].ToString()
    })
    .Distinct()
    .OrderBy(x => x.Product)
    .ThenBy(x => x.Region);
// Add header row
summarySheet["A1"].Value = "Product";
summarySheet["B1"].Value = "Region";
summarySheet["C1"].Value = "Total Sales";
summarySheet["D1"].Value = "Count";
// Populate rows with formulas
int rowIndex = 2;
foreach (var combo in uniqueCombos)
{
    summarySheet[$"A{rowIndex}"].Value = combo.Product;
    summarySheet[$"B{rowIndex}"].Value = combo.Region;
    // Adjust column references if your Sales column is C (not D)
    summarySheet[$"C{rowIndex}"].Formula =
        $"=SUMIFS(DataSheet!C:C,DataSheet!A:A,\"{combo.Product}\",DataSheet!B:B,\"{combo.Region}\")";
    summarySheet[$"D{rowIndex}"].Formula =
        $"=COUNTIFS(DataSheet!A:A,\"{combo.Product}\",DataSheet!B:B,\"{combo.Region}\")";
    rowIndex++;
}
// Optional: add total row
summarySheet[$"A{rowIndex}"].Value = "Total";
summarySheet[$"C{rowIndex}"].Formula = $"=SUM(C2:C{rowIndex - 1})";
summarySheet[$"D{rowIndex}"].Formula = $"=SUM(D2:D{rowIndex - 1})";
// Save output file
workbook.SaveAs(outputPath);  //filename
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

これらの数式は、ソースデータへのライブ接続を維持し、データシートが変更されると自動的に更新されます - ピボットテーブルのリフレッシュ動作と似ていますが、Interopの依存関係はありません。

このコードを先ほどの例のExcelファイル(XLS / XLSX)に適用すると、このようなフィールドがページに出力されます:

How to Create Pivot Table in Excel Using C# Interop vs IronXL: Image 2 - Note: C# Dynamic summaries output seen in location context.

ピボットテーブルのC# InteropとIronXLを比較する

アスペクト C#相互運用 IronXL
必要なオフィス はい - フルインストール スタンドアロンライブラリ
プラットフォームサポート Windowsのみ Windows、Linux、macOS、Docker
メモリ管理 手作業によるCOMのクリーンアップが必要 .NET 自動ガベージコレクション
デプロイメント 複雑 - オフィスライセンス シンプル - 単一DLL
パフォーマンス 遅い - Excelプロセス起動 高速 - インメモリ計算
クラウド対応 いいえ - Azureの制限 はい - Azure Functionsのサポート
ネイティブピボットテーブル はい いいえ - 集計の代替
開発スピード 遅い - COM の複雑さ 高速で直感的なAPI

どのアプローチを選ぶべきか?

C# Interopを選択する場合:

  • ネイティブのExcelピボットテーブルオブジェクトが絶対必要です。
  • 対象マシンにOfficeをインストールし、Windowsのみで作業すること。
  • 自分が管理するデスクトップシステムへのデプロイのみ
  • 既存のレガシーコードがInteropに依存している
  • レガシー.NET Frameworkバージョンの使用

IronXLをお選びください:

  • サーバーまたはクラウド環境とサービス(Azure、AWS ...)へのデプロイ
  • クロスプラットフォームアプリケーションの構築
  • パフォーマンスと信頼性の向上
  • Officeライセンスコストの回避
  • よりシンプルで保守性の高いコードが必要
  • Mac、iOS、Android、Linuxシステムに対応
  • 最新の.NET Framework Coreおよび.NET 5,6,7,8,9,10で動作すること。
  • ピボット・テーブルの各フィールドの設定を、データ範囲からプログラムで構成するために、開発コンソール/IDE にフル・アクセスできるようにしてください。

結論

C# Excel Interopはネイティブピボットテーブルを開発できますが、そのデプロイメント制限と複雑さは、現代のアプリケーションにはますます不向きになっています。 IronXLは、データ集計と数式ベースのサマリーによって強力な代替手段を提供し、分析機能を維持しながらOffice依存を排除します。 参考になりましたら、投票、コメント、購読をお願いします。

Interopなしでピボットテーブルを開発する代替オプションをお探しの開発者にとって、IronXLはCOMの複雑さを回避し、すべてのプラットフォームで動作し、デプロイを簡素化する優れたパスを提供します。 ネイティブピボットオブジェクトがないことのトレードオフは、より柔軟性が高く、パフォーマンスが向上し、Officeライセンス要件が排除されることで相殺されます。

今IronXLを始めましょう。
green arrow pointer

Excelの自動化をモダナイズし、現代的なC#で自分のピボットテーブルコードを作成する準備ができていますか?

IronXLはNuGetパッケージ・マネージャーを通して、あなたのC#アプリケーションに数秒で実装することができます。 無料トライアルをお試しください、またはXLライセンスをご購入ください

カーティス・チャウ
テクニカルライター

Curtis Chauは、カールトン大学でコンピュータサイエンスの学士号を取得し、Node.js、TypeScript、JavaScript、およびReactに精通したフロントエンド開発を専門としています。直感的で美しいユーザーインターフェースを作成することに情熱を持ち、Curtisは現代のフレームワークを用いた開発や、構造の良い視覚的に魅力的なマニュアルの作成を楽しんでいます。

開発以外にも、CurtisはIoT(Internet of Things)への強い関心を持ち、ハードウェアとソフトウェアの統合方法を模索しています。余暇には、ゲームをしたりDiscordボットを作成したりして、技術に対する愛情と創造性を組み合わせています。