スタイルは 4 段階で継承されます。下位が指定した値が勝ち、指定していない(null の)
プロパティは上位から引き継がれます。
セル ◁ 行 ◁ 列 ◁ シート(RootStyle)

4 段階
using unvell.ReoGrid.Core;
using unvell.ReoGrid.Core.Style;
ws.RootStyle = ws.RootStyle with { FontFamily = "Meiryo UI", FontSize = 11f };
ws.SetColumnStyle(1, new StyleRecord { TextAlign = HAlign.Right });
ws.SetRowStyle(0, new StyleRecord { Bold = true });
ws.SetCellStyle(0, 1, new StyleRecord { BackgroundColor = 0xFFFFF3CD });
// B1 の実効スタイル:
// FontFamily = "Meiryo UI" ← シート
// TextAlign = Right ← 列
// Bold = true ← 行
// Background = 0xFFFFF3CD ← セル
StyleRecord effective = ws.GetEffectiveStyle(0, 1);
| 段階 | 設定方法 | 取得 |
|---|---|---|
| セル | ws.SetCellStyle(r, c, style) | ws.GetCellStyle(r, c) |
| 行 | ws.SetRowStyle(row, style) | ws.GetRowStyle(row) |
| 列 | ws.SetColumnStyle(col, style) | ws.GetColumnStyle(col) |
| シート | ws.RootStyle | 同左 |
行が列より優先されます。 同じプロパティを行と列の両方で指定した場合、行の値が勝ちます。 ただし範囲 API 経由であとから適用した場合は Excel と同じ「後勝ち」になります (行と列が交差するセル)。
上書きして継承を打ち消す
ws.SetRowStyle(0, new StyleRecord { Bold = true });
// 行が太字でも、このセルだけ太字にしない
ws.SetCellStyle(0, 3, new StyleRecord { Bold = false });
false は「継承しない」ではなく「明示的にオフ」です。継承させたい場合は null にします。
実効スタイルの取得
GetEffectiveStyle(r, c) は 4 段階を解決した結果を返します。描画・印刷・エクスポートは
すべてこれを通ります。
GetCellStyle(r, c) との違いに注意してください。
| メソッド | 返すもの |
|---|---|
GetCellStyle(r, c) | そのセルに直接設定された指定のみ(未設定なら null) |
GetEffectiveStyle(r, c) | 継承を解決した最終結果(常に非 null) |
合成のしくみ
継承の 1 段階は MergeOver です。
var baseStyle = new StyleRecord { FontSize = 11f, Bold = true };
var over = new StyleRecord { Bold = false, Italic = true };
// over 側で指定されたものが勝ち、null のものは baseStyle が残る
StyleRecord result = baseStyle.MergeOver(over);
// → FontSize = 11, Bold = false, Italic = true
性能上の理由
継承があるおかげで、行・列全体の書式をセル数に依存しないコストで表現できます。
// 良い例 — エントリ 1 個
ws.SetColumnStyle(2, new StyleRecord { TextAlign = HAlign.Right });
// 悪い例 — 104 万エントリが実体化する
for (int r = 0; r < ws.RowCount; r++)
ws.SetCellStyle(r, 2, new StyleRecord { TextAlign = HAlign.Right });
見た目は同じでも、メモリ使用量と処理時間がまったく違います。列全体・行全体に対する 書式は必ず行・列単位の API を使ってください。
範囲へまとめて適用する
どの段へ書くかは SetRangeStyle / MutateRangeStyle が範囲の形から判断します。
呼び出し側で振り分ける必要はありません。
// 部分範囲 → セルへ 1 件ずつ
ws.SetRangeStyle("B2:D5", new StyleRecord { BackgroundColor = 0xFFFFF3CD });
// 列全体 → 列の既定スタイル(列数ぶんの書き込みで済む)
ws.SetRangeStyle("A:C", new StyleRecord { TextAlign = HAlign.Right });
// シート全体 → RootStyle への 1 回の書き込み
ws.SetRangeStyle(new RangePosition(0, 0, ws.RowCount, ws.ColumnCount),
new StyleRecord { FontFamily = "Meiryo UI" });
// 既存の指定を残して 1 プロパティだけ変えるなら MutateRangeStyle
ws.MutateRangeStyle("A:C", s => s with { Bold = true });
| 範囲の形 | 書き込み先 | 書き込み件数 | RangeStyleScope |
|---|---|---|---|
| 部分範囲 | セル | セル数 | Cells |
列全体(A:C) | 列の既定スタイル | 列数 | Columns |
行全体(3:5) | 行の既定スタイル | 行数 | Rows |
| シート全体 | RootStyle | 1 | Sheet |
SetRangeStyle は書き込み先の指定を置き換え、MutateRangeStyle は現在の指定を受け取って
返した値に更新します。シート全体だけは RootStyle が常に全項目を持つため、SetRangeStyle
でも上書きマージになります。
書き込み先を事前に知る
GetRangeStyleScope は、その範囲に書いたらどの段へ落ちるかを書く前に返します。
「この操作はセルを何件実体化するのか」を UI 側で判断したいときに使えます。
// 書く前に、どの段へ落ちるかを尋ねる
RangeStyleScope scope = ws.GetRangeStyleScope(RangePosition.Parse("A:C"));
// → RangeStyleScope.Columns(列の既定スタイルへ 3 件の書き込み)
if (ws.GetRangeStyleScope(range) == RangeStyleScope.Cells)
{
// セルを実体化する経路なので、範囲が広ければ確認を挟む、など
}
// 形の判定は個別にも取れる
bool wholeCols = ws.IsWholeColumns(range);
bool wholeRows = ws.IsWholeRows(range);
bool wholeSheet = ws.IsWholeSheet(range);
_ = (scope, wholeCols, wholeRows, wholeSheet);
判定はシート全体 > 列全体 > 行全体の順で、どれにも当てはまらなければ Cells です。
形の判定そのものは IsWholeColumns / IsWholeRows / IsWholeSheet で個別にも取れます。
いずれもシートの宣言上の寸法に対する判定なので、A:C のような範囲は
RowCount が何であっても列全体として扱われます。
行・列・シートの既定へ書くので、セルが自分で持っている指定はそのまま残ります。 背景色を自分で持っているセルは、列を塗っても自分の色のままです。唯一の例外が次の交差セルです。
行と列が交差するセル
継承では行が列より強いので、そのままだと「行 5 を赤 → 列 C を青」としても C5 は赤のままです。
Excel は後から適用したほうが勝つため、SetRangeStyle / MutateRangeStyle は
行スタイルと列スタイルが交差するセルだけをセルスタイルとして実体化し、後勝ちに揃えます。
- 実体化するのは、相手の行/列が実際に指定しているプロパティだけです。他は継承のままなので、 交差セルにスタイル一式が焼き付くことはありません。
- コストは「反対側の軸でスタイルを持つ line 数」ぶんで、セル数には比例しません。 行スタイルも列スタイルも無いシートでは何も起きません。
- シート全体への適用は、スタイルを持つ行・列の既定へそのまま畳み込まれます (こちらは line 数ぶんの書き込みで、セルは増えません)。
SetRowStyle / SetColumnStyle / RootStyle を直接書いた場合は、この処理は行われません。
固定の優先順位(Root ◁ Column ◁ Row ◁ Cell)そのままで解決されます。
UI から選択範囲に書式を適用する場合、コントロール側のヘルパ(SetSelectionBackColor など)が
同じ API を通るので、行・列・シート全体の選択もそのまま振り分けられます。
条件付き書式との関係
条件付き書式は継承チェーンの外側にあり、実効スタイルの上に重ねられます。 条件が一致したセルだけが上書きされ、モデルのスタイルは変更されません。
詳細は 条件付き書式 を参照してください。