C#でExcelを操作する方法|読み込み・書き込み・出力まで初心者向けに徹底解説

はじめに

C#でExcelを操作できるようになると、業務アプリケーションでよく求められる「Excelファイルの読み込み」「データの書き込み」「帳票出力」「一覧表のダウンロード」などを自動化できます。たとえば、売上一覧をExcelに出力したり、ユーザーがアップロードしたExcelファイルを読み込んでデータベースへ登録したり、既存のテンプレートに値を差し込んで請求書を作成したりできます。

C#でExcelを操作する方法はいくつかありますが、初心者にはExcel本体を起動せずに.xlsxファイルを扱えるライブラリを使う方法がわかりやすいです。代表的なライブラリにはClosedXML、EPPlus、NPOI、Open XML SDKなどがあります。特にClosedXMLは、C#のコードから直感的にセルやシートを操作しやすく、Excelがインストールされていない環境でもExcelファイルを作成できるため、最初の学習に向いています。ClosedXML公式ドキュメントでも、ExcelアプリケーションなしでExcelファイルを作成でき、Webサーバー上のExcel帳票作成にも使えると説明されています。

この記事では、C#でExcelを操作する基本から、読み込み、書き込み、新規作成、見た目の調整、実践的な売上一覧のExcel出力まで、初心者にもわかりやすく解説します。

1. C#でExcel操作を始める前に知っておきたい基礎

1-1. C#でExcelを操作してできること

C#でExcelを操作すると、主に次のような処理を自動化できます。

・Excelファイルを開いてセルの値を読み込む
・行や列をループして一覧データを取得する
・指定したセルに値を書き込む
・既存のExcelファイルを編集して保存する
・新しいExcelファイルを作成する
・DataTableやListの内容をExcelに出力する
・罫線、背景色、列幅、表示形式などを設定する
・テンプレートExcelに値を差し込んで帳票を出力する
・WebアプリからExcelファイルをダウンロードさせる

Excelは業務データの受け渡しでよく使われるため、C#と組み合わせることで、手作業で行っていた集計や帳票作成を効率化できます。

1-2. Excel読み込み・書き込み・出力の主な利用シーン

C#でExcelを扱う場面は、大きく「読み込み」「書き込み」「出力」に分けられます。

読み込みは、ユーザーが作成したExcelをシステムに取り込む処理です。商品マスタ、社員一覧、売上データ、在庫データなどをExcelから読み込み、データベースに登録するケースがあります。

書き込みは、既存のExcelファイルを開いて値を更新する処理です。テンプレートに顧客名や金額を差し込む、集計結果を指定セルに反映する、既存の帳票フォーマットを再利用する、といった用途に向いています。

出力は、C#側で持っているデータをExcelファイルとして新規作成する処理です。検索結果一覧、売上一覧、請求書、レポート、月次集計表などをExcelファイルとして保存またはダウンロードさせる場合に使います。

1-3. 初心者が最初につまずきやすいポイント

C#でExcel操作を始めた初心者がつまずきやすいポイントは、主に次の5つです。

1つ目は、Excel本体を使う方法と、Excelファイルを直接編集するライブラリの違いです。Microsoft.Office.Interop.ExcelはExcelアプリケーションを操作する方式ですが、ClosedXMLやEPPlusなどは.xlsxファイルを直接扱います。

2つ目は、ファイルパスの指定ミスです。相対パスと絶対パスの違い、実行時のカレントディレクトリ、保存先フォルダの存在確認を理解していないと、「ファイルが見つからない」というエラーが起きやすくなります。

3つ目は、セルの型変換です。Excel上では日付に見えていても、内部的には数値や文字列として扱われることがあります。C#側でDateTime、decimal、intなどに変換する際は注意が必要です。

4つ目は、ファイルが開かれている状態で保存しようとすることです。Excelで開いているファイルに対して上書き保存しようとすると、アクセス拒否や保存失敗が起きることがあります。

5つ目は、ライセンスの確認不足です。ライブラリによって無料利用、商用利用、非商用利用の条件が異なるため、個人学習と業務利用では確認すべき内容が変わります。

1-4. .xlsx・.xls・CSVの違いと使い分け

C#でExcelを扱う場合、拡張子の違いを理解しておくことが大切です。

.xlsxは、現在よく使われるExcelブック形式です。シート、セルの書式、数式、罫線、色、複数シートなどを扱えます。ClosedXMLやEPPlus、Open XML SDKなどは主に.xlsx形式を得意とします。

.xlsは、古いExcel形式です。古い社内システムや過去資産で残っていることがあります。.xlsを扱いたい場合は、NPOIなど.xlsに対応できるライブラリを検討します。NPOIはApache POIの.NET版で、Office 2003/2007形式のファイルを読み書きできるライブラリとして説明されています。

CSVは、カンマ区切りのテキストファイルです。Excel専用形式ではありませんが、Excelで開けます。見た目の装飾や複数シートは扱えませんが、構造が単純で軽量なため、大量データのエクスポートやシステム間連携に向いています。

見た目を整えた帳票や複数シートが必要なら.xlsx、古いExcel資産との互換性が必要なら.xls、単純なデータ連携ならCSV、という使い分けが基本です。

1-5. Excelがインストールされていない環境でも操作できるのか

ClosedXML、EPPlus、NPOI、Open XML SDKなどのライブラリを使えば、Excelがインストールされていない環境でもExcelファイルを作成・編集できます。これは、Excelアプリケーションを起動するのではなく、Excelファイルの中身を直接読み書きする仕組みだからです。

一方、Microsoft.Office.Interop.Excelを使う場合は、ExcelアプリケーションをCOM経由で操作します。そのため、実行環境にExcelが必要になるだけでなく、サーバーサイドでの利用には注意が必要です。MicrosoftはOffice製品のサーバーサイド自動化を推奨・サポートしていないと明記しています。

Webアプリやバッチ処理、サーバー環境でExcelを扱うなら、基本的にはInteropではなく、ClosedXMLなどのライブラリを選ぶのが安全です。

2. C#でExcelを操作する主な方法

2-1. Microsoft.Office.Interop.Excelを使う方法

Microsoft.Office.Interop.Excelは、C#からExcelアプリケーションを操作する方法です。Excelを実際に起動し、ブックを開き、セルを操作し、保存する流れになります。

Excelの操作に近い感覚で使えるため、VBA経験者には理解しやすい面があります。また、Excel本体の機能を使うため、既存のマクロや複雑なExcel機能と組み合わせたい場合に候補になります。

ただし、実行環境にExcelが必要です。また、Excelプロセスが残る、権限設定で失敗する、サーバー環境で不安定になる、といった問題が起きやすいです。特にASP.NETなどのWebアプリケーションで使うのは避けた方がよいでしょう。MicrosoftもサーバーサイドでのOffice自動化を推奨していません。

2-2. ClosedXMLを使う方法

ClosedXMLは、C#で.xlsxや.xlsmファイルを読み書きしやすくするライブラリです。Open XML SDKを扱いやすくしたようなAPIで、セル、シート、行、列、スタイルを直感的に操作できます。公式にも、Excel 2007以降の.xlsx、.xlsmファイルを読み書き・操作する.NETライブラリと説明されています。

ClosedXMLの基本コードは次のようにシンプルです。

C#
using ClosedXML.Excel;

using var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Sample");

worksheet.Cell("A1").Value = "Hello Excel";
worksheet.Cell("B1").Value = 100;

workbook.SaveAs("sample.xlsx");

初心者がC#でExcel操作を学ぶなら、まずClosedXMLから始めるのがおすすめです。Excelが入っていない環境でも使いやすく、セル指定やスタイル設定のコードも読みやすいためです。

2-3. EPPlusを使う方法

EPPlusは、.NET向けのExcel操作ライブラリです。.xlsxファイルの作成、読み込み、更新、計算などに対応しています。公式サイトでは、.NET Framework/.NET Core向けのスプレッドシートライブラリとして紹介されています。

EPPlusは機能が豊富で、パフォーマンス面でも選ばれることがあります。ただし、ライセンスには注意が必要です。EPPlus 8は非商用向けのCommunity Licenseと商用ライセンスの二重ライセンスモデルで、個人・非商用利用は無料ですが、商用利用では商用ライセンスが必要と説明されています。

業務システムで使う場合は、導入前に必ずライセンス条件を確認しましょう。

2-4. NPOIを使う方法

NPOIは、JavaのApache POIを.NET向けに移植したライブラリです。.xlsxだけでなく、古い.xls形式も扱える点が特徴です。GitHubでは、Office 2003/2007ファイルを読み書きできる.NET版Apache POIプロジェクトとして説明されています。

古い社内システムから出力される.xlsを読み込みたい場合や、.xls形式での出力が求められる場合は、NPOIが候補になります。

一方で、ClosedXMLと比べるとコードがやや低レベルになりやすく、初心者には少し難しく感じることがあります。.xls対応が不要であれば、まずはClosedXMLを検討するとよいでしょう。

2-5. Open XML SDKを使う方法

Open XML SDKは、Microsoft系のOpen XML形式を直接扱うためのSDKです。Excelだけでなく、WordやPowerPointのOpen XML文書も扱えます。NuGetのDocumentFormat.OpenXmlは、Word、Excel、PowerPoint文書を厳密に型付けされた.NET APIで扱うための中核ライブラリと説明されています。

Open XML SDKは細かい制御ができる一方で、セルやスタイルの操作コードが複雑になりやすいです。初心者がいきなり使うより、ClosedXMLなどを使ってExcel操作の流れを理解してから学ぶ方がスムーズです。

2-6. 有料ライブラリを使う方法

商用システムでは、有料のExcel操作ライブラリを使う選択肢もあります。代表的には、Aspose.Cells、DioDocs for Excel、IronXL、Spire.XLSなどがあります。

有料ライブラリは、サポート、機能の豊富さ、帳票出力、PDF変換、大量データ処理、グラフ、画像、ピボットテーブルなどに強い場合があります。業務要件が複雑で、無料ライブラリだけでは実装が難しい場合は検討する価値があります。

ただし、コストが発生するため、必要な機能、ライセンス形態、サーバー利用可否、サポート範囲を比較して選びましょう。

2-7. 初心者にはどの方法がおすすめか

初心者に最もおすすめしやすいのはClosedXMLです。理由は、コードがわかりやすく、Excelがインストールされていない環境でも扱いやすく、読み込み・書き込み・新規作成・スタイル設定といった基本操作を一通り学べるからです。

選び方の目安は次のとおりです。

目的おすすめ
初めてC#でExcel操作を学ぶClosedXML
.xlsxを簡単に読み書きしたいClosedXML
商用で高機能な処理をしたいEPPlusまたは有料ライブラリ
.xlsを扱いたいNPOI
Open XMLを細かく制御したいOpen XML SDK
Excel本体の機能を直接操作したいInterop。ただしサーバー利用は非推奨

まずはClosedXMLで基本を覚え、要件に応じてEPPlus、NPOI、Open XML SDK、有料ライブラリを検討するとよいでしょう。

3. C#向けExcel操作ライブラリの比較

3-1. 各ライブラリの特徴一覧

C#でExcelを操作する主な方法を比較すると、次のようになります。

方法特徴Excel本体主な対応形式初心者向け
Microsoft.Office.Interop.ExcelExcelアプリをCOM操作する必要.xlsx、.xlsなど
ClosedXML.xlsxを直感的に読み書きできる不要.xlsx、.xlsm
EPPlus高機能な.xlsx操作が可能不要.xlsx
NPOI.xlsにも対応しやすい不要.xls、.xlsx
Open XML SDKOpen XMLを直接操作できる不要.xlsxなど
有料ライブラリ帳票、PDF変換、大量データなどに強い不要製品による

C#でExcel操作を始める段階では、まず「Excel本体が必要かどうか」「.xls対応が必要か」「商用利用できるライセンスか」を確認しましょう。

3-2. 読み込みに向いているライブラリ

.xlsxファイルの読み込みなら、ClosedXMLが使いやすいです。セルの値をGetString()GetValue<T>()で取得でき、行や列のループも書きやすいです。

大量データを高速に読み込む必要がある場合は、EPPlusやOpen XML SDK、軽量な読み込み専用ライブラリも候補になります。古い.xlsファイルを読み込むならNPOIが選択肢になります。

初心者が「まずExcelからデータを読み込む」処理を作るなら、ClosedXMLで十分です。

3-3. 書き込み・新規作成に向いているライブラリ

新しいExcelファイルを作成してデータを書き込む用途でも、ClosedXMLは扱いやすいです。

C#
using ClosedXML.Excel;

using var workbook = new XLWorkbook();
var ws = workbook.Worksheets.Add("一覧");

ws.Cell(1, 1).Value = "商品名";
ws.Cell(1, 2).Value = "価格";

ws.Cell(2, 1).Value = "ノートPC";
ws.Cell(2, 2).Value = 120000;

workbook.SaveAs("products.xlsx");

セル番地を文字列で指定できるため、Excelを手作業で操作する感覚に近いコードを書けます。表形式のデータを出力する場合も、行番号と列番号をループで指定すれば簡単です。

3-4. 帳票出力に向いているライブラリ

帳票出力では、テンプレートExcelを用意しておき、C#から必要な値だけを差し込む方法が実用的です。

たとえば、請求書テンプレートのB3セルに顧客名、B4セルに請求日、E10セルに合計金額を入れるような処理です。デザインはExcel側で調整できるため、プログラム側の修正を減らせます。

ClosedXMLはテンプレート読み込みとセルへの値設定が簡単なので、帳票出力にも向いています。複雑な帳票、PDF変換、画像、グラフ、印刷制御まで求める場合は、有料ライブラリも検討しましょう。

3-5. .xls対応が必要な場合の選び方

.xls対応が必要な場合は、NPOIを検討します。ClosedXMLやEPPlusは主に.xlsx向けのライブラリであり、古い.xlsファイルを直接扱う用途には向きません。

ただし、可能であれば.xlsを.xlsxへ移行することも検討しましょう。.xlsxの方が現在のExcel環境で扱いやすく、ライブラリ選択の幅も広がります。

どうしても取引先や既存システムの都合で.xlsが必要な場合は、NPOIを使う、または有料ライブラリで.xls対応を確認する、という選び方になります。

3-6. 商用利用時に注意したいライセンス

C#のExcel操作ライブラリを業務システムに導入する場合、ライセンス確認は必須です。

ClosedXMLはGitHub上でMITライセンスとして公開されています。 Open XML SDKもMITライセンスです。 一方でEPPlusは、個人・非商用利用は無料ですが、商用利用では商用ライセンスが必要とされています。

同じ「無料で使えるライブラリ」に見えても、商用利用の条件は異なります。会社のプロジェクトで使う場合は、NuGetページ、GitHub、公式サイトのライセンス表記を確認し、必要に応じて法務部門やプロジェクト責任者にも確認しましょう。

3-7. Windowsアプリ・Webアプリ・サーバー環境での選び方

Windowsデスクトップアプリで、利用者のPCにExcelがインストールされている前提なら、Interopも選択肢になります。ただし、Excelプロセスの解放や例外時の後始末には注意が必要です。

Webアプリやサーバー環境では、Interopは避けましょう。MicrosoftがサーバーサイドOffice自動化を推奨・サポートしていないためです。

Webアプリ、API、バッチ、クラウド環境でExcelを扱うなら、ClosedXML、EPPlus、NPOI、Open XML SDK、有料ライブラリのようにExcel本体を必要としない方法を選ぶのが基本です。

4. C#でExcel操作する開発環境の準備

4-1. Visual Studioでプロジェクトを作成する

まず、Visual StudioでC#のプロジェクトを作成します。学習用であれば、コンソールアプリが最も簡単です。

手順は次のとおりです。

  1. Visual Studioを起動する

  2. 「新しいプロジェクトの作成」を選ぶ

  3. 「コンソール アプリ」を選ぶ

  4. プロジェクト名を入力する

  5. .NETのバージョンを選択して作成する

最初はコンソールアプリでExcelファイルを作成・読み込みできるようにしてから、WindowsアプリやWebアプリに応用すると理解しやすくなります。

4-2. NuGetでExcel操作ライブラリを追加する

ClosedXMLを使う場合は、NuGetからパッケージを追加します。

Visual Studioの場合は、プロジェクトを右クリックして「NuGetパッケージの管理」を開き、「ClosedXML」を検索してインストールします。

.NET CLIを使う場合は、次のコマンドで追加できます。ClosedXML公式ドキュメントでも、dotnet add package ClosedXMLでインストールする例が示されています。

Bash
dotnet add package ClosedXML

インストール後、C#ファイルの先頭に次のusingを追加します。

C#
using ClosedXML.Excel;

4-3. サンプル用Excelファイルを用意する

読み込み処理を試す場合は、次のようなExcelファイルを用意します。

ファイル名はsample.xlsx、シート名は売上とします。

日付商品名数量単価
2026/6/1ノートPC2120000
2026/6/2マウス52500
2026/6/3キーボード38000

このように、1行目をヘッダー行、2行目以降をデータ行にしておくと、C#で読み込みやすくなります。

4-4. usingの追加と基本コードの書き方

ClosedXMLを使う基本コードは次の形です。

C#
using ClosedXML.Excel;

var filePath = @"C:\Work\sample.xlsx";

using var workbook = new XLWorkbook(filePath);
var worksheet = workbook.Worksheet("売上");

var value = worksheet.Cell("A1").GetString();

Console.WriteLine(value);

XLWorkbookでExcelブックを開き、Worksheetでシートを取得し、Cellでセルを指定します。

using varを使うことで、処理が終わったときにリソースを自動的に解放できます。Excelファイル操作では、ファイルの解放漏れを防ぐためにもusingを使う習慣をつけましょう。

4-5. 実行前に確認すべきファイルパスと権限

Excelファイル操作でエラーが起きた場合、まず確認すべきなのはファイルパスです。

次の点を確認しましょう。

・指定したフォルダが存在するか
・ファイル名や拡張子が間違っていないか
・相対パスではなく絶対パスで試したか
・保存先フォルダに書き込み権限があるか
・対象ファイルをExcelで開いたままにしていないか
・Webアプリの場合、アプリケーション実行ユーザーに権限があるか

特にWebアプリでは、開発者のユーザー権限ではなく、アプリケーションプールや実行プロセスの権限でファイルにアクセスします。そのため、ローカルでは動くのにサーバーでは失敗することがあります。

5. C#でExcelファイルを読み込む方法

5-1. Excelファイルを開く基本コード

ClosedXMLでExcelファイルを開く基本コードは次のとおりです。

C#
using ClosedXML.Excel;

var filePath = @"C:\Work\sample.xlsx";

using var workbook = new XLWorkbook(filePath);
var worksheet = workbook.Worksheet(1);

Console.WriteLine(worksheet.Cell("A1").GetString());

Worksheet(1)は一番左のシートを取得します。シート番号は1から始まる点に注意してください。

5-2. シートを指定して読み込む

シート名で指定する場合は、次のように書きます。

C#
using var workbook = new XLWorkbook(@"C:\Work\sample.xlsx");

var worksheet = workbook.Worksheet("売上");
var title = worksheet.Cell("A1").GetString();

Console.WriteLine(title);

シート名が存在しない場合は例外が発生します。ユーザーがアップロードしたExcelを扱う場合は、事前にシート名の存在チェックを行うと安全です。

C#
var sheetName = "売上";

if (!workbook.Worksheets.Contains(sheetName))
{
Console.WriteLine("指定したシートが見つかりません。");
return;
}

var worksheet = workbook.Worksheet(sheetName);

5-3. セルの値を取得する

セルの値は、セル番地または行番号・列番号で取得できます。

C#
var value1 = worksheet.Cell("A1").GetString();
var value2 = worksheet.Cell(1, 1).GetString();

Console.WriteLine(value1);
Console.WriteLine(value2);

Cell("A1")はExcelのセル番地に近く、直感的です。ループ処理ではCell(row, column)の方が扱いやすくなります。

数値として取得したい場合は、次のように書けます。

C#
var quantity = worksheet.Cell("C2").GetValue<int>();
var price = worksheet.Cell("D2").GetValue<decimal>();

5-4. 行・列をループして一覧データを読み込む

一覧データを読み込む場合は、使用範囲を取得して行をループします。

C#
using ClosedXML.Excel;

using var workbook = new XLWorkbook(@"C:\Work\sample.xlsx");
var worksheet = workbook.Worksheet("売上");

var range = worksheet.RangeUsed();

foreach (var row in range.RowsUsed().Skip(1))
{
var date = row.Cell(1).GetDateTime();
var productName = row.Cell(2).GetString();
var quantity = row.Cell(3).GetValue<int>();
var price = row.Cell(4).GetValue<decimal>();

Console.WriteLine($"{date:yyyy/MM/dd} {productName} {quantity} {price}");
}

Skip(1)はヘッダー行を読み飛ばすために使っています。Skipを使うには、次のusingも追加します。

C#
using System.Linq;

5-5. ヘッダー行付きの表データを読み込む

列の順番が変わる可能性がある場合は、ヘッダー名から列番号を特定する方法が便利です。

C#
using ClosedXML.Excel;

using var workbook = new XLWorkbook(@"C:\Work\sample.xlsx");
var ws = workbook.Worksheet("売上");

var headerRow = ws.Row(1);

int productCol = 0;
int quantityCol = 0;

foreach (var cell in headerRow.CellsUsed())
{
if (cell.GetString() == "商品名")
{
productCol = cell.Address.ColumnNumber;
}

if (cell.GetString() == "数量")
{
quantityCol = cell.Address.ColumnNumber;
}
}

foreach (var row in ws.RowsUsed().Skip(1))
{
var productName = row.Cell(productCol).GetString();
var quantity = row.Cell(quantityCol).GetValue<int>();

Console.WriteLine($"{productName}: {quantity}");
}

この方法なら、Excel側で列順が少し変わっても、ヘッダー名が同じであれば読み込めます。

5-6. 数値・文字列・日付の型変換に注意する

Excelのセルは見た目と実際の値が異なることがあります。たとえば「00123」という商品コードをExcelが数値として扱うと、先頭の0が消えてしまいます。

商品コード、郵便番号、電話番号のように計算しない値は、C#側では文字列として扱うのが安全です。

C#
var code = worksheet.Cell("A2").GetString();

日付は、Excel側の入力形式によって変換に失敗する場合があります。確実に日付として取得できる前提ならGetDateTime()を使えます。

C#
var orderDate = worksheet.Cell("A2").GetDateTime();

ユーザー入力のExcelでは、日付に見えても文字列の場合があるため、実務では変換チェックを入れると安全です。

C#
var text = worksheet.Cell("A2").GetString();

if (DateTime.TryParse(text, out var date))
{
Console.WriteLine(date.ToString("yyyy/MM/dd"));
}
else
{
Console.WriteLine("日付として変換できません。");
}

5-7. 空白セルや結合セルを扱うときの注意点

空白セルを読み込むと、空文字やnull相当の値として扱われることがあります。必須項目であれば、読み込み時に空白チェックを入れましょう。

C#
var productName = worksheet.Cell("B2").GetString();

if (string.IsNullOrWhiteSpace(productName))
{
Console.WriteLine("商品名が未入力です。");
}

結合セルにも注意が必要です。Excel上では複数セルにまたがって表示されていても、値が入っているのは結合範囲の左上セルだけであることが多いです。データ取り込み用Excelでは、できるだけ結合セルを使わず、1行1データ、1列1項目の形式にするのがおすすめです。

6. C#でExcelファイルに書き込む方法

6-1. 既存のExcelファイルを編集する基本コード

既存のExcelファイルを開いて値を書き込み、別名で保存する基本コードです。

C#
using ClosedXML.Excel;

var inputPath = @"C:\Work\template.xlsx";
var outputPath = @"C:\Work\output.xlsx";

using var workbook = new XLWorkbook(inputPath);
var worksheet = workbook.Worksheet("Sheet1");

worksheet.Cell("A1").Value = "更新しました";

workbook.SaveAs(outputPath);

テンプレートを壊したくない場合は、元ファイルを直接上書きせず、別名で保存するのがおすすめです。

6-2. 指定したセルに値を書き込む

セルに値を書き込むには、Valueに代入します。

C#
worksheet.Cell("A1").Value = "商品名";
worksheet.Cell("B1").Value = "数量";
worksheet.Cell("C1").Value = "単価";

worksheet.Cell("A2").Value = "ノートPC";
worksheet.Cell("B2").Value = 2;
worksheet.Cell("C2").Value = 120000;

セル番地ではなく、行番号と列番号で指定することもできます。

C#
worksheet.Cell(1, 1).Value = "商品名";
worksheet.Cell(2, 1).Value = "ノートPC";

6-3. 行を追加してデータを書き込む

ListなどのデータをExcelに書き込む場合は、行番号を増やしながらループします。

C#
var products = new[]
{
new { Name = "ノートPC", Quantity = 2, Price = 120000 },
new { Name = "マウス", Quantity = 5, Price = 2500 },
new { Name = "キーボード", Quantity = 3, Price = 8000 }
};

int row = 2;

foreach (var product in products)
{
worksheet.Cell(row, 1).Value = product.Name;
worksheet.Cell(row, 2).Value = product.Quantity;
worksheet.Cell(row, 3).Value = product.Price;
worksheet.Cell(row, 4).Value = product.Quantity * product.Price;

row++;
}

ヘッダー行を1行目に作り、データは2行目から書き込む形にすると、読みやすいExcelになります。

6-4. DataTableやListの内容をExcelに書き込む

List<T>をExcelに出力する場合は、プロパティを列に対応させて書き込みます。

C#
public class Product
{
public string Name { get; set; } = "";
public int Quantity { get; set; }
public decimal Price { get; set; }
}

var products = new List<Product>
{
new Product { Name = "ノートPC", Quantity = 2, Price = 120000 },
new Product { Name = "マウス", Quantity = 5, Price = 2500 }
};

worksheet.Cell(1, 1).Value = "商品名";
worksheet.Cell(1, 2).Value = "数量";
worksheet.Cell(1, 3).Value = "単価";

for (int i = 0; i < products.Count; i++)
{
worksheet.Cell(i + 2, 1).Value = products[i].Name;
worksheet.Cell(i + 2, 2).Value = products[i].Quantity;
worksheet.Cell(i + 2, 3).Value = products[i].Price;
}

DataTableを使っている場合も、列名と行データをループして出力できます。

6-5. 複数シートにデータを書き込む

複数シートを作成する場合は、Worksheets.Addを複数回呼び出します。

C#
using var workbook = new XLWorkbook();

var salesSheet = workbook.Worksheets.Add("売上");
salesSheet.Cell("A1").Value = "売上一覧";

var summarySheet = workbook.Worksheets.Add("集計");
summarySheet.Cell("A1").Value = "月次集計";

workbook.SaveAs(@"C:\Work\report.xlsx");

部署別、月別、カテゴリ別などでシートを分けると、利用者が見やすいExcelを作成できます。

6-6. 上書き保存と別名保存の違い

上書き保存は、元のファイルをそのまま更新します。別名保存は、元ファイルを残したまま新しいファイルとして保存します。

既存ファイルを編集して上書きする場合は、次のように保存できます。

C#
workbook.Save();

別名で保存する場合は、次のようにします。

C#
workbook.SaveAs(@"C:\Work\output.xlsx");

実務では、テンプレートファイルを開いて別名保存するケースが多いです。テンプレートを上書きしてしまうと、次回以降の出力に影響するため注意しましょう。

6-7. 書き込み時にファイルが開けない場合の対処法

Excelファイルに書き込めない場合は、次を確認します。

・出力先ファイルをExcelで開いていないか
・保存先フォルダが存在するか
・書き込み権限があるか
・同名ファイルが読み取り専用になっていないか
・ファイルパスに使えない文字が含まれていないか
・別プロセスがファイルを使用中ではないか

特に「ファイルが使用中」のエラーはよく起きます。上書き保存ではなく、日時付きのファイル名で別名保存する方法も有効です。

C#
var fileName = $"売上一覧_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
var outputPath = Path.Combine(@"C:\Work", fileName);

workbook.SaveAs(outputPath);

7. C#でExcelファイルを新規作成・出力する方法

7-1. 新しいExcelファイルを作成する

新規Excelファイルを作成する最小コードは次のとおりです。

C#
using ClosedXML.Excel;

using var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Sheet1");

worksheet.Cell("A1").Value = "新しいExcelファイルです";

workbook.SaveAs(@"C:\Work\newfile.xlsx");

new XLWorkbook()で空のブックを作成し、シートを追加してから保存します。

7-2. ワークシートを追加する

ワークシートはWorksheets.Addで追加します。

C#
var ws1 = workbook.Worksheets.Add("売上");
var ws2 = workbook.Worksheets.Add("商品");
var ws3 = workbook.Worksheets.Add("顧客");

シート名には、Excelで使えない文字を含めないようにしましょう。また、同じブック内でシート名は重複できません。

7-3. セルにデータを出力する

セルにデータを出力する基本は、Valueへの代入です。

C#
worksheet.Cell("A1").Value = "日付";
worksheet.Cell("B1").Value = "商品名";
worksheet.Cell("C1").Value = "金額";

worksheet.Cell("A2").Value = DateTime.Today;
worksheet.Cell("B2").Value = "ノートPC";
worksheet.Cell("C2").Value = 240000;

日付や金額は、表示形式も設定すると見やすくなります。

C#
worksheet.Cell("A2").Style.DateFormat.Format = "yyyy/mm/dd";
worksheet.Cell("C2").Style.NumberFormat.Format = "#,##0";

7-4. 一覧表をExcelとして出力する

一覧表を出力する場合は、ヘッダー行を作成し、データ行をループで書き込みます。

C#
worksheet.Cell(1, 1).Value = "No";
worksheet.Cell(1, 2).Value = "商品名";
worksheet.Cell(1, 3).Value = "数量";
worksheet.Cell(1, 4).Value = "単価";
worksheet.Cell(1, 5).Value = "金額";

int row = 2;
int no = 1;

foreach (var item in sales)
{
worksheet.Cell(row, 1).Value = no;
worksheet.Cell(row, 2).Value = item.ProductName;
worksheet.Cell(row, 3).Value = item.Quantity;
worksheet.Cell(row, 4).Value = item.UnitPrice;
worksheet.Cell(row, 5).Value = item.Quantity * item.UnitPrice;

row++;
no++;
}

最後に罫線や列幅を整えると、実務でそのまま使いやすいExcelになります。

7-5. テンプレートExcelを使って帳票を出力する

請求書や見積書のような帳票は、Excelテンプレートを用意しておくと便利です。

C#
using var workbook = new XLWorkbook(@"C:\Work\invoice_template.xlsx");
var ws = workbook.Worksheet("請求書");

ws.Cell("B3").Value = "株式会社サンプル";
ws.Cell("B4").Value = DateTime.Today;
ws.Cell("E20").Value = 150000;

workbook.SaveAs(@"C:\Work\invoice_output.xlsx");

帳票デザインはExcel上で調整し、C#側では値の差し込みに集中できます。見た目の変更が発生しても、テンプレートを修正するだけで対応しやすくなります。

7-6. WebアプリでExcelをダウンロード出力する

ASP.NET CoreなどのWebアプリでは、Excelファイルをメモリ上に作成し、ダウンロードレスポンスとして返せます。

C#
using ClosedXML.Excel;
using Microsoft.AspNetCore.Mvc;

public IActionResult Download()
{
using var workbook = new XLWorkbook();
var ws = workbook.Worksheets.Add("売上");

ws.Cell("A1").Value = "商品名";
ws.Cell("B1").Value = "金額";
ws.Cell("A2").Value = "ノートPC";
ws.Cell("B2").Value = 240000;

using var stream = new MemoryStream();
workbook.SaveAs(stream);

var content = stream.ToArray();
var fileName = "sales.xlsx";

return File(
content,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
fileName
);
}

Webアプリでは、サーバー上に一時ファイルを残さず、メモリ上でExcelを作成して返す方法がよく使われます。

7-7. CSV出力とExcel出力の使い分け

CSV出力は実装が簡単で、ファイルサイズも軽く、大量データに向いています。一方、見た目の装飾、複数シート、セルの書式、数式、罫線などは扱えません。

Excel出力は、見た目を整えた帳票や、利用者がそのまま編集・確認する資料に向いています。ただし、CSVよりファイル構造が複雑で、処理も重くなりやすいです。

単純なデータ連携ならCSV、利用者向けの帳票やレポートならExcel、という使い分けがおすすめです。

8. Excelの見た目を整える方法

8-1. フォント・文字サイズ・太字を設定する

ClosedXMLでは、セルのスタイルを簡単に設定できます。

C#
var cell = worksheet.Cell("A1");

cell.Value = "売上一覧";
cell.Style.Font.Bold = true;
cell.Style.Font.FontSize = 16;
cell.Style.Font.FontName = "メイリオ";

見出しやタイトルは、太字や文字サイズを設定すると見やすくなります。

8-2. 背景色や文字色を設定する

背景色や文字色は、ヘッダー行を目立たせるときによく使います。

C#
var header = worksheet.Range("A1:E1");

header.Style.Fill.BackgroundColor = XLColor.LightGray;
header.Style.Font.FontColor = XLColor.Black;
header.Style.Font.Bold = true;

色を使いすぎると読みにくくなるため、タイトル行やヘッダー行など、重要な箇所に絞るのがおすすめです。

8-3. 罫線を設定する

一覧表には罫線を設定すると、Excelらしい見た目になります。

C#
var tableRange = worksheet.Range("A1:E10");

tableRange.Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
tableRange.Style.Border.InsideBorder = XLBorderStyleValues.Thin;

データ範囲が動的に変わる場合は、最終行を変数で管理します。

C#
var range = worksheet.Range(1, 1, lastRow, 5);
range.Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
range.Style.Border.InsideBorder = XLBorderStyleValues.Thin;

8-4. 列幅や行の高さを自動調整する

列幅を自動調整するには、次のように書きます。

C#
worksheet.Columns().AdjustToContents();

特定の列だけ調整することもできます。

C#
worksheet.Column(1).AdjustToContents();
worksheet.Column(2).Width = 30;

日本語の長い文字列がある場合は、列幅を固定で少し広めに設定した方が見やすいこともあります。

8-5. セルの表示形式を設定する

日付、金額、パーセントなどは表示形式を設定します。

C#
worksheet.Cell("A2").Style.DateFormat.Format = "yyyy/mm/dd";
worksheet.Cell("C2").Style.NumberFormat.Format = "#,##0";
worksheet.Cell("D2").Style.NumberFormat.Format = "0.0%";

金額にカンマ区切りを設定すると、業務資料として見やすくなります。

8-6. セル結合や中央寄せを設定する

タイトルを複数列にまたがって表示したい場合は、セル結合を使います。

C#
worksheet.Range("A1:E1").Merge();
worksheet.Cell("A1").Value = "売上一覧";
worksheet.Cell("A1").Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
worksheet.Cell("A1").Style.Font.Bold = true;
worksheet.Cell("A1").Style.Font.FontSize = 16;

ただし、データ取り込み用のExcelでは結合セルは避けた方がよいです。帳票の見た目を整える用途に限定して使いましょう。

8-7. フィルターや固定行を設定する

一覧表では、ヘッダー行にフィルターを設定すると便利です。

C#
worksheet.Range("A2:E10").SetAutoFilter();

ヘッダー行を固定する場合は、次のように書きます。

C#
worksheet.SheetView.FreezeRows(2);

タイトル行とヘッダー行を固定しておくと、データが多いExcelでも見やすくなります。

9. 実践サンプル:C#で売上一覧をExcel出力する

9-1. 作成するサンプルの完成イメージ

ここでは、C#で売上一覧をExcel出力するサンプルを作成します。

出力するExcelは、次のような構成です。

No日付商品名数量単価金額
12026/6/1ノートPC2120000240000
22026/6/2マウス5250012500
32026/6/3キーボード3800024000

最後に合計金額を出力し、ヘッダー、罫線、列幅、表示形式を整えます。

9-2. 売上データ用のクラスを作成する

まず、売上データを表すクラスを作成します。

C#
public class Sale
{
public DateTime Date { get; set; }
public string ProductName { get; set; } = "";
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }

public decimal Amount => Quantity * UnitPrice;
}

Amountは数量と単価から計算する読み取り専用プロパティにしています。

9-3. データをExcelに書き込む

次に、売上データを用意し、Excelに書き込みます。

C#
var sales = new List<Sale>
{
new Sale { Date = new DateTime(2026, 6, 1), ProductName = "ノートPC", Quantity = 2, UnitPrice = 120000 },
new Sale { Date = new DateTime(2026, 6, 2), ProductName = "マウス", Quantity = 5, UnitPrice = 2500 },
new Sale { Date = new DateTime(2026, 6, 3), ProductName = "キーボード", Quantity = 3, UnitPrice = 8000 }
};

Excelへの書き込みは、行番号を増やしながら行います。

C#
int row = 3;
int no = 1;

foreach (var sale in sales)
{
ws.Cell(row, 1).Value = no;
ws.Cell(row, 2).Value = sale.Date;
ws.Cell(row, 3).Value = sale.ProductName;
ws.Cell(row, 4).Value = sale.Quantity;
ws.Cell(row, 5).Value = sale.UnitPrice;
ws.Cell(row, 6).Value = sale.Amount;

row++;
no++;
}

9-4. 見出し行と罫線を設定する

見出し行を作成し、太字、背景色、中央寄せを設定します。

C#
ws.Cell("A1").Value = "売上一覧";
ws.Range("A1:F1").Merge();
ws.Cell("A1").Style.Font.Bold = true;
ws.Cell("A1").Style.Font.FontSize = 16;
ws.Cell("A1").Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;

ws.Cell(2, 1).Value = "No";
ws.Cell(2, 2).Value = "日付";
ws.Cell(2, 3).Value = "商品名";
ws.Cell(2, 4).Value = "数量";
ws.Cell(2, 5).Value = "単価";
ws.Cell(2, 6).Value = "金額";

var headerRange = ws.Range("A2:F2");
headerRange.Style.Font.Bold = true;
headerRange.Style.Fill.BackgroundColor = XLColor.LightGray;
headerRange.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;

罫線は、データ範囲全体に設定します。

C#
var tableRange = ws.Range(2, 1, row - 1, 6);
tableRange.Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
tableRange.Style.Border.InsideBorder = XLBorderStyleValues.Thin;

9-5. 合計金額を計算して出力する

合計金額はC#側で計算して出力します。

C#
var total = sales.Sum(x => x.Amount);

ws.Cell(row, 5).Value = "合計";
ws.Cell(row, 6).Value = total;

ws.Range(row, 5, row, 6).Style.Font.Bold = true;
ws.Range(row, 5, row, 6).Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
ws.Range(row, 5, row, 6).Style.Border.InsideBorder = XLBorderStyleValues.Thin;

Excelの数式を使いたい場合は、FormulaA1を設定する方法もあります。

C#
ws.Cell(row, 6).FormulaA1 = $"=SUM(F3:F{row - 1})";

9-6. Excelファイルとして保存する

最後に、列幅や表示形式を整えて保存します。

C#
ws.Column(2).Style.DateFormat.Format = "yyyy/mm/dd";
ws.Columns(5, 6).Style.NumberFormat.Format = "#,##0";

ws.Columns().AdjustToContents();
ws.SheetView.FreezeRows(2);

workbook.SaveAs(@"C:\Work\sales.xlsx");

金額列にはカンマ区切り、日付列には日付形式を設定しています。

9-7. サンプルコード全文

以下が、売上一覧をExcel出力するサンプルコード全文です。

C#
using ClosedXML.Excel;
using System;
using System.Collections.Generic;
using System.Linq;

public class Sale
{
public DateTime Date { get; set; }
public string ProductName { get; set; } = "";
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }

public decimal Amount => Quantity * UnitPrice;
}

public class Program
{
public static void Main()
{
var sales = new List<Sale>
{
new Sale { Date = new DateTime(2026, 6, 1), ProductName = "ノートPC", Quantity = 2, UnitPrice = 120000 },
new Sale { Date = new DateTime(2026, 6, 2), ProductName = "マウス", Quantity = 5, UnitPrice = 2500 },
new Sale { Date = new DateTime(2026, 6, 3), ProductName = "キーボード", Quantity = 3, UnitPrice = 8000 }
};

using var workbook = new XLWorkbook();
var ws = workbook.Worksheets.Add("売上一覧");

ws.Cell("A1").Value = "売上一覧";
ws.Range("A1:F1").Merge();
ws.Cell("A1").Style.Font.Bold = true;
ws.Cell("A1").Style.Font.FontSize = 16;
ws.Cell("A1").Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;

ws.Cell(2, 1).Value = "No";
ws.Cell(2, 2).Value = "日付";
ws.Cell(2, 3).Value = "商品名";
ws.Cell(2, 4).Value = "数量";
ws.Cell(2, 5).Value = "単価";
ws.Cell(2, 6).Value = "金額";

var headerRange = ws.Range("A2:F2");
headerRange.Style.Font.Bold = true;
headerRange.Style.Fill.BackgroundColor = XLColor.LightGray;
headerRange.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;

int row = 3;
int no = 1;

foreach (var sale in sales)
{
ws.Cell(row, 1).Value = no;
ws.Cell(row, 2).Value = sale.Date;
ws.Cell(row, 3).Value = sale.ProductName;
ws.Cell(row, 4).Value = sale.Quantity;
ws.Cell(row, 5).Value = sale.UnitPrice;
ws.Cell(row, 6).Value = sale.Amount;

row++;
no++;
}

var total = sales.Sum(x => x.Amount);

ws.Cell(row, 5).Value = "合計";
ws.Cell(row, 6).Value = total;

var tableRange = ws.Range(2, 1, row, 6);
tableRange.Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
tableRange.Style.Border.InsideBorder = XLBorderStyleValues.Thin;

ws.Range(row, 5, row, 6).Style.Font.Bold = true;

ws.Column(2).Style.DateFormat.Format = "yyyy/mm/dd";
ws.Columns(5, 6).Style.NumberFormat.Format = "#,##0";

ws.Columns().AdjustToContents();
ws.SheetView.FreezeRows(2);

workbook.SaveAs(@"C:\Work\sales.xlsx");

Console.WriteLine("Excelファイルを出力しました。");
}
}

このサンプルを実行すると、指定したフォルダにsales.xlsxが作成されます。保存先フォルダが存在しない場合はエラーになるため、事前にC:\Workを作成しておきましょう。

10. C#でExcel操作するときのよくあるエラーと対処法

10-1. ファイルが使用中で保存できない

ExcelファイルをExcelアプリで開いたままC#から上書き保存しようとすると、保存に失敗することがあります。

対処法は次のとおりです。

・対象ファイルを閉じる
・別名で保存する
・日時付きファイル名にする
・一時ファイルに保存してから置き換える
・Webアプリではユーザーごとにファイル名を分ける

上書き保存より、別名保存や一時ファイル出力の方が安全です。

10-2. ファイルパスが見つからない

「ファイルが見つからない」エラーの多くは、パスの指定ミスです。

C#
var filePath = @"C:\Work\sample.xlsx";

C#では、Windowsパスの\を扱うために、文字列の前に@を付けると書きやすくなります。

相対パスを使う場合は、実行時のカレントディレクトリがどこかを確認しましょう。初心者のうちは絶対パスで動作確認するのがおすすめです。

10-3. セルの値がnullになる

セルの値がnullまたは空になる場合は、次を確認します。

・セル番地が間違っていないか
・シート名が正しいか
・ヘッダー行とデータ行を取り違えていないか
・結合セルの左上以外を読んでいないか
・Excel上では数式だが計算結果が空ではないか

空白セルを許可しない項目では、次のようにチェックします。

C#
var value = worksheet.Cell("A2").GetString();

if (string.IsNullOrWhiteSpace(value))
{
Console.WriteLine("A2セルが空です。");
}

10-4. 日付や数値の表示がおかしい

Excel出力後に日付や数値の表示がおかしい場合は、表示形式を設定します。

C#
worksheet.Cell("A2").Style.DateFormat.Format = "yyyy/mm/dd";
worksheet.Cell("B2").Style.NumberFormat.Format = "#,##0";

数値を文字列として書き込むと、Excel上で計算できない場合があります。計算したい値は数値型として書き込み、商品コードや郵便番号のように先頭ゼロが必要な値は文字列として書き込みましょう。

10-5. 日本語が文字化けする

.xlsxファイルをClosedXMLなどで扱う場合、日本語が文字化けすることは多くありません。文字化けが起きやすいのはCSV出力です。

CSVで日本語を扱う場合は、文字コードに注意します。Excelで開く前提なら、BOM付きUTF-8やShift_JISを検討します。

C#
using System.Text;

File.WriteAllText(@"C:\Work\data.csv", csvText, new UTF8Encoding(true));

Excel出力とCSV出力では、文字コードの考え方が異なる点を理解しておきましょう。

10-6. サーバー環境でExcel操作が失敗する

サーバー環境でExcel操作が失敗する場合、Interopを使っていないか確認しましょう。Officeアプリケーションのサーバーサイド自動化はMicrosoftが推奨・サポートしていません。

サーバーでExcelファイルを生成する場合は、ClosedXML、EPPlus、NPOI、Open XML SDK、有料ライブラリなど、Excel本体を起動しない方法を選ぶのが基本です。

また、サーバーでは保存先フォルダの権限にも注意が必要です。アプリケーションの実行ユーザーに書き込み権限があるかを確認しましょう。

10-7. InteropでExcelプロセスが残る

Interopを使うと、処理終了後にExcelプロセスが残ることがあります。原因は、COMオブジェクトの解放漏れです。

Interopを使う場合は、Workbookを閉じる、Applicationを終了する、COMオブジェクトを解放する、例外時にもfinallyで後処理する、といった対応が必要です。

ただし、これらを正しく実装してもサーバーサイドでは問題が起きやすいため、新規開発ではClosedXMLなどExcel本体を使わない方法を優先しましょう。

11. C#でExcel操作する際の注意点とベストプラクティス

11-1. Interopをサーバーサイドで使うべきではない理由

InteropはExcelアプリケーションを自動操作する仕組みです。デスクトップで人が使うExcelをプログラムから操作するイメージに近いため、サーバー環境とは相性がよくありません。

サーバーでは、同時実行、権限、ユーザープロファイル、ダイアログ表示、プロセス残留などの問題が発生しやすくなります。MicrosoftがサーバーサイドOffice自動化を推奨・サポートしていない点も重要です。

Webアプリやバッチ処理では、Excel本体を起動しないライブラリを使いましょう。

11-2. 大量データを扱うときのパフォーマンス対策

大量データをExcelに出力する場合は、次の点に注意します。

・セルごとに過剰なスタイル設定をしない
・範囲単位でスタイルを設定する
・不要な数式や結合セルを減らす
・一度に大量のブックを開かない
・必要なデータだけ出力する
・CSV出力で十分ならCSVを選ぶ

数十万行のデータを見た目付きExcelとして出力すると、ファイルサイズも処理時間も大きくなります。利用者が本当にExcelで見る必要があるのか、CSVやデータベース検索で代替できないかも検討しましょう。

11-3. usingでリソースを正しく解放する

Excelファイルを扱うときは、usingを使ってリソースを解放しましょう。

C#
using var workbook = new XLWorkbook(filePath);

using varを使えば、スコープを抜けたタイミングで自動的に破棄されます。ファイルがロックされたままになる問題を防ぎやすくなります。

ストリームを使う場合も同様です。

C#
using var stream = new MemoryStream();
workbook.SaveAs(stream);

11-4. ファイル名・保存先・権限を安全に扱う

ユーザー入力をそのままファイル名に使うのは避けましょう。ファイル名に使えない文字が含まれているとエラーになります。また、意図しないパスに保存される危険もあります。

安全なファイル名を作るには、システム側で固定名や日時を付けます。

C#
var fileName = $"report_{DateTime.Now:yyyyMMddHHmmss}.xlsx";

保存先は、アプリケーションが書き込み可能な専用フォルダにします。Webアプリでは、一時ファイルを作成した後に削除する運用も重要です。

11-5. 例外処理を入れて安全に実装する

Excel操作では、ファイルが存在しない、権限がない、形式が不正、セルの値を変換できない、といった例外が起こります。

最低限、ファイル操作の周辺には例外処理を入れましょう。

C#
try
{
using var workbook = new XLWorkbook(@"C:\Work\sample.xlsx");
var ws = workbook.Worksheet("売上");

Console.WriteLine(ws.Cell("A1").GetString());
}
catch (FileNotFoundException)
{
Console.WriteLine("ファイルが見つかりません。");
}
catch (Exception ex)
{
Console.WriteLine($"エラーが発生しました: {ex.Message}");
}

実務では、ログ出力も合わせて行うと原因調査がしやすくなります。

11-6. 保守しやすいコードに分割する

Excel操作のコードを1つのメソッドに詰め込みすぎると、後から修正しにくくなります。

たとえば、次のように役割を分けると保守しやすくなります。

・データ取得処理
・Excelブック作成処理
・ヘッダー作成処理
・データ行出力処理
・スタイル設定処理
・保存処理

帳票ごとにクラスを分けるのも有効です。Excelの列番号やセル番地は定数化しておくと、レイアウト変更にも対応しやすくなります。

11-7. テンプレートを使って帳票修正に強くする

帳票の見た目が頻繁に変わる場合は、C#で全てのレイアウトを組むより、Excelテンプレートを使う方が保守しやすいです。

テンプレート方式では、罫線、色、ロゴ、印刷範囲、余白などをExcel側で作り、C#側では必要なセルに値を差し込みます。

C#
using var workbook = new XLWorkbook("template.xlsx");
var ws = workbook.Worksheet("帳票");

ws.Cell("B3").Value = "顧客名";
ws.Cell("E10").Value = 100000;

workbook.SaveAs("output.xlsx");

帳票デザインの変更をプログラム修正なしで対応しやすくなるため、実務では非常に有効です。

12. C#のExcel操作に関するよくある質問

12-1. C#でExcelなしでもExcelファイルを作成できますか

はい、作成できます。ClosedXML、EPPlus、NPOI、Open XML SDKなどを使えば、Excelアプリケーションをインストールしていない環境でもExcelファイルを作成できます。ClosedXML公式ドキュメントでも、ExcelアプリケーションなしでExcelファイルを作成できると説明されています。

Webアプリやサーバー環境では、Excel本体を起動するInteropではなく、これらのライブラリを使うのがおすすめです。

12-2. 無料で使えるおすすめライブラリはどれですか

初心者にはClosedXMLがおすすめです。コードが読みやすく、セル操作、シート操作、書式設定、Excel出力の基本を学びやすいためです。ClosedXMLはMITライセンスとして公開されています。

ただし、ライセンスは変更される可能性があるため、業務利用前には必ず公式情報を確認してください。

12-3. .xlsファイルは読み書きできますか

.xlsファイルを扱いたい場合は、NPOIが候補になります。NPOIはOffice 2003/2007ファイルを読み書きできる.NETライブラリとして説明されています。

一方、ClosedXMLやEPPlusは主に.xlsx向けです。.xlsが不要であれば、.xlsxに統一した方がライブラリ選択や保守が楽になります。

12-4. Excelマクロ付きファイルは扱えますか

マクロ付きExcelファイルは、拡張子が.xlsmです。ライブラリによっては.xlsmを開いて保存できる場合がありますが、マクロの編集や実行まで対応できるとは限りません。

マクロを実行したい場合はExcel本体が必要になることが多く、サーバー環境では推奨されません。マクロに依存しない帳票設計に変更できるなら、C#側で処理を実装して.xlsxとして出力する方が安全です。

12-5. WebアプリからExcelをダウンロードできますか

はい、できます。ASP.NET Coreでは、ClosedXMLでExcelをメモリ上に作成し、Fileメソッドで返すことでダウンロードできます。

C#
return File(
content,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"report.xlsx"
);

Webアプリでは、サーバーにExcelをインストールする必要がないライブラリを使うのが基本です。

12-6. ClosedXMLとEPPlusはどちらを選べばよいですか

初心者や一般的な.xlsxの読み書きであれば、ClosedXMLがおすすめです。シンプルなコードでExcel操作を始められます。

EPPlusは機能が豊富ですが、商用利用時のライセンス確認が重要です。EPPlusは個人・非商用利用は無料ですが、商用利用では商用ライセンスが必要と説明されています。

学習や小規模なExcel出力から始めるならClosedXML、高機能な要件やサポートを重視するならEPPlusや有料ライブラリを検討するとよいでしょう。

12-7. Excel操作とCSV出力はどちらが簡単ですか

実装の簡単さだけでいえば、CSV出力の方が簡単です。テキストをカンマ区切りで作成するだけなので、ライブラリなしでも実装できます。

ただし、CSVでは罫線、背景色、複数シート、セル結合、表示形式などは扱えません。利用者が見やすい帳票を求める場合はExcel出力が向いています。

データ連携や大量データ出力ならCSV、見た目を整えたレポートや帳票ならExcel、と考えると選びやすくなります。

まとめ

C#でExcelを操作する方法には、Microsoft.Office.Interop.Excel、ClosedXML、EPPlus、NPOI、Open XML SDK、有料ライブラリなどがあります。初心者が最初に学ぶなら、Excel本体が不要でコードも書きやすいClosedXMLがおすすめです。

C#でExcel操作を行う基本の流れは、Excelファイルを開く、シートを取得する、セルを読み書きする、必要に応じてスタイルを設定する、保存する、というものです。読み込みではシート名やセル番地、型変換、空白セルに注意しましょう。書き込みや出力では、上書き保存と別名保存、ファイルパス、権限、ファイル使用中のエラーに注意が必要です。

Webアプリやサーバー環境では、Interopではなく、ClosedXMLなどExcelをインストールせずに使えるライブラリを選びましょう。MicrosoftもサーバーサイドでのOffice自動化を推奨・サポートしていません。

まずは小さなコンソールアプリで、Excelファイルの読み込み、セルへの書き込み、新規作成、一覧表の出力を試してみるのが近道です。基本を理解できれば、売上一覧、請求書、在庫表、集計レポート、WebアプリからのExcelダウンロードなど、実務で役立つさまざまなExcel処理に応用できます。