WinFormsアプリでスプレッドシートに大量のデータを表示しようとすると、従来のアプローチでは避けられない問題がありました。数万行のデータを一度にロードしようとすると、起動に数秒かかったり、メモリを大量に消費したりといった問題です。
ReoGrid V4では Lazy Loading(遅延読み込み) が正式に導入され、100万行以上のデータでも数百ミリ秒で表示できるようになりました。この記事では、その実装方法を具体的なコード例とともに解説します。
Lazy Loadingとは
従来の方式では、アプリ起動時にすべてのデータをセルへ書き込む必要がありました。
// 従来方式:全データを一括ロード
for (int i = 0; i < records.Count; i++)
{
worksheet[i, 0] = records[i].Id;
worksheet[i, 1] = records[i].Name;
worksheet[i, 2] = records[i].Value;
// ...100万行ループすると数秒かかる
}
Lazy Loadingでは、画面に表示されているセルだけをオンデマンドでデータソースから取得します。ユーザーがスクロールして初めてそのセルのデータが読み込まれるため、初期表示が劇的に高速になります。
実装手順
1. IDataRecord を実装する
まず、1行分のデータを表す IDataRecord 実装クラスを作ります。
using unvell.ReoGrid.Data;
public class SalesRecord : IDataRecord
{
private readonly SalesData data;
public SalesRecord(SalesData data)
{
this.data = data;
}
// 列インデックスに応じてデータを返す
public object GetData(int columnIndex)
{
return columnIndex switch
{
0 => data.OrderId,
1 => data.CustomerName,
2 => data.Amount,
3 => data.OrderDate.ToString("yyyy/MM/dd"),
4 => data.Status,
_ => null
};
}
}
2. IDataSource<T> を実装する
次に、データ全体を管理する IDataSource<T> 実装クラスを作ります。
using unvell.ReoGrid.Data;
public class SalesDataSource : IDataSource<SalesRecord>
{
private readonly List<SalesData> records;
private readonly SalesRecord[] cache;
public SalesDataSource(List<SalesData> records)
{
this.records = records;
this.cache = new SalesRecord[records.Count];
}
// 総行数(ReoGridがスクロール範囲の計算に使用)
public int RecordCount => records.Count;
// 列数
public int ColumnCount => 5;
public bool SuspendDataChangeEvent { get; set; }
public event EventHandler<DataSourceChangedEventArgs> OnInputDataChanged;
// Lazy Loadingの核心:スクロールで表示されたときだけ呼ばれる
public SalesRecord GetRecord(int row)
{
// キャッシュがあれば再利用、なければ生成
return cache[row] ??= new SalesRecord(records[row]);
}
public IEnumerator<SalesRecord> GetEnumerator()
=> records.Select((_, i) => GetRecord(i)).GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
3. AddDataSource でワークシートに接続する
最後に、DataSourceLoadMode.LazyLoading を指定してワークシートに接続します。
using unvell.ReoGrid;
using unvell.ReoGrid.Data;
private void LoadData(List<SalesData> records)
{
var worksheet = reoGridControl.CurrentWorksheet;
// ヘッダー設定
worksheet[0, 0] = "注文ID";
worksheet[0, 1] = "顧客名";
worksheet[0, 2] = "金額";
worksheet[0, 3] = "注文日";
worksheet[0, 4] = "ステータス";
// 行数を先に確保
worksheet.SetRows(records.Count + 1);
// データソースを接続(LazyLoadingモードで)
var dataSource = new SalesDataSource(records);
worksheet.AddDataSource(
new RangePosition(1, 0, records.Count, 5),
dataSource,
DataSourceLoadMode.LazyLoading
);
}
これだけです。GetRecord() はスクロールで行が表示されたタイミングでのみ呼ばれるため、100万行のデータでも初期ロードは一瞬で完了します。
パフォーマンス比較
| 方式 | 従来(一括書き込み) | Lazy Loading |
|---|---|---|
| 100,000行の初期ロード | 約3〜8秒 | 数百ミリ秒 |
| メモリ使用量 | 高(全データをセルに展開) | 低(表示分のみ保持) |
データ更新時の対応
データが動的に増える場合は ResizeDataSource で範囲を拡張できます。
// 新しいレコードを追加してデータソースを拡張
records.AddRange(newRecords);
worksheet.SetRows(records.Count + 1);
worksheet.ResizeDataSource(
new RangePosition(1, 0, records.Count, 5),
dataSource
);
// データ変更を通知してUIを更新
dataSource.OnInputDataChanged?.Invoke(this, EventArgs.Empty);
まとめ
ReoGrid V4のLazy Loadingを使えば、以下の手順でパフォーマンスを大幅改善できます。
-
IDataRecordを実装して1行のデータ構造を定義 -
IDataSource<T>を実装してデータ全体を管理 -
AddDataSource()にDataSourceLoadMode.LazyLoadingを指定して接続
大量データを扱う業務システム(ログビューア、在庫管理、取引履歴など)でぜひ活用してみてください。
ReoGrid .NET について
ReoGrid は .NETアプリケーション向けのExcel互換スプレッドシートコンポーネントです。V4では Lazy Loading のほか、マルチロウヘッダー、WPF完全対応、VLOOKUP/XLOOKUP など16の主要機能が追加されています。