C#でExcel出力する方法完全ガイド|ライブラリ選び・帳票作成・エラー対策まで解説

はじめに

C#でExcel出力を実装する場面は、業務システムやWebアプリ開発で非常に多くあります。売上一覧、請求書、見積書、勤怠表、在庫表、集計レポートなど、ユーザーがExcelで確認・加工したいデータを出力する機能は、多くのシステムで求められます。

ただし、C#でExcel出力する方法は1つではありません。ClosedXML、EPPlus、NPOI、Open XML SDK、Microsoft Office Interopなど複数の選択肢があり、それぞれ特徴やライセンス、向いている用途が異なります。

この記事では、C#でExcel出力する方法を基礎から実装例、ライブラリ選び、帳票作成、大量データ対応、よくあるエラー対策までまとめて解説します。

1. C#でExcel出力する方法の全体像

1-1. C#でExcel出力が必要になる主な場面

C#でExcel出力が必要になる代表的な場面は、次のようなケースです。

業務システムでは、検索結果や一覧データをExcelでダウンロードしたいという要望がよくあります。画面上では確認しにくい大量データも、Excelに出力すればフィルター、並べ替え、集計、印刷がしやすくなります。

また、請求書、納品書、見積書、発注書などの帳票をExcel形式で作成するケースもあります。PDFではなくExcelで出力することで、担当者が後から微調整できる点がメリットです。

管理画面や社内システムでは、売上レポート、月次集計、在庫一覧、勤怠データ、ユーザー一覧などをExcelファイルとして出力する機能がよく使われます。

1-2. Excel出力で実現できること

C#のExcel出力では、単にセルへ文字や数値を書き込むだけでなく、さまざまな表現が可能です。

たとえば、見出し行の背景色を変更する、罫線を引く、列幅を自動調整する、日付や金額の表示形式を設定する、複数シートを作成する、数式を埋め込む、テンプレートExcelを読み込んで帳票を作る、といった処理ができます。

ライブラリによっては、画像挿入、シート保護、印刷設定、セル結合、フィルター設定、テーブル化などにも対応できます。

1-3. Excel出力の代表的な実装パターン

C#でExcel出力する方法は、大きく分けると次の3パターンです。

1つ目は、ライブラリを使ってxlsxファイルを直接生成する方法です。ClosedXML、EPPlus、NPOI、Open XML SDKなどがこの方式に該当します。Excelアプリをインストールしなくても出力できるため、Webアプリやサーバー環境でよく使われます。

2つ目は、既存のExcelテンプレートを読み込み、必要なセルに値を差し込んで保存する方法です。請求書や見積書など、レイアウトが決まっている帳票に向いています。

3つ目は、Microsoft Office Interopを使ってExcelアプリケーションを操作する方法です。ただし、サーバー環境では推奨されないことが多く、基本的にはデスクトップアプリ向けの選択肢と考えるべきです。

1-4. この記事で解説する範囲

この記事では、C#でExcelファイルを出力する実用的な方法を中心に解説します。

特に、初心者でも扱いやすく、Webアプリや業務システムでも利用しやすいClosedXMLを中心に、基本的なExcel出力の実装例を紹介します。

あわせて、EPPlus、NPOI、Open XML SDK、Microsoft Office Interopとの違い、ライブラリ選びの考え方、大量データ出力時の注意点、よくあるエラーの解決策についても取り上げます。

2. C#でExcel出力する前に知っておきたい基礎知識

2-1. xlsx・xls・csvの違い

C#でExcel出力を考えるときは、まずファイル形式の違いを理解しておく必要があります。

xlsxは、Excel 2007以降で標準的に使われている形式です。複数シート、セル書式、罫線、数式、画像、印刷設定などを扱えます。現在のExcel出力では、基本的にxlsx形式を選ぶのが一般的です。

xlsは、Excel 97〜2003で使われていた古い形式です。古いシステムとの互換性が必要な場合に使われますが、行数や列数の制限がxlsxより小さく、新規開発では積極的に選ぶ理由は多くありません。

csvは、カンマ区切りのテキストファイルです。Excelで開くことはできますが、セルの装飾、複数シート、数式、罫線などは保持できません。一方で、軽量で大量データに強く、他システムとの連携に向いています。

2-2. Excelファイルを直接生成する方法とExcelアプリを操作する方法の違い

C#でExcel出力する方法には、Excelファイルそのものを生成する方法と、Excelアプリケーションを操作する方法があります。

Excelファイルを直接生成する方法では、ClosedXMLやEPPlusなどのライブラリを使い、プログラム上でxlsxファイルを作成します。この方法はExcelアプリをインストールする必要がなく、サーバー環境やクラウド環境でも使いやすいのが特徴です。

一方、Microsoft Office Interopを使う方法では、インストール済みのExcelをC#から操作します。Excelの機能を直接利用できる反面、Excelアプリケーションのインストールが必要で、プロセス管理や権限、安定性の問題が発生しやすくなります。

WebアプリやAPIでExcel出力する場合は、基本的にExcelアプリを操作する方法ではなく、ライブラリでファイルを直接生成する方法を選ぶのが安全です。

2-3. サーバー環境でExcel出力する際の注意点

ASP.NET CoreなどのWebアプリでExcel出力する場合、サーバー上でExcelアプリを起動する設計は避けるべきです。

サーバー環境では、同時アクセス、権限、プロセスの残存、UI操作の前提、メモリ使用量などが問題になりやすいためです。そのため、ClosedXMLやOpen XML SDKのように、Excelをインストールせずにxlsxファイルを生成できるライブラリを使うのが一般的です。ClosedXMLも、ExcelアプリなしでExcelファイルを作成できるライブラリとして説明されています。

2-4. .NET Framework・.NET Core・.NET 6以降での違い

C#でExcel出力を実装する際は、対象の.NET環境も確認しましょう。

.NET Frameworkの既存システムでは、昔から使われているNPOIやEPPlus、Interopが採用されているケースがあります。

一方、ASP.NET Coreや.NET 6以降では、Windows以外のLinuxサーバーやコンテナ環境で動かすことも多いため、OS依存の少ないライブラリを選ぶ必要があります。

ClosedXML、EPPlus、NPOI、Open XML SDKはいずれもNuGetから導入できますが、バージョンによって対応フレームワークやAPIが異なるため、導入前に公式ドキュメントとNuGetページを確認することが重要です。

2-5. 商用利用・ライセンス確認の重要性

Excel出力ライブラリを選ぶときは、機能だけでなくライセンス確認が必須です。

特にEPPlusは、バージョン5以降でライセンスモデルが変更され、非商用利用向けのPolyform Noncommercialと商用ライセンスのデュアルライセンスになっています。商用業務システムで利用する場合は、ライセンス条件を必ず確認する必要があります。

ClosedXMLは、Excel 2007以降のxlsx・xlsmファイルを扱えるライブラリとして公開されており、直感的なAPIでOpenXMLを扱える点が特徴です。

NPOIはApache POIの.NET版で、Office 2003/2007形式の読み書きに対応しています。

業務システムでは、「無料で使えるか」だけで判断せず、商用利用可否、サポート、保守性、将来のバージョンアップ方針まで確認して選定しましょう。

3. C#でExcel出力に使える主要ライブラリ比較

3-1. ClosedXMLの特徴と向いているケース

ClosedXMLは、C#でExcel出力を行う際に非常に使いやすいライブラリです。Open XML SDKを直接扱うよりも簡潔なコードで、セルへの値設定、書式設定、罫線、列幅調整、複数シート作成などを実装できます。

特に、業務システムの一覧出力、帳票出力、ASP.NET CoreでのExcelダウンロード機能に向いています。

ClosedXMLはExcelアプリを必要とせずにxlsxファイルを作成できるため、サーバー環境でも扱いやすい選択肢です。初心者がC#でExcel出力を始める場合は、まずClosedXMLを検討するとよいでしょう。

3-2. EPPlusの特徴とライセンス上の注意点

EPPlusは、高機能なExcel出力ライブラリです。セル操作、書式設定、グラフ、テーブル、ピボットテーブルなど、Excelらしい機能を幅広く扱えます。

ただし、EPPlusを業務システムで使う場合はライセンス確認が重要です。EPPlus 5以降は、非商用向けライセンスと商用ライセンスのデュアルライセンスになっており、商用利用ではライセンス購入が必要になるケースがあります。

既存プロジェクトでEPPlusを使っている場合も、バージョンと利用形態を確認しておきましょう。

3-3. NPOIの特徴とxls対応のメリット

NPOIは、Apache POIの.NET版として知られるライブラリです。xlsxだけでなく、古いxls形式にも対応しやすい点が特徴です。

既存システムでxls形式が必要な場合や、古いExcelファイルを読み書きする必要がある場合には、NPOIが選択肢になります。

一方で、ClosedXMLに比べるとコード量が多くなりやすく、初心者にはやや扱いにくい場面もあります。新規開発でxlsxだけを出力するなら、まずClosedXMLを検討し、xls対応が必要な場合にNPOIを候補にするとよいでしょう。

3-4. Open XML SDKの特徴と向いているケース

Open XML SDKは、Microsoftが提供するOfficeファイル操作用のSDKです。Excel、Word、PowerPointなどのOpen XML形式を低レベルに操作できます。Open XML SDKは、Open XMLパッケージやスキーマ要素の操作を支援するSDKとして提供されています。

細かい制御ができる反面、ClosedXMLのような高レベルAPIではないため、実装は複雑になりがちです。

大量データ出力や、xlsxファイル構造を細かく制御したい場合、ライブラリ依存を抑えたい場合には向いています。ただし、一般的な帳票出力や一覧出力では、ClosedXMLなどのラッパーライブラリのほうが開発効率は高くなります。

3-5. Microsoft Office Interopを使う場合の注意点

Microsoft Office Interopは、C#からExcelアプリケーションを操作する方法です。Excelの機能を直接使えるため、デスクトップアプリでユーザーのPC上にインストールされたExcelを操作する用途では使われることがあります。

しかし、Webサーバーやバッチサーバーでの利用には注意が必要です。Excelプロセスが残る、同時実行に弱い、権限エラーが起きる、サーバーにOfficeをインストールする必要があるなど、運用上の問題が発生しやすいためです。

サーバーサイドでC#のExcel出力を行う場合は、Interopではなく、ClosedXML、EPPlus、NPOI、Open XML SDKなどを使うのが基本です。

3-6. ライブラリ選びの比較表

ライブラリ主な対応形式特徴向いている用途
ClosedXMLxlsx、xlsmコードが簡潔で初心者にも扱いやすい一覧出力、帳票出力、Webアプリ
EPPlusxlsx高機能だが商用利用はライセンス確認が必要高度なExcel機能を使う帳票
NPOIxls、xlsx古いxls形式にも対応しやすい既存xls資産の活用
Open XML SDKxlsxなど低レベルで細かく制御できる大量データ、特殊な制御
Office InteropExcel依存Excelアプリを直接操作デスクトップアプリ向け

3-7. 初心者・業務システム・大量データ別のおすすめライブラリ

初心者がC#でExcel出力を学ぶなら、ClosedXMLがおすすめです。APIが直感的で、少ないコードでExcelファイルを作成できます。

業務システムで一覧表や帳票を出力する場合も、まずClosedXMLを検討するとよいでしょう。テンプレートExcelを読み込んで値を差し込む実装にも対応しやすく、保守性も高めやすいです。

xls形式が必要な場合はNPOI、大量データや低レベル制御が必要な場合はOpen XML SDK、グラフや高度なExcel機能を多用する場合はEPPlusを検討します。ただし、EPPlusはライセンス条件を必ず確認してください。

4. C#でExcel出力する基本手順

4-1. 開発環境とNuGetパッケージの準備

C#でExcel出力を始めるには、まずプロジェクトにExcel操作ライブラリを追加します。

ClosedXMLを使う場合は、Visual StudioのNuGetパッケージマネージャー、または.NET CLIでインストールできます。

Bash
dotnet add package ClosedXML

C#コードでは、次のusingを追加します。

C#
using ClosedXML.Excel;

ASP.NET CoreでExcel出力する場合も、基本的な使い方は同じです。作成したExcelファイルをファイルとして保存するか、メモリ上で作成してダウンロードレスポンスとして返します。

4-2. 新規Excelファイルを作成する

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

C#
using ClosedXML.Excel;

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

worksheet.Cell("A1").Value = "商品名";
worksheet.Cell("B1").Value = "金額";

workbook.SaveAs("sales.xlsx");

このコードでは、新しいExcelブックを作成し、「売上一覧」というシートを追加し、A1とB1に値を設定して保存しています。

4-3. セルに文字列・数値・日付を書き込む

Excel出力では、文字列、数値、日付を正しく扱うことが重要です。

C#
worksheet.Cell("A1").Value = "商品A";
worksheet.Cell("B1").Value = 1200;
worksheet.Cell("C1").Value = DateTime.Today;

数値は文字列としてではなく数値として設定することで、Excel上で集計や計算ができます。日付もDateTimeとして設定すれば、Excel側で日付として扱えます。

表示形式を指定したい場合は、Style.NumberFormat.Formatを使います。

C#
worksheet.Cell("B1").Style.NumberFormat.Format = "#,##0";
worksheet.Cell("C1").Style.NumberFormat.Format = "yyyy/mm/dd";

4-4. DataTableやListからExcelに出力する

業務システムでは、データベースから取得したDataTableやListをExcelに出力することが多くあります。

Listを使った例は次のとおりです。

C#
public class SalesItem
{
public string ProductName { get; set; } = "";
public int Quantity { get; set; }
public decimal Amount { get; set; }
}

var items = new List<SalesItem>
{
new SalesItem { ProductName = "商品A", Quantity = 2, Amount = 2400 },
new SalesItem { ProductName = "商品B", Quantity = 1, Amount = 1500 }
};

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

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

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

workbook.SaveAs("sales.xlsx");

見出し行を1行目に出力し、2行目以降にデータを出力する形にすると、一覧表として扱いやすくなります。

4-5. ファイルとして保存する

ローカルやサーバー上にExcelファイルを保存する場合は、SaveAsを使います。

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

保存先フォルダが存在しない場合や、アプリケーションに書き込み権限がない場合はエラーになります。Webアプリでは、サーバー上に一時ファイルとして保存するよりも、MemoryStreamに保存してそのままダウンロードさせる方法がよく使われます。

4-6. WebアプリでExcelファイルをダウンロードさせる

ASP.NET CoreでExcelファイルをダウンロードさせる場合は、MemoryStreamを使います。

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

public IActionResult DownloadExcel()
{
using var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("売上一覧");

worksheet.Cell("A1").Value = "商品名";
worksheet.Cell("B1").Value = "金額";
worksheet.Cell("A2").Value = "商品A";
worksheet.Cell("B2").Value = 1200;

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

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

Content-Typeには、xlsx用のMIMEタイプを指定します。ファイル名には日本語を使うこともできますが、ブラウザや環境によって文字化けする場合があるため注意しましょう。

5. ClosedXMLでExcel出力する実装例

5-1. ClosedXMLをインストールする

ClosedXMLを使うには、NuGetでパッケージを追加します。

Bash
dotnet add package ClosedXML

Visual Studioの場合は、「NuGetパッケージの管理」からClosedXMLを検索してインストールしても構いません。

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

C#
using ClosedXML.Excel;

5-2. 最小コードでExcelファイルを作成する

ClosedXMLでExcel出力する最小構成は次のとおりです。

C#
using ClosedXML.Excel;

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

sheet.Cell("A1").Value = "Hello Excel";

workbook.SaveAs("sample.xlsx");

このコードだけで、Excelアプリを起動せずにxlsxファイルを作成できます。

5-3. 見出し行とデータ行を出力する

一覧表を出力する場合は、見出し行とデータ行を明確に分けます。

C#
using var workbook = new XLWorkbook();
var sheet = workbook.Worksheets.Add("商品一覧");

sheet.Cell(1, 1).Value = "商品コード";
sheet.Cell(1, 2).Value = "商品名";
sheet.Cell(1, 3).Value = "単価";

var products = new[]
{
new { Code = "P001", Name = "ノート", Price = 120 },
new { Code = "P002", Name = "ペン", Price = 80 },
new { Code = "P003", Name = "ファイル", Price = 250 }
};

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

workbook.SaveAs("products.xlsx");

5-4. セル幅・罫線・背景色を設定する

Excel出力では、見た目を整えることでユーザーが使いやすいファイルになります。

C#
var headerRange = sheet.Range("A1:C1");
headerRange.Style.Font.Bold = true;
headerRange.Style.Fill.BackgroundColor = XLColor.LightGray;
headerRange.Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
headerRange.Style.Border.InsideBorder = XLBorderStyleValues.Thin;

var dataRange = sheet.Range("A1:C4");
dataRange.Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
dataRange.Style.Border.InsideBorder = XLBorderStyleValues.Thin;

sheet.Columns().AdjustToContents();

見出し行を太字にし、背景色を付け、罫線を設定すると、業務帳票らしい見た目になります。

5-5. 日付・通貨・小数点などの表示形式を設定する

Excelでは、値そのものと表示形式を分けて考える必要があります。

C#
sheet.Cell("A1").Value = DateTime.Today;
sheet.Cell("A1").Style.DateFormat.Format = "yyyy/mm/dd";

sheet.Cell("B1").Value = 1234567;
sheet.Cell("B1").Style.NumberFormat.Format = "#,##0";

sheet.Cell("C1").Value = 0.1234;
sheet.Cell("C1").Style.NumberFormat.Format = "0.00%";

金額や日付を文字列として出力してしまうと、Excel上で計算や並べ替えがしにくくなります。数値は数値、日付はDateTimeとして出力し、見た目は表示形式で調整しましょう。

5-6. 複数シートを作成する

1つのExcelブックに複数シートを作成することもできます。

C#
using var workbook = new XLWorkbook();

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

var stockSheet = workbook.Worksheets.Add("在庫");
stockSheet.Cell("A1").Value = "在庫一覧";

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

workbook.SaveAs("report.xlsx");

部署別、月別、カテゴリ別など、データを分けて出力したい場合に便利です。

5-7. ASP.NET CoreでExcelをダウンロード出力する

ASP.NET Core MVCやWeb APIでExcelをダウンロードさせる場合は、次のように実装します。

C#
[HttpGet]
public IActionResult Export()
{
using var workbook = new XLWorkbook();
var sheet = workbook.Worksheets.Add("レポート");

sheet.Cell("A1").Value = "日付";
sheet.Cell("B1").Value = "売上";
sheet.Cell("A2").Value = DateTime.Today;
sheet.Cell("B2").Value = 10000;

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

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

return File(
stream.ToArray(),
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"report.xlsx"
);
}

ポイントは、サーバーにファイルを保存せず、MemoryStreamで作成して返すことです。これにより、一時ファイルの削除漏れや保存先権限の問題を避けやすくなります。

6. 帳票・レポート作成でよく使うExcel出力テクニック

6-1. テンプレートExcelを読み込んで帳票を作成する

請求書や見積書のようにレイアウトが決まっている帳票では、テンプレートExcelを用意しておき、C#で値だけを差し込む方法が便利です。

C#
using var workbook = new XLWorkbook("template.xlsx");
var sheet = workbook.Worksheet("請求書");

sheet.Cell("B2").Value = "株式会社サンプル";
sheet.Cell("B3").Value = DateTime.Today;
sheet.Cell("E10").Value = 100000;

workbook.SaveAs("invoice.xlsx");

テンプレート方式にすると、デザイナーや業務担当者がExcel上でレイアウトを調整しやすくなります。プログラム側では、決められたセルに値を入れるだけで済むため、保守性も高くなります。

6-2. 請求書・見積書・一覧表を出力する

請求書や見積書では、宛先、発行日、明細、合計金額、消費税、振込先などを出力します。

一覧表では、検索条件、出力日時、見出し行、データ行、件数、合計などを出力すると実用的です。

帳票出力では、以下のような設計にしておくと変更に強くなります。

  • 固定レイアウトはExcelテンプレートで管理する

  • 明細行は開始行を決めてループ出力する

  • 合計欄は数式またはC#側の計算結果で出力する

  • 出力項目名とセル位置を定数化する

6-3. セル結合・中央揃え・折り返しを設定する

タイトルや備考欄では、セル結合や折り返しを使うことがあります。

C#
sheet.Range("A1:E1").Merge();
sheet.Cell("A1").Value = "売上レポート";
sheet.Cell("A1").Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
sheet.Cell("A1").Style.Font.Bold = true;
sheet.Cell("A1").Style.Font.FontSize = 16;

sheet.Cell("A5").Value = "備考:長い文章を折り返して表示します。";
sheet.Cell("A5").Style.Alignment.WrapText = true;

セル結合は見た目を整えるのに便利ですが、後からデータ加工しにくくなる場合もあります。一覧データ部分では多用せず、タイトルや帳票ヘッダーなどに限定するとよいでしょう。

6-4. 合計・小計・数式を出力する

Excel出力では、数式を埋め込むこともできます。

C#
sheet.Cell("A1").Value = "商品";
sheet.Cell("B1").Value = "金額";

sheet.Cell("A2").Value = "商品A";
sheet.Cell("B2").Value = 1000;

sheet.Cell("A3").Value = "商品B";
sheet.Cell("B3").Value = 2000;

sheet.Cell("A4").Value = "合計";
sheet.Cell("B4").FormulaA1 = "SUM(B2:B3)";

Excelを開いたときに再計算されるため、ユーザーが明細を編集した場合にも合計が変わります。

一方、帳票として金額を確定させたい場合は、C#側で計算した値を出力する方法もあります。業務要件に応じて使い分けましょう。

6-5. 画像やロゴを挿入する

会社ロゴや印影などをExcel帳票に入れたい場合は、画像挿入機能を使います。

ClosedXMLでは画像挿入に対応していますが、バージョンによってAPIが異なる場合があるため、使用しているバージョンのドキュメントを確認してください。

画像を使う場合は、ファイルパスの扱いに注意が必要です。Webアプリでは、実行環境によって相対パスの基準が変わることがあります。テンプレート内にあらかじめ画像を配置しておく方法も実用的です。

6-6. 印刷範囲・用紙サイズ・余白を設定する

Excelを印刷前提の帳票として出力する場合は、印刷設定も重要です。

C#
sheet.PageSetup.PageOrientation = XLPageOrientation.Portrait;
sheet.PageSetup.PaperSize = XLPaperSize.A4Paper;
sheet.PageSetup.Margins.Top = 0.5;
sheet.PageSetup.Margins.Bottom = 0.5;
sheet.PageSetup.Margins.Left = 0.5;
sheet.PageSetup.Margins.Right = 0.5;

sheet.PageSetup.PrintAreas.Add("A1:E30");

請求書や見積書では、A4縦1ページに収まるように列幅、行高、余白、印刷範囲を調整します。

6-7. パスワード保護やシート保護を設定する

Excelファイルでは、シート保護やブック保護を設定できます。

C#
sheet.Protect("password");

ただし、Excelのシート保護は強固な暗号化というより、誤編集を防ぐための機能として考えるべきです。個人情報や機密情報を含むファイルを扱う場合は、ファイルの保存場所、アクセス権限、ダウンロード期限、ログ管理なども含めて設計しましょう。

7. 大量データをExcel出力する際のパフォーマンス対策

7-1. 大量データ出力で処理が遅くなる原因

C#で大量データをExcel出力すると、処理時間やメモリ使用量が問題になることがあります。

主な原因は、セル単位で大量に書き込んでいる、スタイルをセルごとに設定している、列幅の自動調整を大量データに対して実行している、全データをメモリに保持している、といった点です。

特にxlsxは単なるテキストではなく、複数のXMLファイルをZIP形式でまとめた構造のため、CSVよりも生成コストが高くなります。

7-2. メモリ使用量を抑える実装ポイント

大量データを出力する場合は、まず出力対象データを必要最小限に絞りましょう。

画面表示用のデータとExcel出力用のデータを分け、不要な列や中間オブジェクトを持たないようにします。

また、DataTableにすべて詰めてからExcelに書き込むのではなく、必要に応じてデータを分割取得する設計も検討します。

7-3. セル単位の書き込みを減らす

大量データ出力では、セル単位の処理をできるだけ減らすことが重要です。

スタイル設定は、セルごとではなく範囲に対してまとめて設定します。

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

列幅の自動調整も便利ですが、大量データでは時間がかかる場合があります。必要な列だけに限定するか、固定幅にすることも検討しましょう。

7-4. ストリーミング出力を検討する

数十万行規模のExcel出力では、通常のライブラリ操作ではメモリ使用量が大きくなる場合があります。

このような場合は、Open XML SDKを使ったストリーミング出力や、大量データ向けのライブラリを検討します。

ただし、ストリーミング出力ではセルの装飾や後からの編集が制限されることもあります。見た目を重視する帳票なのか、データ量を重視する一覧出力なのかによって選択しましょう。

7-5. Excelの行数・列数制限に注意する

xlsx形式のExcelには、行数と列数の上限があります。Excelのワークシートは、最大で1,048,576行、16,384列です。

この上限を超えるデータを出力する場合、1シートに収まりません。複数シートに分割するか、CSV形式で出力するか、データ抽出条件を見直す必要があります。

業務システムでは、Excel出力ボタンを押したら全件出力できる設計にするのではなく、期間や条件で絞り込ませる設計も重要です。

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

大量データを出力するだけなら、Excel形式よりCSV形式のほうが適している場合があります。

CSVは装飾や複数シートには対応できませんが、軽量で生成が速く、他システム連携にも向いています。

一方、見出しの装飾、罫線、数式、複数シート、帳票レイアウトが必要な場合はxlsxを選びます。

つまり、データ抽出や連携用途ならCSV、ユーザーが見やすい帳票やレポートならExcel形式、という使い分けが基本です。

8. C#のExcel出力でよくあるエラーと解決策

8-1. ファイルが開けない・破損していると表示される

Excelファイルを開いたときに「ファイル形式または拡張子が正しくありません」「破損しています」と表示される場合があります。

原因として多いのは、xlsxとして保存すべきところで別形式の内容を返している、WebアプリのレスポンスにHTMLエラーが混ざっている、MemoryStreamの扱いを誤っている、ファイル書き込み途中で処理が中断している、といったケースです。

ASP.NET Coreでは、Content-Typeと拡張子を正しく指定しましょう。

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

また、例外発生時にエラーページのHTMLをxlsxとして返していないかも確認してください。

8-2. 日本語が文字化けする

xlsx形式では通常、日本語の文字化けは起きにくいです。文字化けが起きる場合は、CSV出力でエンコーディングが合っていないケースが多くあります。

CSVをExcelで開く前提なら、UTF-8 BOM付きやShift_JISなど、利用環境に合った文字コードを選ぶ必要があります。

xlsxでファイル名が文字化けする場合は、HTTPヘッダーやブラウザの扱いが原因のことがあります。ASP.NET CoreのFileメソッドを使う場合は、多くのケースで適切に処理されますが、独自にContent-Dispositionを設定している場合は見直しましょう。

8-3. 日付や数値の表示形式が崩れる

日付や数値が意図した形式で表示されない場合は、値の型と表示形式を確認します。

悪い例は、金額や日付をすべて文字列として出力することです。

C#
sheet.Cell("A1").Value = "2026/06/10";
sheet.Cell("B1").Value = "1,000";

この場合、Excel上で日付や数値として扱えないことがあります。

よい例は、DateTimeや数値として値を設定し、表示形式を指定する方法です。

C#
sheet.Cell("A1").Value = new DateTime(2026, 6, 10);
sheet.Cell("A1").Style.DateFormat.Format = "yyyy/mm/dd";

sheet.Cell("B1").Value = 1000;
sheet.Cell("B1").Style.NumberFormat.Format = "#,##0";

8-4. ファイル保存時にアクセス権限エラーが出る

サーバー上にExcelファイルを保存するときに、アクセス権限エラーが出ることがあります。

原因は、保存先フォルダが存在しない、アプリケーション実行ユーザーに書き込み権限がない、同名ファイルを別プロセスが開いている、パスが環境に合っていない、といったものです。

Webアプリでは、可能であればサーバーに保存せず、MemoryStreamで生成して直接ダウンロードさせる方法が安全です。保存が必要な場合は、一時フォルダ、ファイル名の一意性、削除処理、アクセス権限を設計しましょう。

8-5. ASP.NETでダウンロードできない

ASP.NET CoreでExcelをダウンロードできない場合は、次の点を確認します。

  • アクションメソッドがFileResultを返しているか

  • Content-Typeがxlsx用になっているか

  • stream.ToArray()の前にデータが保存されているか

  • 例外が発生してHTMLが返っていないか

  • JavaScript側でBlobとして正しく処理しているか

Ajaxでダウンロードする場合、通常の画面遷移ダウンロードとは実装が異なります。fetchやaxiosを使う場合は、responseTypeをblobにする必要があります。

8-6. Excelプロセスが残る

Excelプロセスが残る問題は、Microsoft Office Interopを使っている場合によく発生します。

Interopでは、Excel.Application、Workbook、WorksheetなどのCOMオブジェクトを適切に解放しないと、EXCEL.EXEが残ることがあります。

サーバー環境では、この問題が重大な障害につながることがあります。そのため、Webアプリやバッチ処理では、InteropではなくClosedXMLやOpen XML SDKなど、Excelアプリを起動しない方法を選ぶべきです。

8-7. ライブラリのバージョン違いによるエラー

Excel出力ライブラリは、バージョンによってAPIや依存パッケージが変わることがあります。

たとえば、古い記事のコードをコピーしたら現在のバージョンでは動かない、.NET Frameworkでは動いたが.NET 6ではエラーになる、といったケースがあります。

対策として、次の点を確認しましょう。

  • NuGetでインストールしたバージョン

  • 対応している.NETのバージョン

  • 公式ドキュメントの対象バージョン

  • 既存コードとの互換性

  • ライセンス変更の有無

特にEPPlusのようにライセンス条件がバージョンで変わったライブラリは、導入前に必ず確認が必要です。

9. C#でExcel出力する際の設計・運用の注意点

9-1. 業務ロジックとExcel出力処理を分離する

Excel出力処理の中に、売上計算や権限判定などの業務ロジックを直接書くと、保守しにくくなります。

理想的には、業務データを作成する処理と、Excelに書き込む処理を分けます。

C#
public class SalesReportRow
{
public string ProductName { get; set; } = "";
public int Quantity { get; set; }
public decimal Amount { get; set; }
}

このような出力用DTOを作り、Excel出力クラスはDTOを受け取ってファイル化するだけにすると、テストや修正がしやすくなります。

9-2. 出力項目の変更に強い設計にする

業務システムでは、「Excelにこの列を追加してほしい」「列の順番を変えてほしい」という変更がよくあります。

そのため、列番号をコード中に直接大量に書くと、変更時に修正漏れが起きやすくなります。

列定義を配列やクラスで管理する方法も有効です。

C#
var columns = new[]
{
new { Header = "商品名", Property = "ProductName" },
new { Header = "数量", Property = "Quantity" },
new { Header = "金額", Property = "Amount" }
};

単純な一覧出力であれば、列定義を共通化することで、複数のExcel出力機能を効率よく実装できます。

9-3. テンプレート管理の方法を決める

テンプレートExcelを使う場合は、テンプレートファイルをどこで管理するかを決めておく必要があります。

アプリケーションに同梱する、クラウドストレージに置く、管理画面からアップロード可能にするなど、運用方法によって設計が変わります。

テンプレートを業務担当者が編集する場合は、セル位置を変えるとプログラムが動かなくなる可能性があります。入力セルに名前付き範囲を設定する、変更可能範囲を限定する、テンプレートのバージョン管理を行う、といった対策が有効です。

9-4. テストしやすいExcel出力処理にする

Excel出力処理は、画面で確認するだけではテストが不十分です。

ファイルが生成されるか、シート名が正しいか、見出しが正しいか、行数が合っているか、数式が入っているか、日付や数値が正しい型で出力されているかをテストできるようにしましょう。

ClosedXMLを使えば、生成したExcelファイルを再度読み込んでセルの値を確認するテストも書けます。

C#
using var workbook = new XLWorkbook("report.xlsx");
var sheet = workbook.Worksheet("売上一覧");

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

9-5. セキュリティと個人情報の取り扱いに注意する

Excel出力では、個人情報や機密情報を含むファイルが生成されることがあります。

注意すべきポイントは、出力権限、出力ログ、一時ファイルの削除、ダウンロードURLの有効期限、ファイル名、メール添付時の誤送信などです。

また、ユーザーが入力した値をExcelに出力する場合、先頭が「=」「+」「-」「@」で始まる文字列は、Excelで数式として解釈される可能性があります。外部入力をそのままExcelに出す場合は、必要に応じてエスケープや文字列化を検討しましょう。

9-6. クラウド・コンテナ環境での注意点

クラウドやコンテナ環境では、ローカルファイルシステムに永続保存できない、フォントが不足している、パスがWindowsと異なる、同時実行数が多い、といった問題が起きることがあります。

Excel出力処理では、Windows固有のパスを書かない、MemoryStreamを活用する、一時ファイルは確実に削除する、フォント依存のレイアウトに注意する、といった設計が重要です。

DockerやLinux環境で動かす場合は、事前に本番に近い環境でExcelファイルを生成し、文字幅や表示崩れを確認しておきましょう。

10. C#のExcel出力に関するよくある質問

10-1. C#でExcelをインストールせずに出力できますか?

はい、できます。

ClosedXML、EPPlus、NPOI、Open XML SDKなどを使えば、ExcelアプリをインストールせずにExcelファイルを生成できます。Webアプリやサーバー環境では、Excelアプリを操作する方法ではなく、これらのライブラリを使う方法が一般的です。

10-2. 無料で使えるExcel出力ライブラリはありますか?

ありますが、無料で使えるかどうかはライセンスと利用目的によります。

ClosedXMLやNPOIなどは選択肢になりますが、導入前に必ず最新のライセンスを確認してください。

EPPlusは高機能なライブラリですが、バージョン5以降は非商用利用と商用利用でライセンス条件が異なります。商用システムで使う場合は特に注意が必要です。

10-3. ClosedXMLとEPPlusはどちらを選ぶべきですか?

一般的な一覧出力や帳票出力であれば、まずClosedXMLを検討するとよいでしょう。コードがわかりやすく、初心者にも扱いやすいからです。

一方で、EPPlusは高度なExcel機能に対応しており、グラフやテーブルなどを多用する場合に候補になります。ただし、商用利用ではライセンス確認が必要です。

判断基準としては、シンプルな業務帳票ならClosedXML、高度なExcel機能が必要ならEPPlus、ライセンスやサポート条件を含めて比較する、という考え方が現実的です。

10-4. WebアプリでもExcel出力できますか?

はい、ASP.NET CoreなどのWebアプリでもExcel出力できます。

ClosedXMLでExcelファイルをMemoryStreamに保存し、Fileメソッドでxlsxファイルとして返せば、ブラウザからダウンロードできます。

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

Webアプリでは、サーバーにExcelをインストールする方法ではなく、Excelファイルを直接生成するライブラリを使うのが基本です。

10-5. Excelテンプレートを使った帳票作成はできますか?

できます。

あらかじめExcelでテンプレートを作成し、C#で読み込んで必要なセルに値を差し込むことで、請求書、見積書、納品書などの帳票を作成できます。

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

sheet.Cell("B2").Value = "取引先名";
sheet.Cell("E5").Value = DateTime.Today;

workbook.SaveAs("output.xlsx");

テンプレート方式は、レイアウト変更をExcel側で行いやすい点がメリットです。

10-6. 大量データの出力にはどの方法が向いていますか?

大量データを出力する場合は、データ量と目的によって選びます。

見た目よりもデータ量を優先するならCSV出力が向いています。軽量で高速に出力しやすいためです。

Excel形式が必要で、数万行程度の一覧出力であればClosedXMLでも対応できるケースがあります。ただし、スタイル設定や自動列幅調整を多用すると遅くなるため注意が必要です。

さらに大規模なデータをxlsxで出力する場合は、Open XML SDKを使ったストリーミング出力などを検討します。

まとめ

C#でExcel出力する方法には、ClosedXML、EPPlus、NPOI、Open XML SDK、Microsoft Office Interopなど複数の選択肢があります。

初心者や一般的な業務システムでは、Excelアプリをインストールせずに使えて、コードも書きやすいClosedXMLが有力な選択肢です。ASP.NET CoreでExcelをダウンロードさせる場合も、MemoryStreamに保存してFileメソッドで返すことで実装できます。

一方で、古いxls形式が必要ならNPOI、低レベルで細かく制御したいならOpen XML SDK、高度なExcel機能を使いたいならEPPlusも候補になります。ただし、EPPlusを含め、ライブラリを商用利用する場合は必ず最新のライセンスを確認しましょう。

C#のExcel出力では、単にファイルを作るだけでなく、表示形式、罫線、テンプレート、帳票レイアウト、大量データ対応、エラー対策、セキュリティまで考慮することが大切です。用途に合ったライブラリを選び、業務ロジックと出力処理を分離して設計すれば、保守しやすく実用的なExcel出力機能を実装できます。