DataTable を直接バインドする仕組みはありません。ループで書き込みます。
そのぶん、どの列をどこに置くか・どう見せるかを完全に決められます。
数万行でも問題になりません。書き込みのコストは実際に書いたセル数だけです (性能とメモリ)。
流し込む
using System.Data;
using unvell.ReoGrid.Core;
using unvell.ReoGrid.Core.Style;
// 1 行目に列名、2 行目からデータ
for (int c = 0; c < table.Columns.Count; c++)
ws.SetText(0, c, table.Columns[c].ColumnName);
for (int r = 0; r < table.Rows.Count; r++)
for (int c = 0; c < table.Columns.Count; c++)
{
object? v = table.Rows[r][c];
ws.SetObjectValue(r + 1, c, v == DBNull.Value ? null : v);
}
SetObjectValue は string / double / int / bool / DateTime / decimal などを
適切な型に振り分けます。DBNull は渡す前に null へ直してください
(CellValue)。
DateTime は Excel と同じシリアル値として入ります。日付として見せるには
表示形式を指定します(後述)。
型が分かっているなら型付きで書く
// 列の型が分かっているなら、型ごとの Set* のほうが速い
for (int r = 0; r < table.Rows.Count; r++)
{
DataRow row = table.Rows[r];
ws.SetText(r + 1, 0, (string)row["Name"]);
ws.SetNumber(r + 1, 1, Convert.ToDouble(row["Amount"]));
ws.SetObjectValue(r + 1, 2, row["OrderDate"]); // DateTime はシリアル値になる
}
SetText / SetNumber / SetBoolean は型判定を通らないぶん SetObjectValue より
軽くなります。10 万行を超えるあたりから体感差が出ます。
見出しと書式を付ける
// 見出し行は行スタイルで一括指定(セルごとに設定しない)
ws.SetRowStyle(0, new StyleRecord
{
Bold = true,
BackgroundColor = 0xFFF3F3F3,
TextAlign = HAlign.Center,
});
// 金額列は列スタイル+数値書式で。範囲は使用範囲に絞る
ws.SetColumnStyle(1, new StyleRecord { TextAlign = HAlign.Right });
ws.SetNumberFormat(new RangePosition(1, 1, table.Rows.Count, 1), "#,##0");
セルのループで書式を設定しないでください。 見出し行は SetRowStyle、
列の右寄せは SetColumnStyle を使います。見た目は同じでも、セル単位で設定すると
その行・列のセル数ぶんのエントリが実体化します
(スタイルの継承)。
日付列の表示形式も同じ要領です。
ws.SetNumberFormat(new RangePosition(1, 2, table.Rows.Count, 1), "yyyy/mm/dd");
見出し行を固定するのはコントロール側の操作です。
control.SetFreeze(rows: 1, cols: 0);
列幅を内容に合わせる
control.AutoFitSelectedColumns();
選択中の列が対象です。全列に効かせたい場合は、先に全体を選択してから呼びます。 ヘッダー境界のダブルクリックと同じ処理です。
List<T> から流し込む
DataTable でなくても同じです。プロパティを列に割り当てるだけです。
for (int i = 0; i < items.Count; i++)
{
ws.SetText(i + 1, 0, items[i].Name);
ws.SetNumber(i + 1, 1, items[i].Amount);
ws.SetObjectValue(i + 1, 2, items[i].OrderDate);
}
リフレクションで列を自動生成することもできますが、10 万行規模ではプロパティアクセスが 支配的になります。件数が多い場合は上のように直接書いてください。
編集結果を読み戻す
// シート → DataTable。1 行目を列名として読む
var table = new DataTable();
if (!ws.TryGetUsedRange(out RangePosition used)) return table;
for (int c = used.Col; c <= used.EndCol; c++)
table.Columns.Add(ws.GetDisplayText(used.Row, c));
for (int r = used.Row + 1; r <= used.EndRow; r++)
{
DataRow row = table.NewRow();
for (int c = used.Col; c <= used.EndCol; c++)
row[c - used.Col] = ws.GetObjectValue(r, c) ?? DBNull.Value;
table.Rows.Add(row);
}
GetObjectValue はセルの型に応じて string / double / bool / null を返します。
数式セルの場合は計算結果が返ります。数式そのものが要るなら GetFormula を使います。
日付として取り出したい場合は、シリアル値を変換してください。
double serial = ws.GetValue(r, c).AsNumber;
DateTime date = DateTime.FromOADate(serial);