【C#でエクセル操作】
ClosedXMLの特徴と操作まとめ


(最終更新日:

記事イメージ

ClosedXMLは、C#でのエクセル操作ライブラリの中でも、実用性や使いやすさの面で信頼しているライブラリです(私自身も長年活用させていただいています)。その優れたポイントと基本的な実装コードをまとめてご紹介します。

以下、ページ内リンクです。目的に応じてご活用ください。

(ページ内リンク)チートシートを見たい、具体的な実装方法を探す方はこちら

(ページ内リンク)ClosedXMLと何?特徴は?導入方法は?を知りたい方はこちら

(ページ内リンク)XLWorkbookオブジェクト生成時の小技を知りたい方はこちら

また、C#でエクセル操作を行うライブラリとしては双璧を成すEPPlus、また読込のみながら高速かつXLS形式にも対応できるExcelDataReaderについても、本記事と同様に操作概要と、比較記事を作成しています。下記ご参考ください。

関連記事:【C#でエクセル操作】EPPlus操作まとめ
関連記事:【C#×Excelライブラリ選定】及びEPPlus vs ClosedXML 処理速度・概要比較
関連記事:【C#でエクセル解読】ExcelDataReaderの実装とパフォーマンス測定
関連記事:【C#・Excel】SpreadSheetLightの特徴と基本操作

◇目次

  1. ClosedXMLの特徴 ~メリットが多く使いやすいライブラリ
  2. 導入:NuGetでVisual Studioのプロジェクトにインストール
  3. チートシート:基本的な処理実装方法まとめ
  4. ワークブックを開く際のXLWorkbook引数のテクニック
  5. トラブルシューティング:作成したワークブックを開くと、「'XXXX.xlsx'の一部の内容に問題が見つかりました。」と表示される場合
  6. 「C#でエクセル」ができるEPPlusについて、ClosedXMLとの比較を関連記事にまとめています。
  7. 参考リンク(Github)
  8. 記事筆者へのお問い合わせ、仕事のご依頼

ClosedXMLの特徴 ~メリットが多く使いやすいライブラリ

ClosedXMLはC#のライブラリです。概要は次の通りです。

ClosedXMLの概要
  • C#でエクセルファイルを新規または既存ファイルを操作をするためのライブラリ。
  • NuGet(Visual Studio標準のパッケージマネージャ)で入手可能。
  • オープンソースによる開発、MITライセンス
ClosedXMLで何ができるのか?→エクセルの標準機能は一通り実行可能
  • エクセルファイルの新規作成
  • 既存エクセルファイルの読み込み
  • 値や式の入力
  • セル挿入削除、結合
  • シート追加
  • その他諸々(ピボットテーブル、表示の固定、その他)
ClosedXMLの特徴
  • APIが直感的で簡潔に記述できる。特にマクロ制作経験があれば、VBAに文法が似ており理解しやすい。
  • 値や数式の取得及び記述、行列単位や範囲での切り出し、シート追加、表示関連操作など、幅広い機能が実装されている。基本的な操作はまず困らない。
  • Open XML SDK(Microsoft純正API)のラッパーであり、安定感がある。
  • そこそこ高速な動作
  • .NET Framework系、Core系のいずれにも対応

他のC#ライブラリ(EPPlus、ExcelDataReader)との比較

ClosedXMLはMITライセンスかつXLSX形式の読み込み・書き込み両方に対応可能な点が特徴です。同じくXLSX形式の読み書きが可能なEPPlusは動作は高速ですが、商用有償ライセンスとなります。用途・プロジェクトにより選択が必要でしょう。

また、ExcelDataReaderはXLS形式にも対応可能(ClosedXMLはXLSX形式のみ対応可)で読み込みも高速ですが、書き込み機能はありません。ファイル作成・編集の必要がないのであればExcelDataReaderも有力な選択肢と言えます。尚、ExcelDataReaderもMITライセンスで公開されています。

★C#エクセル操作ライブラリ比較早見表(アップデート等で変動する可能性があります。)
ライブラリ名ClosedXMLEPPlusExcelDataReader
ライセンスMIT独自(商用有償)MIT
対応形式XLSXXLSXXLSX、XLS、CSV等
読み込み
書き込み
筆者独自調査によると比較的高速比較的高速
新しいファイルを作り、値や式を書き込めます(右がコード、左が実行結果)。既存ファイルを開いて編集することもできます。
新しいファイルを作り、値や式を書き込めます(右がコード、左が実行結果)
既存ファイルを開きセルから値を読み込むことも、もちろんできます。(右がコード、左が実行結果)
既存ファイルを開きセルから値を読み込むことも、もちろんできます

導入:NuGetでVisual Studioのプロジェクトにインストール

ClosedXMLは下図の通りNuGetパッケージマネージャーでVisual Studioのプロジェクトにインストール可能です。

ライセンスはMITで提供されています。

nuget

【社内PR】チーム・ウォーク

チートシート:基本的な処理実装方法まとめ

ワークブックの作成、編集、保存、変換の一連の流れをまとめます。

コード冒頭のusing記述

NuGetでのインストール後、コード冒頭に記述するusingは1行でOKです。

C#
using ClosedXML.Excel;

新しいワークブックの作成

空のワークブックを作成します。

リソースはアンマネージドのため、usingステートメントと一緒に使用することをオススメします。(保存する前にオブジェクトを破棄することがないように注意しましょう。)

C#
using var wb = new XLWorkbook();

//尚、C#8.0より前であれば以下の様に記述します。
using (var wb = new XLWorkbook()) {
    //do something
}

※詳細はこちらで後述(ページ内リンク)しますが、new XLWorkbookについては次のようなテクニックもご活用ください。

C#
//①XLEventTracking.Disabledの指定(セル挿入・削除追跡をオフ)によるパフォーマンス向上
//【重要】2023/2/3追記:XLEventTrackingはバージョン0.100系で削除されました。詳しくは次のURLをご参考ください。https://closedxml.readthedocs.io/en/latest/migrations/migrate-to-0.100.html#xleventtracking-removed
////既存ファイルを開く場合
//using var wb = new XLWorkbook(@"C:\Users\sakai\aaa.xlsx", XLEventTracking.Disabled);
////新規ファイルの場合
//using var wb = new XLWorkbook(XLEventTracking.Disabled);

//②読み取り専用で既存ファイルを開く
using var fileStream = new FileStream(@"C:\Users\sakai\aaa.xlsx", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using var wb = new XLWorkbook(fileStream);

ワークブックにワークシートを追加

ワークブックを新規に作っただけではシートが一つもないので、追加していきます。

IXLWorksheets.Addメソッドに新規シート名を指定します。

Addメソッドの戻り値に新しく作ったワークシートオブジェクトが格納されますので、このオブジェクトに対して作業をしていきます。

C#
using var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("新しいシート名");

シートのポジション(エクセルで開いた時のシートタブの並び位置)を指定することもできます。第2引数positio=0で一番左の指定となります。

C#
//一番左にシートを追加
var ws = wb.Worksheets.Add("新しいシート名", 0);

ちなみにwb.Worksheetsの型IXLWorksheetsは、IEnumerable<IXLWorksheet>の派生型です。(AddメソッドはIXLWorksheetsクラスで定義されています。)

したがって、例えばLinqを使って既存のワークシートの取得・絞り込みなどが行えます。

C#
//例えば名前で絞込み
var wss = wb.Worksheets.Where(x => x.Name.Contains("test"));

既存のワークブックファイルを開く

既存のファイルを開くには、引数にパスを指定します。

C#
using var wb = new XLWorkbook(@"C:\Users\sakai\test.xlsx");

ワークブックの中の既存のワークシートを取得

XLWorkbook.Worksheetメソッドの引数にシート名を指定します。存在しないシート名が指定された場合、例外がスローされます。

C#
var ws = wb.Worksheet("シート名");

シート位置をint型で指定して取得することもできます。

位置番号は、ワークブックの一番左のシートが1で、右に行くにつれて1ずつ大きくなります。引数に0以下の数値を指定したり、シート数を超えた数値を指定すると、例外がスローされます。

C#
//一番左のシートを取得
var ws = wb.Worksheet(1);

尚、混同しやすいですが、XLWorkbook.Worksheetはメソッド、XLWorkbook.Worksheetsはプロパティとして存在しています。

ワークシートのセルの値を取得

2023年1月公開のClosedXMLバージョン0.100より、IXLCell.Valueプロパティの型がobject型から独自型(XLCellValue型)に変更されるという、大きめの変更が入りました。値取得に関しては0.9X系以前とはコードの書き方を変える必要があります。詳しくはリリースノートをご確認ください。

上記変更により、V0.100以降では値取得時に厳格に型を評価することができるようになりました。ここでは、変更前・変更後の両方の値の取得方法を紹介します。

尚、V0.100以降で「難しいこと考えずとにかく値を取りたい」ということであれば、XLCellValue.ToString()を使えばOKです。型の如何を問わず文字列でセルの値を取得できます。尚、ここでのToStringは、.NET標準ではなくXLCellValueクラスに独自に実装されています。

【バージョン0.100以降】IXLCell.Valueプロパティで取得されるXLCellValue型の取り扱い

バージョン0.100以降では、セルの値を取得するIXLCell.Valueプロパティは、object型ではなくXLCellValue型となっています。XLCellValue型には、取得したセルの値の型(日付、文字列、数値等)の判定と、それぞれの形式での値を取得するメソッドが実装されています。

数値、日付、文字列、ブーリアンの値の取得をそれぞれGetNumber、GetDateTime、GetText、GetBooleanメソッドを使用して取り出します。

C#
//ここで、wsはIXLWorksheet型のオブジェクト
XLCellValue value = ws.Cell(1, 1).Value; //XLCellValue型で取得

//XLCellValue型から値を取得
//※適切なメソッドを呼ばないとInvalidCastExceptionがスローされるので、
//事前に型の判定を行う必要があります。
if (value.IsNumber) {
    //数値型(double)で取得
    double num = value.GetNumber();
} else if (value.IsDateTime) {
    //日付型で取得(エクセル式シリアル日付値を変換してくれます)
    DateTime date = value.GetDateTime();
} else if (value.IsText) {
    //文字列型で取得
    string text = value.GetText();
}

//型を問わず文字列型で取得する場合はToStringメソッドを使用します。
//尚、このToStringメソッドは.NET標準ではなくXLCellValueに定義されています。
var text2 = value.ToString();

尚、セルの値の型と一致しない取得メソッド(GetXXXX)を呼ぶと例外がスローされる点には注意が必要です。型を問わず値を文字列で取得するにはToStringメソッド(.NET標準ではなくXLCellValueに定義されています)を使用します。

C#
//型を問わず値を文字列で取得するにはToStringメソッドを使用します。
//尚、このToStringメソッドは.NET標準ではなくXLCellValueに定義されています。
var value = ws.Cell(1, 1).Value;
var text = value.GetText();

尚、ここでいう「セルの型」は書式の設定と同等と考えて差し支えありません。仮にシリアル日付として認識可能な値(43298など)をセットしたセルでも、GetDateTimeを呼ぶとInvalidCastExceptionがスローされます。
尚、ここでいう「セルの型」は書式の設定と同等と考えて差し支えありません

【バージョン0.9X以前】IXLCell.Valueはobject型で取得される

旧型式の値の取得方法です。IXLCell.Valueにアクセスすると、セルの値がobject型で取得されます。

C#
var cell = ws.Cell(1, 1);
object value = cell.Value;

ワークシートのセルに値を記述

セルに値をセットする場合はこちらです。尚、他のセルを参照するなどのエクセル式を記述したい場合、後段のFormulaA1等を使用する必要がありますのでご注意ください。(Value/SetValueを使用すると文字列になってしまいます。)

また、上記の通りバージョン0.100よりIXLCell.Valueの型が変更されていますが、こちらの操作に関しては旧来と同じコードで動作します。

C#
using var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("新しいシート名");
var cell = ws.Cell(1, 1);
//SetValueメソッドを使用するか、Valueプロパティに値をセットします。
//以下2つのコードは同等の結果を得られます。
cell.SetValue("てすと");
cell.Value = "てすと";

//SetValueメソッドは当該IXLCellオブジェクトが返り値となるため、
//次のように続けて書式指定などをする場合に便利です。
cell
    .SetValue("てすと")
    .Style.Fill.SetBackgroundColor(XLColor.FromArgb(155, 194, 230));

尚、RangeやCellsのValueプロパティもしくはSetValueメソッドに値を指定することで、範囲内にまとめて値や式、書式をセットすることが出来ます。

C#
//A1~A10000セルにまとめて値をセット
ws.Range(1, 1, 10000, 1).SetValue("2");
ws.Range(1, 1, 10000, 1).Value = "2";

//A1~A10000セルにまとめて式をセット
ws.Range(1, 1, 10000, 1).FormulaA1 = "=1+1";

//A1~A10000セルの背景をまとめて黒にする
ws.Range(1, 1, 10000, 1).Style.Fill.BackgroundColor = XLColor.Black;

※ちなみに、2022年初頭時点のGAS(Google Apps Script、Googleスプレッドシート版VBAライクな処理が可能な開発環境)では、Rangeでやるかセル個別処理でやるかという違いで大幅な処理速度の差が出る(範囲の方が早い)のですが、ClosedXMLで実測してみたところ、Rangeに対して値をセットしたほうが若干早い程度で、大きな差は見られませんでした。

ワークシートのセルから値を取得

セルの値に合わせてobject型で取得されます。適宜必要な形式に変換して使いましょう。

C#
using var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("新しいシート名");
var cell = ws.Cell(1, 1);
//ワークシートのセルから値を取得
var value = cell.Value;

ワークシートのセルに式をセット

A1形式で式を指定する場合はFormulaA1系、RC形式で使用する場合はFormulaR1C1系のメソッド・プロパティを使用します。

C#
using var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("新しいシート名");
var cell = ws.Cell(1, 1);
//SetValueと同じように、SetFormulaA1メソッドを使用するか、FormulaA1プロパティに値をセットします。
//以下2つのコードは同等の結果を得られます。
cell.SetFormulaA1("=B1+C1");
cell.FormulaA1 = "=B1+C1";

//SetFormulaA1メソッドは当該IXLCellオブジェクトが返り値となるため、
//次のように続けて書式指定などをする場合に便利です。
cell
    .SetFormulaA1("=B1+C1")
    .Style.Fill.SetBackgroundColor(XLColor.FromArgb(155, 194, 230));

セルの書式設定

セルやテキストの色、数値の表示書式、罫線などは、IXLCell.Styleプロパティに対して設定します。

C#
using var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("新しいシート名");
var cell = ws.Cell(1, 1);
//A1セルに書式をセット
cell.Style.Fill.BackgroundColor = XLColor.FromArgb(155, 194, 230); //セルの色
cell.Style.Border.TopBorder = XLBorderStyleValues.Dotted; //セルの下側の罫線
cell.Style.Border.BottomBorder = XLBorderStyleValues.Thin; //セルの上側の罫線(点線)
cell.Style.DateFormat.Format = "0.0%;▲0.0%;- "; //数値の書式

//以下の書き方でも同じ結果を得られます。
//メソッド形式の場合、戻り値に対して連続で書式設定ができるので便利です。
cell.Style
    .Fill.SetBackgroundColor(XLColor.FromArgb(155, 194, 230)) //セルの色
    .Border.SetBottomBorder(XLBorderStyleValues.Thin) //セルの下側の罫線
    .Border.SetTopBorder(XLBorderStyleValues.Dotted) //セルの上側の罫線(点線)
    .NumberFormat.SetFormat("0.0%;▲0.0%;- "); //数値の書式

条件付き書式の指定(色・罫線・数値フォーマット)

条件付き書式は、セルに追加した条件付き書式オブジェクトに、上記(セルの書式設定セクションで紹介したもの)と同様のメソッドを使用して書式設定を行います。

尚、AddConditionalFormatメソッドは、条件を1個追加するごとにコールする必要があります。また、WhenEqualsメソッドは完全一致条件を追加するものです。その他、範囲であればWhenBetween、部分一致であればWhenContains、空白指定であればWhenIsBlank等、IXLConditionalFormatクラス(AddConditionalFormatメソッド戻り値)に各条件指定方法のメソッドが用意されています。

C#
//A1セルに条件付き書式「値が"OK"なら背景色を黄、値が"NG"なら背景色をライトグレー」と設定する。
//ここで、wsはIXLWorksheet型のオブジェクトです。
ws.Cell(1, 1).AddConditionalFormat().WhenEquals("OK").Fill.SetBackgroundColor(XLColor.Yellow);
ws.Cell(1, 1).AddConditionalFormat().WhenEquals("NG").Fill.SetBackgroundColor(XLColor.LightGray);

//✕NG:以下の実装では、最初の条件追加が次の条件追加に上書きされてしまいます。AddConditionalFormatメソッドは条件ごとにコールする必要があります。
var conditionalFormat = ws.Cell(1, 1).AddConditionalFormat();
conditionalFormat.WhenEquals("OK").Fill.SetBackgroundColor(XLColor.Yellow);
conditionalFormat.WhenEquals("NG").Fill.SetBackgroundColor(XLColor.LightGray);

折り返して全体を表示/縮小して全体を表示

IXLCell.Style.Alignment内に設定プロパティが設置されています。

C#
//ここで、wsはIXLWorksheet型のオブジェクトです。
//縮小して全体を表示
ws.Cell(1, 1).Style.Alignment.ShrinkToFit = true;
//折り返して全体を表示
ws.Cell(1, 1).Style.Alignment.WrapText = true;

ワークブックを上書き保存

既存ファイルを開いている場合、Saveメソッドで上書き保存ができます。

C#
using var wb = new XLWorkbook(@"C:\Users\sakai\Desktop\Book1.xlsx");
//上書き保存
wb.Save();

新規作成ファイル(new XLWorkbook()で引数なしで作成したXLWorkbookオブジェクト)に対してSaveメソッドを実行すると、例外がスローされます。新規ファイルの場合は、次に説明するSaveAsメソッドで名前を付けて保存しましょう。
新規作成ファイル(new XLWorkbook()で引数なしで作成したXLWorkbookオブジェクト)に対してSaveメソッドを実行すると、例外がスローされます

ワークブックを名前を付けて保存(別名保存)

別名保存する場合、SaveAsメソッドに保存先のファイルパスを引数として渡します。

C#
using var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("新しいシート名");
//引数に保存先パスを指定
wb.SaveAs(@"C:\Users\sakai\test2.xlsx");

ワークシートの列・行を固定表示する

ExcelのUIにおける「表示」→「ウィンドウ枠の固定」に相当する設定を行います。

C#
using var wb = new XLWorkbook();
var worksheet = wb.Worksheets.Add("test");

//1~3行目を固定表示
worksheet.SheetView.FreezeRows(3);
//A~B列を固定表示
worksheet.SheetView.FreezeColumns(2);
//列行同時設定(1~3行目、A~B列を固定表示)
worksheet.SheetView.Freeze(3, 2);

worksheet.SheetView.Freeze(3, 2);を実行した結果。1~3行目、A~B列が固定表示されています。
worksheet.SheetView.Freeze(3, 2);を実行した結果

尚、固定表示を解除は、列・行に0を指定することで可能です。※マイナス値を指定するとエクセルファイルを開くときにエラーになります。


//列行固定表示を解除
worksheet.SheetView.Freeze(0, 0);

ワークシートからDataTable型への変換

ワークシートの範囲を指定して.NETネイティブ型であるSystem.Data.DataTable型に変換できます。

それなりに時間がかかる処理なので、組み込む場合は応答時間に注意しましょう。

尚、コード内で使用しているRangeUsedメソッドは、ワークシート内で使用済みのセル範囲(A1:XX)を取得する機能を持ちます。

C#
using var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("新しいシート名");
//DataTable型への変換処理
DataTable table = ws.RangeUsed().AsTable().AsNativeDataTable();

印刷に関する諸設定(ヘッダ・フッタ表示、ページ数指定による自動スケール、印刷用紙の向き・サイズ指定など)

ws.PageSetupプロパティに、印刷に関連する様々な設定(エクセルにおけるページレイアウトタグの設定)を変更可能です。

PageSetupプロパティ(IXLPageSetupインターフェース)には、ここで紹介する以外にも様々な設定値が用意されています。

1ページに印刷するように自動スケールを設定

Excel・VBAにおけるPageSetup.FitToPagesWide及びPageSetup.FitToPagesTallプロパティに相当する設定です。

C#
//横幅全体を1ページで印刷
ws.PageSetup.PagesWide = 1;
//縦幅全体を1ページで印刷
ws.PageSetup.PagesTall = 1;

印刷用紙の縦横を指定

C#
//用紙を縦に印刷
ws.PageSetup.PageOrientation = XLPageOrientation.Portrait;
//用紙を横に印刷
ws.PageSetup.PageOrientation = XLPageOrientation.Landscape;

印刷用紙のサイズを指定

C#
//A3用紙に印刷
ws.PageSetup.PaperSize = XLPaperSize.A3Paper

印刷マージン(余白)を指定

以下のコードでセットされるマージン数値はインチ扱いされるので、センチに変換して利用しましょう。

C#
//順に上・下・左・右の印刷マージンを設定
ws.PageSetup.Margins.SetTop(ToInch(2.0));
ws.PageSetup.Margins.SetBottom(ToInch(2.0));
ws.PageSetup.Margins.SetLeft(ToInch(2.0));
ws.PageSetup.Margins.SetRight(ToInch(2.0));

//ヘッダ・フッタのマージン
ws.PageSetup.Margins.SetHeader(ToInch(2.0));
ws.PageSetup.Margins.SetFooter(ToInch(2.0));

//センチメートル→インチに変換
static double ToInch(double centimeter) {
    return centimeter * 0.39370;
}

印刷ヘッダー・フッターに値を指定

C#
//ヘッダー右(右上)に値をセット
ws.PageSetup.Header.Right.AddText("ヘッダーだよ");
//フッター中央にページ番号を表示
ws.PageSetup.Footer.Center.AddText(XLHFPredefinedText.PageNumber);
//ヘッダー右(右上)に画像をセット
ws.PageSetup.Header.Right.AddImage("C:/test/hoge.png");

印刷範囲(改ページ)を指定

IXLWorksheet.PageSetup.PrintAreasプロパティにAddメソッドで印刷範囲を追加します。

追加した順に、シート内で1ページ目、2ページ目・・・と増えていきます。

尚、PrintAreasプロパティの型IXLPrintAreasはIEnumerable<IXLRange>の派生型で、こちらもLinq等が有効です。(AddメソッドはIXLPrintAreasクラスで定義されています。)

C#
using var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("新しいシート名");
//A1:F10の範囲を印刷範囲に指定
ws.PageSetup.PrintAreas.Add("A1:F10");

ASP.NET Core MVC / ASP.NET MVCでエクセルファイルをダウンロード

MVCプロジェクトでファイルをダウンロードするには、ファイルをバイト配列(byte[]型)に変換した上、FileメソッドでFileContentResultオブジェクト(ActionResult派生クラス)を返します。

XLWorkbook.SaveAsメソッドでMemoryStreamに書き出し可能なため、経由してバイト配列に変換します。

C#
public IActionResult DownloadXlsx() {
    using var wb = new XLWorkbook();
    var ws = wb.Worksheet("新しいシート名");

    using var ms = new MemoryStream();
    wb.SaveAs(ms);
    //ASP.NET MVCの場合
    return System.Web.Mvc.File(ms.ToArray(), "application/msexcel", "test3.xlsx");
}

上記コードのreturnステートメントにて、System.Web.Mvc.Fileメソッドを使用しています。

Core MVCの場合では、名前空間が下のようになりますのでご注意ください。

C#
    // ASP.NET Core MVC(.NET5.0~)の場合
    return Microsoft.AspNetCore.Mvc.File(ms.ToArray(), "application/msexcel", "test3.xlsx");

ワークブックを開く際のXLWorkbook引数のテクニック

XLWorkbookクラスのコンストラクタ(new XLWorkbook())でワークブックを開く際のテクニックを紹介します。

セル挿入・削除トラッキングをオフにすることによるメモリ節約・パフォーマンス向上

この項目で紹介していた内容は、バージョン0.100系で削除されました。詳しくは移行ガイド(Migration from 0.97 to 0.100 — ClosedXML 0.97.1-preview documentation - XLEventTracking removed)をご参考ください。

デフォルトのオープン方法では、セルの挿入・削除は追跡され、その後のセル指定に反映されます。(例えば、1行目を削除した後に3行目を指定した場合、実際には2行目が選択される、といった具合)

この機能が不要の場合、XLEventTracking.Disabledをコンストラクタに指定することで、メモリを節約し、パフォーマンスを向上できます。

セルを挿入・削除しない、またはセルが移動することを前提に範囲指定する場合、このモードが推奨されます。

他のプロセスで使用されている既存ファイルを開くテクニック

ワークシートを開いたままにしているなどの場合、new XLWorkbookでパスを指定して開こうとすると例外が発生します。

XLWorkbookコンストラクタは、ファイルパス(string型)の他、System.IO.Streamを指定できます。そこで、一旦FileStreamで読み取り専用で開き、XLWorkbookオブジェクトを作成します。

C#
//本タスクでは、FileStreamに第4引数まで指定する必要があります。
//【引数の内容】
//第2引数:新規作成 or 既存を開くの指定
//第3引数:ファイルアクセスモード(書き込み/読み取り)
//第4引数:開いている間に他のプロセスで許可する内容
using var fileStream = new FileStream(@"C:\Users\sakai\aaa.xlsx", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using var wb = new XLWorkbook(fileStream);

ファイルが使用中の場合、一工夫しないとIOExceptionがスローされます。
ファイルが使用中の場合、一工夫しないとIOExceptionがスローされます
FileStream経由で読み取り専用で開いたファイルは、Saveメソッド(上書き)を使用すると例外がスローされます。SaveAsメソッドで別名保存することは可能です。
FileStream経由で読み取り専用で開いたファイルは、Saveメソッド(上書き)を使用すると例外がスローされます

トラブルシューティング:作成したワークブックを開くと、「'XXXX.xlsx'の一部の内容に問題が見つかりました。」と表示される場合

記事分離しました。下記関連記事をご参考ください。結論だけ述べると、不完全な式をセルにセットしていることが原因です。

関連記事:【マクロ・ClosedXML】'xxxx.xlsx'の一部の内容に問題が見つかりました。とエラーが表示される場合の原因と対処法

「C#でエクセル」ができるEPPlusについて、ClosedXMLとの比較を関連記事にまとめています。

同じくC#でエクセル操作ができる代表的なライブラリとしてEPPlusが挙げられます。

ClosedXMLとの差(ライセンス、処理速度、出来ること出来ないこと等)について以下の関連記事にまとめています。セル読み書き処理速度についてはEPPlusの方が高速という結果が出ています。

関連記事:【C#×Excelライブラリ選定】及びEPPlus vs ClosedXML 処理速度・概要比較

参考リンク(Github)

Githubにてソースコードが公開されています。

記事筆者へのお問い合わせ、仕事のご依頼

当社では、IT活用をはじめ、業務効率化やM&A、管理会計など幅広い分野でコンサルティング事業・IT開発事業を行っております。

この記事をご覧になり、もし相談してみたい点などがあれば、ぜひ問い合わせフォームまでご連絡ください。

皆様のご投稿をお待ちしております。

記事筆者へ問い合わせする

※ご相談は無料でお受けいたします。

この記事へのコメント

ニックネーム(任意)

返信通知先Emailアドレス(任意)

本文


* 感想やご意見等、お気軽にコメントください。但し、公序良俗に反するコメントはお控えください。
* 管理者が承認したコメントはこの箇所に公開させていただく可能性がございます。
* 返信通知先Emailアドレスは、筆者のみに通知され、公開されることはありません。返信通知先Emailを入力された場合は、コメントへの返信をこちらに掲載した際に通知させていただきます。その他の目的には使用いたしません。
* スパム対策のため、コメントは日本語のみ受け付けております。

堺財経電算合同会社 小規模IT構築サービス