VB.NET は今も現役です。業務ツール、社内ダッシュボード、データ入力フォームなど、エンタープライズ向けデスクトップソフトウェアの多くは今も VB.NET で書かれており、その多くが Excel とのデータ連携を必要としています。本記事では実践的なアプローチを 1 か所にまとめます — ワークブックの読み込み、コードからの生成、そして WinForms / WPF フォームへのライブビューアの埋め込みです。
いずれのアプローチも Excel のインストールは不要で、.NET が動作するあらゆるマシンで使用できます。
まとめ: 用途別ライブラリ選定表
| やりたいこと | 推奨ライブラリ |
|---|---|
.xlsx からセル値を読み込む | ClosedXML または ReoGrid |
.xlsx レポートを生成する(UI なし) | ClosedXML |
WinForms フォームに .xlsx を表示する | ReoGrid(WinForms パッケージ) |
WPF ウィンドウに .xlsx を表示する | ReoGrid(WPF パッケージ) |
| ユーザーに編集・保存させる | ReoGrid |
レガシー .xls(Excel 97〜2003) | NPOI |
ClosedXML はサーバーサイドやヘッドレスの処理に最適です。ReoGrid はスプレッドシートをアプリの UI 内に表示する場合に最適です。両者は排他ではありませんが、多くのケースでどちらか一方を選べば事足ります。
VB.NET で Excel データを読み込む
ClosedXML を使う
NuGet でインストール:
PM> Install-Package ClosedXML
最初のワークシートからすべての行を読み込む:
Imports ClosedXML.Excel
Sub ReadWorkbook(filePath As String)
Using workbook As New XLWorkbook(filePath)
Dim ws = workbook.Worksheet(1)
For Each row In ws.RowsUsed()
For Each cell In row.CellsUsed()
Console.Write(cell.Value.ToString() & vbTab)
Next
Console.WriteLine()
Next
End Using
End Sub
RowsUsed() は空行をスキップします。CellsUsed() は各行の空セルをスキップします — 空の範囲を走査せずに済みます。
名前付き範囲を読み込む
ワークブックで名前付き範囲(例: SalesData)を使用している場合、行・列番号をハードコードせずに直接ターゲットにできます。
Imports ClosedXML.Excel
Sub ReadNamedRange(filePath As String, rangeName As String)
Using workbook As New XLWorkbook(filePath)
Dim namedRange = workbook.NamedRange(rangeName)
Dim cells = namedRange.Ranges.CellsUsed()
For Each cell In cells
Console.WriteLine($"{cell.Address}: {cell.Value}")
Next
End Using
End Sub
ReoGrid を使う(UI なしのパス)
ReoGrid は UI を表示しなくても、ワークブックを開いて読み込めます — インポートパイプラインに使えます。
Imports unvell.ReoGrid
Imports unvell.ReoGrid.IO
Sub ReadWithReoGrid(filePath As String)
Dim workbook As New ReoGridControl()
workbook.Load(filePath)
Dim ws = workbook.CurrentWorksheet
For r As Integer = 0 To ws.MaxContentRow
For c As Integer = 0 To ws.MaxContentCol
Dim cellData = ws.GetCellData(r, c)
Console.Write(If(cellData IsNot Nothing, cellData.ToString(), "") & vbTab)
Next
Console.WriteLine()
Next
End Sub
データも表示も必要な場合、このアプローチなら ClosedXML は不要です — 1 つのライブラリで IO と UI の両方を処理できます。
VB.NET で Excel ファイルを書き出す
ゼロからワークブックを生成する
Imports ClosedXML.Excel
Sub GenerateReport(outputPath As String, data As DataTable)
Using workbook As New XLWorkbook()
Dim ws = workbook.Worksheets.Add("Report")
' ヘッダー行
For c As Integer = 0 To data.Columns.Count - 1
Dim cell = ws.Cell(1, c + 1)
cell.Value = data.Columns(c).ColumnName
cell.Style.Font.Bold = True
cell.Style.Fill.BackgroundColor = XLColor.FromHtml("#4472C4")
cell.Style.Font.FontColor = XLColor.White
Next
' データ行
For r As Integer = 0 To data.Rows.Count - 1
For c As Integer = 0 To data.Columns.Count - 1
ws.Cell(r + 2, c + 1).Value = XLCellValue.FromObject(data.Rows(r)(c))
Next
Next
ws.Columns().AdjustToContents()
workbook.SaveAs(outputPath)
End Using
End Sub
AdjustToContents() はすべての列を自動的に幅調整します — 生成した Excel ファイルの列幅が常に狭すぎるという定番の不満を防ぐ小さな配慮です。
ストリームへの書き出し(ダウンロードやメール添付用)
データベース、API、メールクライアントは多くの場合ファイルパスではなくバイト列を要求します。
Imports ClosedXML.Excel
Function GenerateToStream(data As DataTable) As Byte()
Using workbook As New XLWorkbook()
Dim ws = workbook.Worksheets.Add("Data")
ws.Cell(1, 1).InsertTable(data)
Using ms As New MemoryStream()
workbook.SaveAs(ms)
Return ms.ToArray()
End Using
End Using
End Function
InsertTable は ClosedXML のショートカットで、DataTable を 1 行で Excel テーブル(オートフィルター・縞模様の行・縞模様の列付き)として書き込みます。
WinForms に Excel ファイルを表示する(VB.NET)
WinForms フォームで .xlsx を表示・編集するのに適したツールはスプレッドシートコントロールです — DataGridView ではありません。DataGridView はフラットなレコードを扱うコントロールで、実際の .xlsx ファイルが持つ結合セル・数式の再計算・複数シート・セル書式を理解しません。
1. WinForms パッケージのインストール:
PM> Install-Package unvell.ReoGrid.dll
2. フォームに ReoGridControl を追加 してから、開く・保存のボタンを実装する:
Imports unvell.ReoGrid
Public Class MainForm
Private Sub OpenButton_Click(sender As Object, e As EventArgs) Handles OpenButton.Click
Using dlg As New OpenFileDialog()
dlg.Filter = "Excel Workbook|*.xlsx"
If dlg.ShowDialog() <> DialogResult.OK Then Return
ReoGridControl1.Load(dlg.FileName)
End Using
End Sub
Private Sub SaveButton_Click(sender As Object, e As EventArgs) Handles SaveButton.Click
Using dlg As New SaveFileDialog()
dlg.Filter = "Excel Workbook|*.xlsx"
If dlg.ShowDialog() <> DialogResult.OK Then Return
ReoGridControl1.Save(dlg.FileName)
End Using
End Sub
End Class
実装はこれだけです。ファイルを読み込めば、ユーザーはフォント・塗りつぶし・罫線がそのまま反映された完全なワークブックを確認し、セルをクリックして入力し、下部のシートタブで切り替え、保存できます。
読み取り専用モード
ファイルをプレビューするだけで編集させたくない場合:
For Each ws In ReoGridControl1.Worksheets
ws.SetSettings(WorksheetSettings.Edit_Readonly, True)
Next
書式・数式・フォントはそのまま描画しつつ、セルへの入力はできなくなります。
ストリームやバイト配列から読み込む
ファイルがディスク上でなく、データベースの BLOB や HTTP レスポンスから来る場合:
Imports unvell.ReoGrid
Imports unvell.ReoGrid.IO
' バイト配列から(例: DB カラム)
Dim xlsxBytes As Byte() = GetBytesFromDatabase()
Using ms As New MemoryStream(xlsxBytes)
ReoGridControl1.Load(ms, FileFormat.Excel2007)
End Using
' HTTP レスポンスから
Dim stream As Stream = Await httpClient.GetStreamAsync(reportUrl)
ReoGridControl1.Load(stream, FileFormat.Excel2007)
WPF に Excel ファイルを表示する(VB.NET)
WPF パッケージと WinForms パッケージは同じ API を持っています。変わるのはインストールする NuGet パッケージとコントロールの宣言方法だけです。
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. VB.NET のコードビハインド:
Imports Microsoft.Win32
Imports unvell.ReoGrid
Class MainWindow
Private Sub OpenButton_Click(sender As Object, e As RoutedEventArgs)
Dim dlg As New OpenFileDialog With {.Filter = "Excel Workbook|*.xlsx"}
If dlg.ShowDialog() <> True Then Return
Grid.Load(dlg.FileName)
End Sub
Private Sub SaveButton_Click(sender As Object, e As RoutedEventArgs)
Dim dlg As New SaveFileDialog With {.Filter = "Excel Workbook|*.xlsx"}
If dlg.ShowDialog() <> True Then Return
Grid.Save(dlg.FileName)
End Sub
End Class
WPF コントロールも WinForms と同様に、複数ワークシート・数式・書式設定・ウィンドウ枠の固定・条件付き書式をサポートしています。
変更の検知
「未保存の変更があります — 終了してよいですか?」ダイアログには、2 つのイベントでほぼすべてのケースをカバーできます。
' セル値が編集されたとき
AddHandler ReoGridControl1.CurrentWorksheet.CellDataChanged,
Sub(s, args)
isDirty = True
Text = "My App *" ' タイトルバーのアスタリスク = 一般的な慣習
End Sub
' 保存後にダーティフラグをリセット
AddHandler ReoGridControl1.WorkbookSaved,
Sub(s, args)
isDirty = False
Text = "My App"
End Sub
なぜ Office Interop を使わないのか
短くまとめると: Microsoft.Office.Interop.Excel は実際の Excel プロセスを COM 経由で自動操作します。ユーザーのマシンすべてに Office のインストールが必要で、サービス上での使用を Microsoft が明示的に非推奨としており、フォームに埋め込んだコントロールではなく別の Excel ウィンドウが表示され、エラー発生時にプロセスが残留します。自己完結型の VB.NET デスクトップアプリには、ファイル形式を直接読み書きするインプロセスのライブラリが適しています。
| Office Interop | インプロセスライブラリ | |
|---|---|---|
| Excel のインストール必須 | はい | いいえ |
| UI をフォームに埋め込み | いいえ(別 Excel ウィンドウ) | はい |
| Office なしのマシンで動作 | いいえ | はい |
| 処理速度 | 遅い(COM マーシャリング) | 速い |
| エラーハンドリング | COM 例外 | 通常の .NET 例外 |
まとめ: シンプルなインポートフォーム
よくある VB.NET のシナリオ: .xlsx を選択し、グリッドで確認してから「インポート」をクリックしてデータベースに取り込むフォームです。
Imports unvell.ReoGrid
Public Class ImportForm
Private Sub BrowseButton_Click(sender As Object, e As EventArgs) Handles BrowseButton.Click
Using dlg As New OpenFileDialog()
dlg.Filter = "Excel Workbook|*.xlsx"
If dlg.ShowDialog() <> DialogResult.OK Then Return
ReoGridControl1.Load(dlg.FileName)
' 編集ロック — これはエディタではなくプレビューです
For Each ws In ReoGridControl1.Worksheets
ws.SetSettings(WorksheetSettings.Edit_Readonly, True)
Next
ImportButton.Enabled = True
End Using
End Sub
Private Sub ImportButton_Click(sender As Object, e As EventArgs) Handles ImportButton.Click
Dim ws = ReoGridControl1.CurrentWorksheet
For r As Integer = 0 To ws.MaxContentRow
Dim id = ws.GetCellData(r, 0)?.ToString()
Dim name = ws.GetCellData(r, 1)?.ToString()
Dim amount = ws.GetCellData(r, 2)
If String.IsNullOrWhiteSpace(id) Then Continue For
InsertRow(id, name, amount)
Next
MessageBox.Show("Import complete.")
End Sub
Private Sub InsertRow(id As String, name As String, amount As Object)
' ... DB 挿入ロジックをここに
End Sub
End Class
このフォームによりユーザーは確定前に何がインポートされるかを正確に確認できます — どのシートが読まれたか、どの行がスキップされたか、といった混乱が生じません。
次に読むもの
- ReoGrid インストールガイド — NuGet パッケージとアセンブリ参照
- ReoGrid クイックスタート — ワークブックを開く・編集する・保存する
- C# で WinForms / WPF アプリに Excel ファイルを表示・編集する — C# でも開発する場合の同内容ガイド
- C# で DataTable を Excel に出力する — ADO.NET データから
.xlsxレポートを生成する
