Stack Overflow には数か月おきに同じ質問が投稿されます。 「WinForms アプリで Excel ファイルを表示するにはどうすればよいですか?」 回答はだいたい 3 種類に分かれます — Office を自動化する(やめておきましょう)、WebBrowser でファイルを開く(やめておきましょう)、スプレッドシートコンポーネントを使う(本記事の内容です)。
.xlsx ファイルをデスクトップアプリの中で実際に 表示 し、できれば 編集 して、保存し直す 必要があるなら、本記事が WinForms / WPF でゼロから動作するビューアまでの最短経路です。
「表示する」とは具体的に何を意味するのか
アプローチを選ぶ前に、ユーザーが本当に求めているものを明確にしておく価値があります。要望には次の 4 段階があります。
- 読み取り専用プレビュー — 既知のシートの値を表示する。書式や数式は不要。
- 忠実なビューア — Excel と同じようにワークブックを描画する: フォント、塗りつぶし、罫線、結合セル、複数シート、ウィンドウ枠の固定。
- ライブエディタ — セルをクリックして入力させ、数式の再計算を見せ、
.xlsxに保存し直す。 - スプレッドシートホスト — アプリ自体がスプレッドシートで、独自コマンドや付随データを持つ。
レベル 1〜2 は DataGridView が向かないタスクです。レベル 3〜4 はあらゆる データグリッド が向かないタスクです。必要なのはスプレッドシートコンポーネント — Excel と同じ方法でセルを描画し、.xlsx 形式をネイティブに理解するコントロールです。
やってはいけないこと
ウェブでよく見かけるものの避けた方がよいアプローチが 3 つあります。
Microsoft.Office.Interop.Excel— 実際の Excel プロセスを COM 経由で自動操作します。ユーザーのマシンすべてに Excel がインストールされていることが必要で、サービス上ではサポートされず、そして UI を自分のフォームに 埋め込む こともできません。- WebBrowser でファイルを開く — Excel をプロセス外で開くか、オンラインなら OneDrive のウェブビューアが表示されます。10 分間は動くように見えますが、Office が入っていない最初のマシンで破綻します。
- 列ヘッダー付き DataGridView — フラットなレコードリストには使えます。ですが、ファイルに数式・結合セル・複数シートが現れた瞬間に破綻します。DataGridView が力不足になるタイミングについては この記事 を参照してください。
実際に必要なアプローチは、ワークブック自体を描画するコントロールです。本記事では ReoGrid を例にします — 同じ形のコードはどのスプレッドシートコンポーネントでも通用しますが、ReoGrid は弊社製品で、無料利用枠が最も寛容です。
WinForms: 読み込み・表示・保存
全体でおよそ 15 行です。
1. NuGet パッケージのインストール:
PM> Install-Package unvell.ReoGrid.dll
2. フォームに ReoGridControl を配置 します(Visual Studio のツールボックスから、もしくはコードから)。
3. 読み込みと保存:
using unvell.ReoGrid;
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void openButton_Click(object sender, EventArgs e)
{
using var dlg = new OpenFileDialog { Filter = "Excel Workbook|*.xlsx" };
if (dlg.ShowDialog() != DialogResult.OK) return;
reoGridControl1.Load(dlg.FileName); // .xlsx を読み込み、完全に描画される。
}
private void saveButton_Click(object sender, EventArgs e)
{
using var dlg = new SaveFileDialog { Filter = "Excel Workbook|*.xlsx" };
if (dlg.ShowDialog() != DialogResult.OK) return;
reoGridControl1.Save(dlg.FileName); // ユーザーの編集内容がそのまま往復する。
}
}
これだけです。ユーザーはファイルを開き、フォント・塗りつぶし・罫線がそのまま反映された状態でワークブックを見て、任意のセルをクリックして入力し、依存する数式が再計算されるのを目視で確認し、下部のタブでシートを切り替え、保存できます。外部プロセスも不要、Office のインストールも不要、WebBrowser のハックも不要です。
WPF: 考え方は同じ、パッケージが違うだけ
1. WPF 用パッケージのインストール:
PM> Install-Package unvell.ReoGridWPF.dll
2. XAML で名前空間を参照し、コントロールを配置:
<Window x:Class="ExcelViewerWpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:rg="clr-namespace:unvell.ReoGrid;assembly=unvell.ReoGrid"
Title="Excel Viewer" Height="600" Width="900">
<DockPanel>
<ToolBar DockPanel.Dock="Top">
<Button Content="Open" Click="OpenButton_Click"/>
<Button Content="Save" Click="SaveButton_Click"/>
</ToolBar>
<rg:ReoGridControl x:Name="Grid"/>
</DockPanel>
</Window>
3. コードビハインド:
using Microsoft.Win32;
using unvell.ReoGrid;
public partial class MainWindow : Window
{
public MainWindow() => InitializeComponent();
private void OpenButton_Click(object sender, RoutedEventArgs e)
{
var dlg = new OpenFileDialog { Filter = "Excel Workbook|*.xlsx" };
if (dlg.ShowDialog() != true) return;
Grid.Load(dlg.FileName);
}
private void SaveButton_Click(object sender, RoutedEventArgs e)
{
var dlg = new SaveFileDialog { Filter = "Excel Workbook|*.xlsx" };
if (dlg.ShowDialog() != true) return;
Grid.Save(dlg.FileName);
}
}
WinForms 版と WPF 版のコントロールは API が同一で、違うのは参照するアセンブリだけです。両方の UI をメンテナンスする場合でも、ロジックを共有する余地が残されています。
「完全に描画される」とは何を意味するのか
ファイルを読み込めば、ユーザーは DataGridView では失われていたものを得られます。
- フォント・塗りつぶし・罫線 — Excel と同じ描画
- 結合セル — ヘッダー内の結合も含む
- 複数ワークシート — 下部にタブバー付き
- 数式 — セルに
=SUM(A1:A10)と入力すれば、内蔵の数式エンジンで即座に再計算 - 数値・日付・通貨・パーセント書式 —
.xlsx元ファイルからそのまま維持 - 行/列の固定 — ファイルに含まれていれば再現
- 条件付き書式 — こちらの記事 を参照
これらを有効化するためのコードは一切書く必要がありません。これこそが、スプレッドシートコントロールが単なるグリッドコントロールと違うところです。
よくある追加要望: 読み取り専用モード
ファイルを 表示するだけ で十分な場合(例: 請求書のプレビュー画面)、すべてのシートで編集をロックします。
foreach (var sheet in reoGridControl1.Worksheets)
{
sheet.SetSettings(WorksheetSettings.Edit_Readonly, true);
}
コントロールはフォント・数式・書式設定をそのまま描画しつつ、ユーザーはどのセルも変更できなくなります。「Excel ビューアが欲しいが、ユーザーには編集させたくない」という要望への最もすっきりした答えです。
よくある追加要望: ストリームやバイト配列から読み込む
多くのアプリでは、.xlsx がディスク上にあるわけではなく、データベースの BLOB、HTTP レスポンス、MemoryStream から来ます。Load メソッドはストリームを引数に取れます。
using var stream = await httpClient.GetStreamAsync(invoiceUrl);
reoGridControl1.Load(stream, FileFormat.Excel2007);
そして逆方向も同様に。
using var stream = new MemoryStream();
reoGridControl1.Save(stream, FileFormat.Excel2007);
byte[] xlsxBytes = stream.ToArray(); // 保存、アップロード、メール添付など
一時ファイルも追加の依存も不要です。
よくある追加要望: ユーザーの変更を検知する
「何か変わったか?」というワークフローのほとんどは、2 つのイベントでカバーできます。
// 特定セルの編集(入力もしくはペースト)
reoGridControl1.CurrentWorksheet.CellDataChanged += (s, e) =>
{
Debug.WriteLine($"セル {e.Cell.Address} が {e.Cell.Data} になりました");
};
// 「ワークブックが dirty」の広範なシグナル — 構造や値が変わるたびに発火
reoGridControl1.WorkbookSaved += (s, e) => isDirty = false;
これだけで、「未保存の変更があります — 終了してよいですか?」ダイアログを、元ファイルとの差分計算なしで実装できます。
Interop と比較したメリット
具体的な比較表は次の通りです。
| Office Interop | スプレッドシートコンポーネント | |
|---|---|---|
| Excel のインストール必須 | はい | いいえ |
| サーバー / Linux で動作 | いいえ | はい(ヘッドレス用途で) |
| UI をアプリに埋め込み | いいえ(別ウィンドウの Excel) | はい(フォーム上のコントロール) |
| Excel アップデートで壊れない | 場合による | はい |
| ライセンス | ユーザーごとに Office ライセンス | コンポーネントライセンス 1 回 |
| セル読み取り速度 | 遅い(COM マーシャリング) | 速い(プロセス内) |
「全ユーザーが Office を持っている」と前提できる社内ツールなら、まだ Interop も魅力的に見えます。しかし、その前提が崩れたとたん — 1 台でも Office が入っていない、1 社の顧客が Mac、サービスとして配布する — 動かなくなります。スプレッドシートコントロールはこの問題を丸ごと回避します。
次に読むもの
- ReoGrid インストールガイド — NuGet パッケージと参照
- ReoGrid クイックスタート — ワークブックを開く・編集する・保存する
- Office Interop を使わずに C# で Excel ファイルを読み書きする — UI が不要なケース
- WinForms / WPF アプリ向け編集可能グリッドの選び方 — データグリッドとスプレッドシートの使い分け
