MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
ClosedXML - Excelファイルの操作のソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
ClosedXML - Excelファイルの操作
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == Closed XMLは、Microsoft Excelファイルの作成、読み取り、編集を簡単に行うことができるように設計されている。<br> <br> Closed XMLの主な特徴は、その使いやすさにある。<br> 開発者は、Excelファイルの操作をプログラム的に行う場合に、複雑なExcel Object Modelを直接扱う必要がない。<br> 代わりに、Closed XMLは直感的なAPIを提供しており、これにより開発者は効率的にExcelファイルを操作することができる。<br> <br> このライブラリを使用すると、新しいワークブックの作成、既存のワークブックの開封、ワークシートの追加や削除、セルの書式設定、数式の追加、グラフや画像の挿入等が可能である。<br> また、大量のデータを扱う際のパフォーマンスも考慮されており、メモリ効率の良い操作が可能である。<br> <br> Closed XMLの大きなメリットの1つは、Microsoft Office製品がインストールされていないPCでも動作することである。<br> これは、サーバ環境でのExcelファイル操作を可能にして、多くの企業システムで重要な機能となっている。<br> <br> セキュリティの観点からもClosed XMLは優れており、ファイルの操作がプログラム的に行われるため、マクロを含むExcelファイルによるセキュリティリスクを軽減できる。<br> <br> Closed XMLの使用例としては、財務レポートの自動生成、大量のデータの分析と視覚化、テンプレートベースの文書生成等が挙げられる。<br> これらのタスクは、ビジネスアプリケーションでよく必要とされるものである。<br> <br> このライブラリは活発に開発が続けられており、コミュニティからの支援も豊富なため、バグ修正や新機能の追加が定期的に行われており、最新のExcel機能にも対応している。<br> <br> ただし、Closed XMLにも制限はある。<br> 例えば、一部の高度なExcel機能はサポートされていない場合がある。<br> また、非常に大きなファイルを扱う場合には、メモリ使用量に注意が必要となる。<br> <br> Closed XMLはC#開発者にとって、Excelファイル操作を効率的に行うための強力なツールである。<br> その使いやすさ、豊富な機能、そして堅牢性により、多くのプロジェクトで重要な役割を果たしている。<br> <br><br> == Closed XMLとは == Open XML形式のExcelファイル(拡張子 : xlsx / xlsm)を読み書きするためのライブラリである。<br> MicrosoftのOpen XML SDKをラップし、Excelに特化することで使用しやすいライブラリになっている。<br> <br> Closed XMLのソースコードは、[https://github.com/ClosedXML/ClosedXML GitHub]で公開されている。<br> また、Closed XMLのライセンスは、MITライセンスである。<br> <br> ==== Closed XMLで可能なこと ==== * Open XML形式のExcelファイルの作成と編集 * セルデータの読み書き ** 数値、文字列、日付等の各種データ型 ** 複雑な数式の挿入と評価 * セルの書式設定 ** フォント ** 色 ** 罫線 ** 背景色 * ワークシートの操作 ** 追加、削除、名前変更、コピー ** 行や列の挿入、削除、非表示設定 * Excelの主要関数のサポート ** SUM, AVERAGE, VLOOKUP, IF等 * 大量データの高速処理 * テンプレートベースの文書生成 * 基本的な条件付き書式の適用 * ハイパーリンクの挿入と管理 * 印刷設定の調整(ページ設定、印刷範囲など) <br> ==== Closed XMLで実行できないこと ==== * Excelアプリケーションの直接操作 * マクロやVBAコードの実行・編集 * 複雑なグラフや図表の新規作成 * ピボットテーブルの新規作成や高度な編集 * 一部の高度なExcel機能 ** 複雑な条件付き書式 ** スパークライン ** 高度なデータ検証ルール * 外部データソースとの動的連携 * リアルタイムデータ更新 * Excelアドインの使用 * 複雑な画像操作や図形の作成 * コメントの詳細な管理や高度な編集 <br> <u>※注意</u><br> <u>上記は、Closed XMLは継続的に更新されているため、一部の機能は将来のバージョンで追加される可能性がある。</u><br> <br> ==== サポートされているプラットフォーム ==== 以下に示すプラットフォームサポートにより、Closed XMLは幅広い.NET環境で使用できる柔軟性の高いライブラリとなっている。<br> デスクトップアプリケーション、Webアプリケーション、モバイルアプリケーション、ゲーム開発まで、様々な種類のプロジェクトでExcelファイルの操作が可能である。<br> <br> * .NET Core 2.0以降 / .NET 5以降 * .NET Framework 4.5以降(4.0ではなく4.5からのサポート) * .NET Standard 2.0以降 <br> .NET Standard 2.0のサポートにより、以下のプラットフォームでも利用可能である。<br> * ASP.NET Core 2.0以降 * UWP(Universal Windows Platform)10.0.16299 (Fall Creators Update、1709) 以降 * Xamarin.iOS 10.14以降 * Xamarin.Android 8.0以降 * Xamarin.Mac 3.8以降 * Unity 2018.1以降 (ゲーム開発プラットフォームとしても利用可能) <br> <u>※注意</u><br> <u>プラットフォームのバージョンは、Closed XMLのバージョンによって変更される可能性がある。</u><br> <u>最新の対応状況は、Closed XMLの公式ドキュメントやGithubリポジトリで確認することを推奨する。</u><br> <u>また、一部の機能は、特定のプラットフォームでのみ利用可能な場合がある。</u><br> <br> Closed XMLのドキュメントは、[https://github.com/closedxml/closedxml/wiki ClosedXMLのGithub]で公開されている。<br> <br> Closed XMLの詳細を知りたい場合は、公式ドキュメントを参照すること。<br> <br><br> == Closed XMLのインストール == RiderまたはVisual StudioからNuGetを使用して、Closed XMLをインストールする。<br> * Riderの場合 *# [ツール]メインメニュー - [Nuget] - [ソリューション の Nuget パッケージを管理] (または、[<プロジェクト名> の Nuget パッケージを管理])を選択する。 *# メイン画面下部にある[パッケージ]タブから<u>ClosedXML</u>と入力して検索する。 *# メイン画面下部の右にある[+]ボタンを押下して、Closed XMLをインストールする。 <br> また、Closed XMLのGithubからソースコードをダウンロードして、ビルドおよびインストールすることもできる。<br> <br> Closed XMLをインストールする時、Open XML SDK等のいくつかの必要なパッケージが同時にインストールされる。<br> <br><br> == Excelファイルの作成 == 以下の例では、Excelファイルおよびシートを新規作成している。<br> <br> * Open XML形式のExcelファイルの作成と編集 *: new XLWorkbook()を使用して新しいワークブックを作成する。 *: workbook.Worksheets.Add("サンプルシート")でワークシートを追加する。 *: workbook.SaveAs("sample.xlsx")でファイルを保存する。 *: 既存のファイルを開く場合は、new XLWorkbook("サンプル.xlsx")を使用する。 <br> <syntaxhighlight lang="c#"> using System; using ClosedXML.Excel; const string ExcelFilePath = @"sample.xlsx"; // Excelファイルの作成 using (var workbook = new XLWorkbook()) { // ワークシートの追加 using (var worksheet = workbook.Worksheets.Add("サンプルシート")) { // 何らかの処理 // ワークブックを保存する workbook.SaveAs(ExcelFilePath); } Console.WriteLine(@"Excelファイルを保存しました"); // 保存したファイルを開いて編集 using (var workbook = new XLWorkbook("サンプル.xlsx")) { var worksheet = workbook.Worksheet(1); // 何らかの処理 // 変更を保存 workbook.Save(); } } </syntaxhighlight> <br><br> == セルデータの読み書き == 以下の例では、Open XML形式のExcelファイルにおいて、セルの値の設定、読み取り、数式の挿入、ファイルの保存と再編集等を行っている。<br> <br> * セルデータの読み書き ** 書き込み **: worksheet.Cell("A1").Value = "文字列" のように、Cellメソッドを使用してセルを指定して、Valueプロパティに値を代入する。 ** 読み取り **: var cellValue = worksheet.Cell("A2").Value のように、Valueプロパティを使用してセルの値を取得する。 <br> * 数値、文字列、日付等の各種データ型 ** 文字列 **: worksheet.Cell("A1").Value = "文字列" ** 数値 **: worksheet.Cell("A2").Value = 123 ** 日付 **: worksheet.Cell("A3").Value = DateTime.Now <br> * 複雑な数式の挿入と評価 ** 基本的な数式 **: worksheet.Cell("B1").FormulaA1 = "=SUM(A1:A3)" ** 条件付き数式 **: worksheet.Cell("C1").FormulaA1 = "=IF(A2>100, \"高い\", \"低い\")" <br> また、大量のデータを扱う場合は、パフォーマンスを考慮したアプローチ (例: バッチ処理) を検討する必要がある。<br> <br> <syntaxhighlight lang="c#"> using System; using ClosedXML.Excel; class Program { static void Main(string[] args) { // 新しいExcelワークブックを作成 using (var workbook = new XLWorkbook()) { var worksheet = workbook.Worksheets.Add("サンプルシート"); // セルデータの書き込み worksheet.Cell("A1").Value = "文字列"; worksheet.Cell("A2").Value = 123; // 数値 worksheet.Cell("A3").Value = DateTime.Now; // 日付 // 数式の挿入 worksheet.Cell("B1").FormulaA1 = "=SUM(A1:A3)"; // セルのスタイル設定 var cell = worksheet.Cell("A1"); cell.Style.Font.Bold = true; cell.Style.Fill.BackgroundColor = XLColor.LightBlue; // 複雑な数式の挿入 worksheet.Cell("C1").FormulaA1 = "=IF(A2>100, \"高い\", \"低い\")"; // 位置を指定してセルの値を読み取り var cellValue = worksheet.Cell("A2").Value; var cellA1 = worksheet.Cell("A1"); var cellA2 = worksheet.Cell(2, "A"); // 行番号と列名でも指定可能 var cellB1 = worksheet.Cell(3, 1); // 行番号と列番号でも指定可能 Console.WriteLine($"A2セルの値: {cellValue}"); Console.WriteLine($"A1セルの値: {cellA1.GetValue<strring>()}"); // 出力 : A1 = "文字列" Console.WriteLine($"A2セルの値: {cellA2.GetValue<int>()}"); // 出力 : A2 = 123 Console.WriteLine($"A3(値)セルの値: {cellA3.GetValue<DateTime>()}"); // 出力 : A3(値) = 30 Console.WriteLine($"B1(数式)セルの値: {cellB1.FormulaA1}"); // 出力 : B1(数式) = SUM(A1:A3) // ファイルを保存 workbook.SaveAs("サンプル.xlsx"); } // 保存したファイルを開いて編集 using (var workbook = new XLWorkbook("サンプル.xlsx")) { var worksheet = workbook.Worksheet(1); // 既存のデータを読み取り var a1Value = worksheet.Cell("A1").Value; Console.WriteLine($"A1セルの値: {a1Value}"); // 新しいデータを追加 worksheet.Cell("D1").Value = "新しいデータ"; // 変更を保存 workbook.Save(); } Console.WriteLine("処理が完了しました。"); } } </syntaxhighlight> <br><br> == セルの書式設定 == 以下の例では、セルにフォント、色、罫線、背景色等の様々な書式設定を適用している。<br> これらの設定を組み合わせたり、より複雑な条件付き書式を適用することができる。<br> <br> <syntaxhighlight lang="c#"> using System; using System.Drawing; using ClosedXML.Excel; class Program { static void Main(string[] args) { using (var workbook = new XLWorkbook()) { var worksheet = workbook.Worksheets.Add("書式設定サンプル"); // フォントの設定 var cell1 = worksheet.Cell("A1"); cell1.Value = "フォント設定"; cell1.Style.Font.FontName = "Arial"; cell1.Style.Font.FontSize = 14; cell1.Style.Font.Bold = true; cell1.Style.Font.Italic = true; cell1.Style.Font.Underline = XLFontUnderlineValues.Single; cell1.Style.Font.FontColor = XLColor.Red; // 背景色の設定 var cell2 = worksheet.Cell("A2"); cell2.Value = "背景色設定"; cell2.Style.Fill.BackgroundColor = XLColor.LightBlue; // 罫線の設定 var range = worksheet.Range("A3:C5"); range.Style.Border.OutsideBorder = XLBorderStyleValues.Thick; range.Style.Border.OutsideBorderColor = XLColor.Black; range.Style.Border.InsideBorder = XLBorderStyleValues.Thin; range.Style.Border.InsideBorderColor = XLColor.Gray; // セルの配置 var cell3 = worksheet.Cell("A3"); cell3.Value = "セル配置"; cell3.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center; cell3.Style.Alignment.Vertical = XLAlignmentVerticalValues.Center; // 数値書式の設定 var cell4 = worksheet.Cell("A6"); cell4.Value = 12345.6789; cell4.Style.NumberFormat.Format = "#,##0.00"; // 日付書式の設定 var cell5 = worksheet.Cell("A7"); cell5.Value = DateTime.Now; cell5.Style.DateFormat.Format = "yyyy年MM月dd日"; // セルの幅と高さの設定 worksheet.Column(1).Width = 20; // セルの幅 worksheet.Row(1).Height = 30; // セルの高さ // 条件付き書式の設定 (メソッドチェーンを使用しない場合) var range = worksheet.Range("A8:A10"); var conditionalFormat = range.AddConditionalFormat(); conditionalFormat.WhenGreaterThan(50); var fillFormat = conditionalFormat.Fill; fillFormat.SetBackgroundColor(XLColor.Green); var fontFormat = conditionalFormat.Font; fontFormat.SetFontColor(XLColor.White); worksheet.Cell("A8").Value = 30; worksheet.Cell("A9").Value = 60; worksheet.Cell("A10").Value = 90; // 条件付き書式の設定 (メソッドチェーンを使用する場合) var conditionalFormat = worksheet.Range("A8:A10").AddConditionalFormat(); conditionalFormat.WhenGreaterThan(50) .Fill.SetBackgroundColor(XLColor.Green) .Font.SetFontColor(XLColor.White); worksheet.Cell("A8").Value = 30; worksheet.Cell("A9").Value = 60; worksheet.Cell("A10").Value = 90; // ファイルを保存 workbook.SaveAs("書式設定サンプル.xlsx"); } Console.WriteLine("書式設定サンプルファイルを作成"); } } </syntaxhighlight> <br><br> == ワークシートの操作 == 以下の例では、ワークシートの追加、削除、名前変更、コピー、行や列の挿入、削除、非表示設定をしている。<br> <br> また、エラーハンドリングのための<code>try-catch</code>ブロックも含んでいる。<br> これにより、操作中に発生する可能性のある例外を捕捉して、適切なエラーメッセージを表示する。<br> <br> <syntaxhighlight lang="c#"> using System; using ClosedXML.Excel; class Program { static void Main(string[] args) { using (var workbook = new XLWorkbook()) { try { // ワークシートの追加 var sheet1 = workbook.Worksheets.Add("Sheet1"); var sheet2 = workbook.Worksheets.Add("Sheet2"); Console.WriteLine("2つのワークシートを追加"); // ワークシートの名前変更 sheet1.Name = "新しい名前"; Console.WriteLine("Sheet1の名前を 新しい名前 に変更"); // ワークシートのコピー (既存のワークシートをコピー) var copiedSheet = sheet2.CopyTo("Sheet2のコピー"); Console.WriteLine("Sheet2をコピー"); // 行の挿入 (指定した行の上に新しい行を挿入) sheet1.Row(2).InsertRowsAbove(2); Console.WriteLine("2行目の上に2行挿入"); // 列の挿入 (指定した列の前に新しい列を挿入) sheet1.Column(2).InsertColumnsBefore(2); Console.WriteLine("B列の前に2列挿入"); // 行の削除 sheet1.Row(5).Delete(); Console.WriteLine("5行目を削除"); // 列の削除 sheet1.Column("D").Delete(); Console.WriteLine("D列を削除"); // 行の非表示設定 sheet1.Row(3).Hide(); Console.WriteLine("3行目を非表示"); // 列の非表示設定 sheet1.Column("C").Hide(); Console.WriteLine("C列を非表示"); // ワークシートの削除 (ワークシート全体を削除) workbook.Worksheet("Sheet2のコピー").Delete(); Console.WriteLine("Sheet2のコピーを削除"); // ファイルを保存 workbook.SaveAs("ワークシート操作サンプル.xlsx"); Console.WriteLine("ファイルを保存"); } catch (Exception ex) { Console.WriteLine($"エラーが発生: {ex.Message}"); } } } } </syntaxhighlight> <br><br> == Excelの主要な関数 == ==== 使用例 ==== 以下の例では、SUM、AVERAGE、VLOOKUP、IF等の関数を直接挿入して使用している。<br> <br> 関数の適用には<code>FormulaA1</code>プロパティを使用して、通常のExcelで使用する形式で数式を記述する。<br> 関数の結果を取得するには、セルの<code>Value</code>プロパティを使用する。<br> <br> また、文字列を含む数式では、ダブルクォートをエスケープする必要がある。(例: \"高い\")<br> <br> <u>※注意</u><br> <u>実際の使用では、これらの関数をより複雑な数式の一部として使用したり、大量のデータに対して適用したりすることができる。</u><br> <u>また、Closed XMLは多くのExcel関数をサポートしているが、一部の高度な関数や最新の関数はサポートされていない可能性がある。</u><br> <u>そのような場合は、代替の方法を検討する必要がある。</u><br> <br> <syntaxhighlight lang="c#"> using System; using ClosedXML.Excel; class Program { static void Main(string[] args) { using (var workbook = new XLWorkbook()) { var worksheet = workbook.Worksheets.Add("関数サンプル"); try { // サンプルデータの入力 worksheet.Cell("A1").Value = "商品"; worksheet.Cell("B1").Value = "価格"; worksheet.Cell("A2").Value = "りんご"; worksheet.Cell("B2").Value = 100; worksheet.Cell("A3").Value = "バナナ"; worksheet.Cell("B3").Value = 80; worksheet.Cell("A4").Value = "オレンジ"; worksheet.Cell("B4").Value = 120; // SUM関数 // A1形式の数式を設定して、B2からB4セルの値を合計する worksheet.Cell("B5").FormulaA1 = "=SUM(B2:B4)"; Console.WriteLine($"合計金額: {worksheet.Cell("B5").Value}"); // AVERAGE関数 // B2からB4セルの値の平均を計算する worksheet.Cell("B6").FormulaA1 = "=AVERAGE(B2:B4)"; Console.WriteLine($"平均価格: {worksheet.Cell("B6").Value}"); // 検索用データの入力 worksheet.Cell("D1").Value = "商品コード"; worksheet.Cell("E1").Value = "商品名"; worksheet.Cell("D2").Value = "A001"; worksheet.Cell("E2").Value = "りんご"; worksheet.Cell("D3").Value = "B001"; worksheet.Cell("E3").Value = "バナナ"; worksheet.Cell("D4").Value = "C001"; worksheet.Cell("E4").Value = "オレンジ"; // VLOOKUP関数 // A7セルの値をキーとして、D2:E4の範囲から対応する値を検索する // 2は返す列のインデックス、FALSEは完全一致を意味する worksheet.Cell("A7").Value = "B001"; // 検索キー worksheet.Cell("B7").FormulaA1 = "=VLOOKUP(A7,D2:E4,2,FALSE)"; Console.WriteLine($"商品コードB001の商品名: {worksheet.Cell("B7").Value}"); // IF関数 // B2セルの値が100より大きい場合は"高い"、そうでない場合は"安い"を返す worksheet.Cell("C2").FormulaA1 = "=IF(B2>100,\"高い\",\"安い\")"; worksheet.Cell("C3").FormulaA1 = "=IF(B3>100,\"高い\",\"安い\")"; worksheet.Cell("C4").FormulaA1 = "=IF(B4>100,\"高い\",\"安い\")"; Console.WriteLine($"りんごの評価: {worksheet.Cell("C2").Value}"); Console.WriteLine($"バナナの評価: {worksheet.Cell("C3").Value}"); Console.WriteLine($"オレンジの評価: {worksheet.Cell("C4").Value}"); // ファイルを保存 workbook.SaveAs("Excel関数サンプル.xlsx"); Console.WriteLine("ファイルを保存"); } catch (Exception ex) { Console.WriteLine($"エラーが発生: {ex.Message}"); } } } } </syntaxhighlight> <br> ==== 関数がサポートされていない場合の代替方法 ==== Closed XMLにおいてサポートされていない高度な関数や最新の関数を扱うための代替方法を、以下に示す。<br> <br> * C#でロジックを実装する *: Excelの関数と同等の機能をC#のコードで直接実装する。 *: これにより、任意の複雑さの計算を行うことができる。 *: 例: SUMIFS関数の代わりに、LINQを使用して条件に合う値を合計する。 *: <br> * 数式を分解する *: 複雑な関数を、サポートされているより単純な関数の組み合わせに分解する。 *: これにより、同等の機能を実現できる場合がある。 *: 例: SUMPRODUCT関数を、複数のセルの乗算とSUM関数の組み合わせで実現する。 *: <br> * 名前付き範囲を利用する *: 複雑な計算を名前付き範囲として定義して、その結果を参照することにより、計算を管理しやすくする。 *: これにより、複雑な計算をより管理しやすい形に分割できる。 *: <br> * データ処理をExcelの外で行う *: 複雑な計算や処理をC#で行い、結果のみをExcelに書き込む。 *: これは、特に大量のデータを扱う場合に効果的である。 *: <br> * 動的配列数式の代替 *: 最新のExcelの動的配列数式がサポートされていない場合、結果を複数のセルに手動で展開する。 *: <br> * Power Query相当の処理をC#で実装する *: データの変換や結合等の操作をC#で実装して、結果をExcelに書き込む。 *: <br> * VBAマクロの代替 *: VBAマクロで行っている処理をC#で実装して、Closed XMLを使用してExcelファイルを操作する。 *: <br> * 外部ライブラリの使用 *: 数学や統計の高度な計算を行う外部ライブラリを使用して、Excelの高度な関数を再現する。 <br> ==== 代替方法の例 : C#でロジックを実装する ==== 以下の例では、C#とLINQを使用して、Excelの<code>SUMIFS</code>関数と同等の機能 (LINQを使用して、条件に合う値を合計) を実現している。<br> <br> <syntaxhighlight lang="c#"> // 実装例 : SUMIFS関数の代替 // C#とLINQを使用 public static double SumIfs(IXLRange dataRange, params Tuple<IXLRange, string>[] criteria) { var data = dataRange.CellsUsed().Select(c => c.GetDouble()); foreach (var criterion in criteria) { var criteriaRange = criterion.Item1; var condition = criterion.Item2; data = data.Where((value, index) => EvaluateCondition(criteriaRange.Cell(index + 1).GetString(), condition)); } return data.Sum(); } private static bool EvaluateCondition(string cellValue, string condition) { // 条件の評価ロジックを実装 // 例: ">10", "=Test", "<5"などの条件をパースして評価 } </syntaxhighlight> <br><br> == 条件付き書式の適用 == 条件付き書式は、データの傾向や例外を視覚的に把握するのに役立つ。<br> <br> Closed XMLでは、<code>AddConditionalFormat</code>メソッドを使用して、各条件付き書式のルールを設定することができる。<br> <br> 以下の例では、条件付き書式をExcelシートに適用している。<br> <br> * サンプルデータを生成して、シートに挿入する。 * 3つの異なる条件付き書式を適用する。 ** 値が50より大きい場合、セルを赤色に塗る。 ** 値が25以下の場合、セルを緑色に塗る。 ** データバーを適用して、値の大きさを視覚的に表現する。 <br> <syntaxhighlight lang="c#"> using System; using System.Linq; using ClosedXML.Excel; class Program { static void Main(string[] args) { Console.WriteLine("条件付き書式の適用を開始..."); try { using (var workbook = new XLWorkbook()) { var worksheet = workbook.Worksheets.Add("条件付き書式"); // サンプルデータを挿入 var data = Enumerable.Range(1, 20).Select(i => new { Value = i * 5 }).ToList(); worksheet.Cell(1, 1).Value = "Value"; worksheet.Cell(2, 1).InsertData(data); // 条件付き書式を適用 var range = worksheet.Range(2, 1, 21, 1); // 1. 値が50より大きい場合、セルを赤色に var rule1 = range.AddConditionalFormat(); rule1.WhenGreaterThan(50).Fill.SetBackgroundColor(XLColor.Red); // 2. 値が25以下の場合、セルを緑色に var rule2 = range.AddConditionalFormat(); rule2.WhenLessThanOrEqual(25).Fill.SetBackgroundColor(XLColor.Green); // 3. データバーを適用 var rule3 = range.AddConditionalFormat(); rule3.DataBar(XLColor.Blue); workbook.SaveAs("条件付き書式.xlsx"); } Console.WriteLine("条件付き書式の適用が完了"); } catch (Exception ex) { Console.WriteLine($"エラーが発生: {ex.Message}"); } } } </syntaxhighlight> <br><br> == テンプレートベースの文書生成 == テンプレートベースの文書の生成は、レポートや請求書等、構造化された文書の生成に適している。<br> <br> <u>※注意</u><br> <u>ただし、テンプレートファイルの構造が変更された場合、コードの修正が必要になる可能性があることに注意すること。</u><br> <br> 以下の例では、既存のテンプレートファイルを基に新しい文書を生成している。<br> <br> * 既存のテンプレートファイルを開いて、新しいワークブックにコピーする。 * <code>ReplaceText</code>メソッドを使用して、プレースホルダーを実際の値で置換する。 * 動的なデータを挿入して、必要な計算を行う。 <br> <syntaxhighlight lang="c#"> using System; using System.Collections.Generic; using ClosedXML.Excel; class Program { static void Main(string[] args) { Console.WriteLine("テンプレートベースの文書生成を開始..."); try { // テンプレートファイルを開く using (var template = new XLWorkbook("テンプレート.xlsx")) using (var result = new XLWorkbook()) { var worksheetTemplate = template.Worksheet(1); var worksheetResult = result.Worksheets.Add("生成結果"); // テンプレートをコピー worksheetTemplate.CopyTo(worksheetResult); // プレースホルダーを置換 worksheetResult.Cells().ReplaceText("{{日付}}", DateTime.Now.ToString("yyyy/MM/dd")); worksheetResult.Cells().ReplaceText("{{会社名}}", "株式会社サンプル"); // 動的データを挿入 var data = new List<object[]> { new object[] { "商品A", 100, 5000 }, new object[] { "商品B", 200, 3000 }, new object[] { "商品C", 150, 4000 } }; var dataRange = worksheetResult.Cell("A5").InsertData(data); // 合計を計算 var lastRow = dataRange.LastRow().RowNumber(); worksheetResult.Cell(lastRow + 1, 1).Value = "合計"; worksheetResult.Cell(lastRow + 1, 3).FormulaA1 = $"=SUM(C5:C{lastRow})"; result.SaveAs("生成結果.xlsx"); } Console.WriteLine("テンプレートベースの文書生成が完了"); } catch (Exception ex) { Console.WriteLine($"エラーが発生: {ex.Message}"); } } } </syntaxhighlight> <br><br> == 大量データの高速処理 == ==== 使用例 : 分割処理なし・ストリーミング処理なし ==== 以下の例では、100万行のデータを生成して、Excelファイルに高速で書き込んでいる。<br> <br> * Enumerable.RangeとLINQを使用して大量のデータを効率的に生成する。 * InsertDataメソッドを使用して、データを一括で挿入する。<br>これは、個別のセルに値を設定するよりも高速である。 <br> 大量のデータを扱う場合は、MemoryStreamのサイズが大きくなる可能性がある。<br> そのような場合は、データを分割して処理、あるいは、ストリーミング方式でファイルに書き込む方法を検討する必要がある。<br> <br> <u>※注意</u><br> <u>Closed XMLには直接的な非同期メソッドが存在しないため、これを回避するための1つの方法である。</u><br> <u>Closed XMLの将来のバージョンで非同期メソッドが提供された場合は、それを使用するように更新することを推奨する。</u><br> <br> <syntaxhighlight lang="c#"> using System; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading.Tasks; using ClosedXML.Excel; class Program { static async Task Main(string[] args) { Console.WriteLine("大量データの完全非同期高速処理を開始..."); var stopwatch = Stopwatch.StartNew(); try { await ProcessLargeDataAsync(); stopwatch.Stop(); Console.WriteLine($"大量データの処理が完了 処理時間: {stopwatch.ElapsedMilliseconds}ms"); } catch (Exception ex) { Console.WriteLine($"エラーが発生しました: {ex.Message}"); } } static async Task ProcessLargeDataAsync() { var workbook = await Task.Run(() => { var wb = new XLWorkbook(); var worksheet = wb.Worksheets.Add("大量データ"); // 100万行のデータを生成 const int rowCount = 1_000_000; var data = Enumerable.Range(1, rowCount) .Select(i => new { ID = i, Value = i * 2 }) .ToList(); // データをワークシートに書き込む worksheet.Cell(1, 1).Value = "ID"; worksheet.Cell(1, 2).Value = "Value"; worksheet.Cell(2, 1).InsertData(data); // 合計を計算 worksheet.Cell(rowCount + 2, 1).Value = "合計"; worksheet.Cell(rowCount + 2, 2).FormulaA1 = $"=SUM(B2:B{rowCount + 1})"; return wb; }); // ファイルを非同期で保存 await SaveWorkbookAsync(workbook, "大量データ処理.xlsx"); } static async Task SaveWorkbookAsync(XLWorkbook workbook, string filePath) { using (var memoryStream = new MemoryStream()) { workbook.SaveAs(memoryStream); memoryStream.Position = 0; using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true)) { await memoryStream.CopyToAsync(fileStream); } } } } </syntaxhighlight> <br> ==== 使用例 : 分割処理 ==== 以下の例では、メモリ使用量を抑えつつ大量のデータを効率的に処理している。<br> また、メモリに制約のあるシステムで動作させる場合にも有効である。<br> <br> * メモリ使用量の削減 *: 1度に全データを生成せずに、小さなバッチで処理するため、メモリ使用量を抑えることができる。 * 柔軟性 *: バッチサイズを調整することにより、様々なシステム環境に対応できる。 <br> <u>※注意</u><br> * <u>バッチサイズの選択</u> *: <u>システムのメモリ容量とパフォーマンスを考慮して適切なバッチサイズを選択する必要がある。</u> * <u>処理時間</u> *: <u>全データを1度に処理する場合と比較して、若干処理時間が増加する可能性がある。</u> <br> <syntaxhighlight lang="c#"> using System; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading.Tasks; using ClosedXML.Excel; class Program { // Mainメソッドは変更なし static async Task Main(string[] args) { // ...略 } static async Task ProcessLargeDataAsync() { const int totalRows = 1_000_000; // 全ての処理する行数 const int batchSize = 10_000; // 1度に処理する行数 using (var workbook = new XLWorkbook()) { var worksheet = workbook.Worksheets.Add("大量データ"); // ヘッダを追加 worksheet.Cell(1, 1).Value = "ID"; worksheet.Cell(1, 2).Value = "Value"; for (int start = 0; start < totalRows; start += batchSize) { int end = Math.Min(start + batchSize, totalRows); await ProcessBatchAsync(worksheet, start, end); Console.WriteLine($"Processed rows {start + 1} to {end}"); } // 合計を計算 worksheet.Cell(totalRows + 2, 1).Value = "合計"; worksheet.Cell(totalRows + 2, 2).FormulaA1 = $"=SUM(B2:B{totalRows + 1})"; await SaveWorkbookAsync(workbook, "大量データ処理_分割.xlsx"); } } static async Task ProcessBatchAsync(IXLWorksheet worksheet, int start, int end) { await Task.Run(() => { var data = Enumerable.Range(start + 1, end - start) .Select(i => new { ID = i, Value = i * 2 }); worksheet.Cell(start + 2, 1).InsertData(data); }); } // SaveWorkbookAsyncメソッドは変更なし static async Task SaveWorkbookAsync(XLWorkbook workbook, string filePath) { // ...略 } } </syntaxhighlight> <br> ==== 使用例 : ストリーミング処理 ==== ストリーミング処理とは、データを連続的に処理する方法であり、全データを1度にメモリに読み込むことなく、データが利用可能になり次第処理を行う。<br> 典型的には、データを小さな塊 (チャンク) として読み取り、即座に処理・結果を出力する。<br> <br> <u>ストリーミング処理をExcelファイルの生成に適用するのは難しく、特に、Closed XMLライブラリではサポートされていない。</u><br> <br> <u>OpenXML SDKを使用する場合は、より低レベルでのストリーミングに近い処理が可能であるが、実装が複雑になる。</u><br> <br><br> == コレクションやDataTableの使用 == Closed XMLは、コレクションやLINQなどと相性が良い。<br> コレクションやDataTableオブジェクト(System.Data名前空間)を簡単にワークシートに挿入できる。<br> <br> 以下のサンプルコードは、コレクションを挿入している例である。<br> データを挿入するInsertDataメソッドは、挿入したセルの範囲を返すので、続けてその範囲のセルを処理しやすい。<br> また、その範囲から特定の行を抽出するには、ラムダ式で条件を指定できる。<br> <br> 以下のサンプルコードではコレクションを挿入したが、DataTableにデータを挿入するときも同様にInsertDataメソッドを使用する。<br> <syntaxhighlight lang="c#"> const string ExcelFilePath = @"sample.xlsx"; // Excelファイルに貼り付けたいデータ // 例として、ここでは今月の日付と曜日のコレクションを用意する List<(DateTime, string)> days = new List<(DateTime, string)>(); var firstDayOfThisMonth = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1); int daysInThisMonth = DateTime.DaysInMonth(firstDayOfThisMonth.Year, firstDayOfThisMonth.Month); for (int i = 0; i < daysInThisMonth; i++) { var d = firstDayOfThisMonth.AddDays(i); days.Add((d, d.DayOfWeek.ToString())); } // Excelファイルを開く using (var workbook = new XLWorkbook(ExcelFilePath)) { // ワークシートの追加 using (var worksheet = workbook.Worksheets.Add("サンプルシート2")) { // タイトル行 var cellA1 = worksheet.Cell("A1"); cellA1.Value = "今月のカレンダー"; cellA1.Style.Alignment.SetHorizontal(XLAlignmentHorizontalValues.Center) .Font.SetFontName("Meiryo") .Font.SetBold(true) .Font.SetFontColor(XLColor.White) .Fill.SetBackgroundColor(XLColor.FromArgb(0x00A2E8)); // セルの連結 worksheet.Range("A1:B1").Merge(); // ワークシートに日付と曜日のコレクションを挿入 var calendarRange = worksheet.Cell("A2").InsertData(days); // 日曜日の行を抽出して使用しているセルの背景を赤に変更 var sundayRows = calendarRange.Rows(r => r.Cell(1).GetDateTime().DayOfWeek == 0); foreach (var r in sundayRows) { r.CellsUsed().Style.Fill.BackgroundColor = XLColor.Red; } // ワークブックの保存 workbook.Save(); } Console.WriteLine("ワークシートを追加しました。"); } </syntaxhighlight> <br> 上記で作成したExcelファイルを読み取る。<br> 何らかのデータや数式が入力されているセルの範囲を取得するRangeUsedメソッドがあるので、セルの位置を指定せずに簡単にデータ範囲を取り出せる。<br> そのセル範囲からコレクションを生成するには、LINQのSelect拡張メソッドを使用する。<br> また、DataTableに変換するのも簡単である。<br> <syntaxhighlight lang="c#"> const string ExcelFilePath = ".\\sample.xlsx"; // Excelファイルを開く using (var workbook = new XLWorkbook(ExcelFilePath)) { // ワークシートの取得 using (var worksheet = workbook.Worksheet("サンプルシート2")) { // データや数式が入力されているセルの範囲 var rangeUsed = worksheet.RangeUsed(); Console.WriteLine($"使用中のセル範囲:{rangeUsed.FirstCell().Address}~{rangeUsed.LastCell().Address}"); // 1列目がDateTime型の行のみを取得してコレクションに変換 IEnumerable<(DateTime,string)> data = rangeUsed.Rows(r => r.Cell(1).DataType == XLDataType.DateTime) .Select(r => (r.Cell(1).GetDateTime(), r.Cell(2).GetString())); // 最初の7個を表示 // 出力 : 10/1(Monday) 10/2(Tuesday) 10/3(Wednesday) 10/4(Thursday) 10/5(Friday) 10/6(Saturday) 10/7(Sunday) foreach (var (d, s) in data.Take(7)) { Console.WriteLine($"{d:M/d}({s})"); } // DataTableへの変換もサポート System.Data.DataTable dataTable = rangeUsed.CreateTable().AsNativeDataTable(); // 8個目から7個を表示 // 出力 : 10/8(Monday) 10/9(Tuesday) 10/10(Wednesday) 10/11(Thursday) 10/12(Friday) 10/13(Saturday) 10/14(Sunday) foreach(System.Data.DataRow r in dataTable.Select().Skip(7).Take(7)) { Console.WriteLine($"{r[0]:M/d}({r[1]})"); } } } </syntaxhighlight> <br><br> __FORCETOC__ [[カテゴリ:C_Sharp]]
ClosedXML - Excelファイルの操作
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse