V4 V5

Excel のテーブル(ListObject)は書式ではなくオブジェクトです。 V5 もそう扱います。TableDefinition が持つのは範囲・見出し行数・スタイル名だけで、 各セルの色は「そのセルが範囲のどこに居るか」から描画のたびに解かれます。

色をセルに焼き込まないので、

  • 10 万行のテーブルでもオブジェクトは 1 個、
  • 途中に行を挿しても縞が崩れず、
  • 手で塗ったセルは縞を破れ、
  • xlsx には ad-hoc な塗りではなく本物の xl/tables/tableN.xml として出ます。

基本

using unvell.ReoGrid.Core;
using unvell.ReoGrid.Core.Tables;

// 先頭行を見出しにして A1:D100 をテーブルにする。既定は TableStyleMedium2
var table = ws.AddTable("A1:D100");

// 列名は見出し行から採られる
string first = table.Columns[0].Name;

// テーブルをやめる(Excel の「範囲に変換」)。書式はセルに入っていないので消えるだけ
ws.RemoveTable(table.Name);

_ = first;

AddTable は範囲を A1 形式のアドレスか名前付き範囲、あるいは RangePosition で受け取ります。 先頭行が見出しになり、列名はその行のテキストから採られます(空白や重複は Column3 / Qty2 のように一意化されます — Excel が列名の衝突を許さないため)。

スタイルとオプション

// スタイルとオプションを指定して作る
var table = ws.AddTable(RangePosition.Parse("A1:D100"), new AddTableOptions
{
	Name = "Sales",
	Style = "TableStyleMedium7",   // 組込 60 種。名前はファイルにそのまま残る
	ShowRowStripes = true,         // 交互行(既定 true)
	ShowFirstColumn = true,        // 先頭列を強調
	ShowFilterButton = true,       // 見出し行にフィルタ▽を出す(既定 false)
});

// 後から切り替える。Style は record struct なので with で書き換える
table.Style = table.Style with { ShowColumnStripes = true, ShowRowStripes = false };
オプション既定内容
NameTable1, Table2, …ブック内で一意な内部名。識別子なので英字か _ で始まり、英数字・.・_ のみ(空白不可、Q1 のようなセル参照も不可)— Excel は構造化参照でこの名前を綴るため
StyleTableStyleMedium2組込スタイル名。未知の名前でも書き換えません(後述)
HeaderRowCount10 か 1。Excel のテーブルに複数見出し行はありません
TotalsRowCount00 か 1。配色はしますが集計関数は未実装です(往復はします)
ShowRowStripestrue交互行(しま模様)
ShowColumnStripesfalse交互列
ShowFirstColumn / ShowLastColumnfalse先頭列・末尾列の強調
ShowFilterButtonfalse見出し行にフィルタ▽を出す(シートの auto-filter を張ります。範囲は見出しとデータ行で、集計行は含みません — Excel と同じく、何を絞り込んでも集計行は残ります)

ShowFilterButton が既定で false なのは、シートが持てる auto-filter が 1 つだけだからです。 既定で true にすると、2 つ目のテーブルを作った瞬間に 1 つ目から▽が消えます。

既定の TableStyleMedium2 のテーブル。見出し行に▽、先頭のデータ行から 1 行おきの縞、行間の罫線、二重線の下に集計行

図は既定の TableStyleMedium2 に ShowFilterButton と TotalsRowCount = 1 を付けたものです。 集計行の数式(ここでは SUBTOTAL(109,B2:B8))は V5 が書くのではなく、アプリ側で入れています(後述)。

交互行(しま模様)

縞は Excel と同じく先頭のデータ行から付きます(1 行目・3 行目・5 行目…が縞の色)。 数え方はシート単位の縞と同じで、可視行だけを数えるので、 フィルタで行が消えても縞が 2 行続きません。 テーブルの中ではテーブルの縞が優先され、シートの縞はテーブルの縁で止まります。

Excel は縞をテーブルスタイルの中に持っているので、 xlsx を往復するのはこちらの縞です(シート単位の縞は Excel に置き場所が無く、reogrid-json のみ)。

塗りの優先順位

強い順に:

  1. 条件付き書式
  2. セル自身の書式(セル → 行 → 列のスタイル鎖)
  3. テーブルスタイル
  4. シートの縞(テーブルの外だけ)

テーブルは継承鎖の Root ◁ Table ◁ Column ◁ Row ◁ Cell に入ります。 セル自身より弱いので、1 行だけ黄色く塗ればそこだけ縞を破れます。 罫線も同じで、テーブルの枠線の上に手書きの罫線が辺ごとに乗ります。

テーブルの内側では、スタイルの各部分が Excel と同じ順に重なります(後ろほど強い): テーブル全体 → 列の縞 → 行の縞 → 末尾列 → 先頭列 → 見出し行 → 集計行。 各部分は自分が指定した項目だけを上書きするので、塗りを持たない見出し行 (Medium 22–28 など)にはテーブル全体の塗りがそのまま見えます。

問い合わせ

bool any = ws.HasTables;

// そのセルを覆っているテーブル(無ければ null)
TableDefinition? at = ws.GetTableAt(5, 2);

// 名前で引く(大小無視)
TableDefinition? byName = ws.GetTable("Sales");

// 見出し・集計行を除いたデータ部分
RangePosition data = at?.DataRange ?? default;

// そのセルにテーブルが与えている塗り(セル自身の書式より弱い層)
var contributed = ws.GetTableStyle(5, 2);

// 手書きの罫線をテーブルの罫線の上に重ねた結果
CellBorders borders = ws.GetEffectiveBorders(5, 2);

_ = (any, byName, data, contributed, borders);

組込スタイルと自前の配色

Excel はファイルにスタイル名しか書きません。TableStyleMedium7 がどう見えるかは アプリ側の知識です。その中身は公開されていて、ECMA-376 が組込 60 種を presetTableStyles.xml として定義しています。V5 はこの定義をそのまま持っているので、 どの行に縞を付け、どの辺に罫線を引き、どの文字を太くするかが Excel と一致します。

組込スタイル 6 種。Light 1・Light 10・Light 21・Medium 2(既定)・Medium 14・Dark 3

組込スタイルは名前ほど規則的ではありません。Light だけでも、上下の罫線と濃い文字色(1–7)、 塗った見出しと縞ごとの罫線(8–14)、格子(15–21)と形が 3 通りあり、Dark 9–11 の見出しは 自分のアクセントとは別の色を使います。色は Office の既定テーマ(2013 以降)から OOXML と同じ HSL の tint 曲線で解くので、Office のスウォッチとの差は RGB で 1〜2 程度です (Medium 2 の縞は Office の #D9E1F2 に対して #DAE3F3)。

知らない名前は既定の配色で描きますが、名前は書き換えません。 ただし残るのは名前だけです。V5 はユーザー定義スタイルの定義(Excel が styles.xml の <tableStyles> に書くもの)を読み書きしないので、Excel で作ったユーザー定義スタイルは V5 で 保存し直すと定義が失われ、Excel ではスタイル無しのテーブルとして表示されます。 下の TableStyles.Register で登録した配色も同じで、ファイルには名前しか残らず、 Excel では書式の無いテーブルになります。Excel で開くファイルには組込 60 種を使ってください。

// 組込スタイルの一覧(Light 1–21 / Medium 1–28 / Dark 1–11)
foreach (string name in TableStyles.BuiltinNames())
{
	TableStyleDefinition def = TableStyles.Resolve(name);
	_ = (def.HeaderFill, def.RowStripeFill, def.WholeBorderColor);
}

// 自前の配色を登録する(同名の組込を上書きもできる)
TableStyles.Register(new TableStyleDefinition
{
	Name = "BrandTable",
	HeaderFill = 0xFF1F3864,
	HeaderColor = 0xFFFFFFFF,
	HeaderBold = true,
	RowStripeFill = 0xFFEAF0F8,
	WholeBorderColor = 0xFF1F3864,
});

HeaderFill や RowStripeFill は簡易記法で、実体は Excel の tableStyleElement に当たる TableStyleElement(WholeTable / HeaderRow / TotalRow / FirstColumn / LastColumn / FirstRowStripe / SecondRowStripe / FirstColumnStripe / SecondColumnStripe)です。 各要素は塗り・文字色・太字と、外周 4 辺と内側の罫線(Horizontal / Vertical)を持ちます。

// 罫線の太さや行間の罫線まで決めるなら、Excel の tableStyleElement と同じ単位で書く
TableStyles.Register(new TableStyleDefinition
{
	Name = "BrandLedger",
	WholeTable = new TableStyleElement
	{
		Horizontal = new BorderEdge(BorderLineStyle.Solid, 0xFFB4C6E7, 1),   // 行と行の間
		Bottom = new BorderEdge(BorderLineStyle.Solid, 0xFF1F3864, 2),       // 表の下端
	},
	HeaderRow = new TableStyleElement { Fill = 0xFF1F3864, Color = 0xFFFFFFFF, Bold = true },
	FirstRowStripe = new TableStyleElement { Fill = 0xFFEAF0F8 },           // 先頭のデータ行から
	TotalRow = new TableStyleElement
	{
		Bold = true,
		Top = new BorderEdge(BorderLineStyle.Double, 0xFF1F3864, 3),
	},
});

行・列の挿入と削除

テーブルは自分が説明しているデータに追従します。 上に行を挿せば下がり、途中に挿せば伸び、列を消せば列リストからもその列が抜けます。 テーブルの行が全部消えれば、テーブルも一緒に消えます。

入出力

形式内容
reogrid-jsontables(reogrid-web の JsonTableDefinition と同形)
XLSXxl/tables/tableN.xml + [Content_Types].xml の Override + シートの _rels + <tableParts>。番号はブック全体の通し番号

どちらの形式でも、テーブルの色はセルに書きません。Excel ではセル自身の書式がテーブルスタイルより 強いので、セルに書き込むと並べ替えで縞が行ごと動き、スタイルを変えても色が変わらなくなります。

XLSX では、Excel が開けるファイルにするために次の 3 点を守っています。どれか 1 つでも外れると、 Excel は修復も含めてファイルを開けません(デスクトップ版 Excel で確認)。

  • テーブルのフィルタ(ShowFilterButton)はテーブルのパーツ側に書き、シートの <autoFilter> には書かない。 テーブルと重なるシートのフィルタがあると開けません。読み込み時はテーブル側のフィルタをシートのフィルタとして 戻します(シートが自分のフィルタを持っていない場合)
  • フィルタの範囲は集計行を含まない
  • 集計行の各セルの中身を列に宣言する。文字は totalsRowLabel、数式や値は totalsRowFunction="custom" + <totalsRowFormula>(セル自身の数式もそのまま書きます)

まだ無いもの

  • 集計行の集計関数(SUBTOTAL)— 行の配色と往復だけ
  • 構造化参照(=Table1[列名])
  • 隣のセルを編集したときの自動拡張
  • ユーザー定義テーブルスタイルの定義(styles.xml の <tableStyles>)の読み書き
ページの内容は役に立ちましたか?