ReoGrid ReoGrid Web

JavaScriptスプレッドシートに「並べ替えとフィルター」を ― Excel 風オートフィルターを、クリックでもコードでも

· unvell team
JavaScriptスプレッドシートに「並べ替えとフィルター」を ― Excel 風オートフィルターを、クリックでもコードでも

データ検証の記事では、グリッドに入るものを固めました。データはもう入っています ― 数百行、あるいは数千行 ― そして誰かがその中を探し回る番です。まだ Open の受注はどれ? 大阪オフィスの人は? 売上の降順で並べ替えて。これはスプレッドシートの日常動作です ― ヘッダーのドロップダウンをクリックし、見たい値にチェックを入れ、列を並べ替える。ReoGrid Web ではこれが、有効化はワンコール、コードからの操作も小さな API で済みます。

並べ替えとフィルターは Pro 機能です(料金)― createAutoFiltersortColumn・ヘッダー固定のヘルパーは、いずれも Pro エディションにあります。


列を並べ替える

いちばんシンプルな操作が単純な並べ替えです。sortColumn に列インデックスと方向を渡します。

const ws = grid.worksheet;

ws.sortColumn(4, 'desc'); // E列(Revenue)で降順に並べ替え
ws.sortColumn(1, 'asc');  // 次に B列(Name)で A→Z

データ行をその場で並べ替えます。オートフィルターが有効なら、並べ替えはフィルターの範囲内にとどまり、ドロップダウンの並べ替えインジケーターを更新します。無効ならシート全体が並びます。呼び出しは SortResult を返し、その originalOrder が並べ替えに各行がどこにあったかのスナップショットになります ― 自前の元に戻す(undo)を作るのに必要なものそのものです。

const { originalOrder } = ws.sortColumn(4, 'desc');
// originalOrder[i] = データ位置 i に元々あった行

現在の状態を読み戻すには ws.getSortState(){ column, order } を返し、何も並んでいないときは null(正確には、記録するアクティブなオートフィルターがないとき)です。


オートフィルター ― ヘッダーのドロップダウン

並べ替えは行を並び替えるもの。フィルターは要らない行を隠すものです。createAutoFilter はヘッダー行を Excel でおなじみのドロップダウン矢印に変えます ― クリックすれば、その列の値のチェックリストと昇順・降順の並べ替えが出てきます。

const filter = ws.createAutoFilter({
  headerRow: 0,   // 列ラベルのある行
  startColumn: 0, // フィルター範囲の最初の列
  endColumn: 4,   // 最後の列(含む)
});

セットアップはこれだけ。データ行は headerRow より下のすべて。ドロップダウンは startColumn から endColumn までのヘッダーセルに現れます。ここからユーザーはマウスで操作しますが、それらのドロップダウン操作にはすべてコードでの等価物があり、そこがこの機能をスクリプト化できる理由です。


実例:フィルターできるデータ表

実際に世に出すものを作りましょう ― スタイル付きのヘッダー、ゼブラ縞、固定されたヘッダー行、全列のフィルタードロップダウン、そして「N / M 行表示中」のライブ表示。これが完全なコードです。

import { createReogrid } from '@reogrid/pro';

const { worksheet: ws } = createReogrid('#grid');

ws.suspendRender(); // 初期構築をバッチ処理

// ── 列 ──
const HEADERS = ['ID', 'Name', 'Department', 'Region', 'Revenue'];
[60, 150, 130, 110, 110].forEach((w, c) => { ws.column(c).width = w; });

HEADERS.forEach((h, c) => {
  ws.cell(0, c).setValue(h).setStyle({
    bold: true, backgroundColor: '#1e3a5f', color: '#e2e8f0', textAlign: 'center',
  });
});
ws.row(0).height = 30;

// ── データ(フィルターが各セルのテキストを読めるよう setCellInput で投入) ──
const ROWS = [
  [1, 'Alice Johnson', 'Sales',       'Tokyo',   124500],
  [2, 'Bob Smith',     'Engineering', 'Osaka',    98200],
  [3, 'Carol White',   'Marketing',   'Tokyo',    87600],
  [4, 'David Lee',     'Sales',       'Nagoya',  142300],
  [5, 'Eva Chen',      'Engineering', 'Tokyo',   105800],
  [6, 'Frank Kim',     'Marketing',   'Osaka',    76400],
  [7, 'Grace Liu',     'Sales',       'Osaka',   131900],
  [8, 'Henry Park',    'Engineering', 'Nagoya',   92100],
];
ROWS.forEach((row, i) => {
  row.forEach((val, c) => { ws.setCellInput(i + 1, c, String(val)); });
});

// ── ゼブラ縞は行の位置で塗るので、並べ替えても崩れない ──
ws.setAlternateRowColors({ evenColor: '#ffffff', oddColor: '#f8fafc' });

ws.resumeRender();

// ── ヘッダーを固定してから、ドロップダウンを有効化 ──
ws.setFrozenRows(1);
const filter = ws.createAutoFilter({ headerRow: 0, startColumn: 0, endColumn: 4 });

// ── 表示中の行数をライブ表示 ──
const info = document.getElementById('info')!;
filter.onFilterChange((e) => {
  info.textContent = `${ROWS.length - e.hiddenRowCount} / ${ROWS.length} 行表示中`;
});

Department のドロップダウンをクリックして Sales を選ぶと、表は3行に畳まれ、表示も追従します。Revenue をクリックして降順に並べ替え。固定ヘッダーの下がすべて流れ直し、縞はそのまま。動くものはデータフィルター・並べ替えデモで試せます ― 同じセットアップを 300〜10,000 行に対して動かしています。

掘り下げるべきポイントが2つ ― コードからのフィルターの掛け方と、なぜ縞が崩れなかったか、です。


コードからフィルターを掛ける

フィルターとは、列ごとの表示する値の集合にすぎません。setColumnFilter は列と、表示し続けたい値の Set<string> を取り、apply() で確定します。null を渡せばその列を「すべて表示」に戻します。

// Department 列(インデックス2)で Sales と Marketing だけ表示
filter.setColumnFilter(2, new Set(['Sales', 'Marketing']));
filter.apply();

// 後で:その列だけクリア
filter.setColumnFilter(2, null);
filter.apply();

とはいえ値をベタ書きすることはまれで、列に「何を持っているか」を尋ねます。getColumnValues はヘッダーより下の一意なセルテキストをアルファベット順で返します ― これがドロップダウンのチェックリストに出るものそのものです。

filter.getColumnValues(2);       // ['Engineering', 'Marketing', 'Sales']
filter.getColumnFilter(2);       // { column: 2, selectedValues: Set(...) } または null
filter.hasActiveFilters();       // いずれかの列がフィルター中なら true
filter.clearAll();               // 全フィルターを解除し、全行を再表示

条件が単なる文字列の集合なので、フィルターは各セルのテキストで照合します ― getColumnValues が渡すのと同じテキストです。実例がデータを setCellInput で入れているのはこのため。フィルターが比較するのは、型付き数値ではなく入力テキストだからです。


フィルター内で並べ替えるか、シート全体か

sortColumn の入口は2つあり、違いはスコープです。

ws.sortColumn(4, 'desc');     // ワークシート:アクティブなフィルターの範囲内で、
                              // フィルターがなければシート全体を並べ替え
filter.sortColumn(4, 'desc'); // フィルター:常に自分のデータ範囲を並べ替え

オートフィルターがある状態では両者は同じ動きをします ― フィルターのデータ行を並べ替え、状態を記録するので、filter.getSortState()(および ws.getSortState())は { column: 4, order: 'desc' } を返します。違いが効くのはフィルターなしで並べ替えるときだけ。ws.sortColumn はそれでも動いてシート全体を並べ替えますが、覚えておくフィルターがないので getSortState()null のままです。データを動かさずにインジケーターだけ立てたいなら(自前の経路で並べ替えた場合など)、filter.setSortState(col, order) で設定、filter.clearSortState() で解除します。


変化に反応する

フィルターは行を隠すことで働き、削除は決してしません ― 隠れた行のデータはそのままで、フィルターを解除した瞬間に戻ってきます。反応するためのフックが2つ。

// フィルター変更のたびに発火。イベントには隠れ行数の累計が乗る
const off = filter.onFilterChange((e) => {
  console.log(e.column, e.selectedValues, e.hiddenRowCount);
});

// ユーザーがヘッダーのドロップダウン矢印をクリックしたときに発火 ― ここで自前の UI を作る
ws.onFilterDropdownClick((column) => {
  openCustomFilterPanel(column);
});

onFilterChange が実例の表示行数を駆動していました。onFilterDropdownClick は逃げ道です ― クリックを横取りして、組み込みのチェックリストの代わりに自前のパネル(日付範囲ピッカー、検索ボックス、件数付きの複数選択など)を描画できます。どちらも購読解除の関数を返すので、グリッドを破棄するときに(off() のように)呼びます。

フィルター自体の管理には、ws.getAutoFilter() が現在の AutoColumnFilter(または null)を返し、ws.removeAutoFilter() がドロップダウンを外してすべてを再表示します。


Lite はどこまで、Pro はどこから

強制と作成を分ける機能もありますが、並べ替えとフィルターは端から端まで Pro です。

操作Lite(無料)Pro
データ読み込み、セルスタイル、setAlternateRowColors
列の並べ替え(sortColumn
オートフィルターのドロップダウン(createAutoFiltersetColumnFilter など)
ヘッダー行・列の固定(setFrozenRows

データとその装飾は無料。対話的な並べ替え・フィルターのエンジン ― そしてフィルター済みのリストをスクロールしてもヘッダーを見せ続ける固定ペイン ― が Pro の始まりです。


まとめ

並べ替えとフィルターは、静的な表を実際に「たどれる」ものに変えます。昇順・降順の sortColumn、Excel 風ヘッダードロップダウンの createAutoFilter、そしてあらゆるクリックを写し取るコンパクトな API ― getColumnValuessetColumnFilterapplyclearAllonFilterChange。行は隠されるだけで失われないので、フィルター済みのビューは常に clearAll() 一発で元通りです。

データフィルター・並べ替えデモで試してみてください ― 最大 10,000 行を並べ替え・フィルターできます。API 全体は並べ替え・フィルターのドキュメントへ。フィルターに届く前に不正なデータを止める話はデータ検証の記事、値に応じて行をスタイリングする話は条件付き書式の記事へ。

ReoGrid Web を試してみる

React/Vue 向けの Canvas ベース Excel 互換スプレッドシートコンポーネント。 Lite は無料 — npm install 一発で始められます。

関連記事

JavaScriptスプレッドシートでピボットテーブル ― 数行のAPIで、ライブ更新されるクロス集計を

数百行の生データを、データの変更に追随して再計算されるクロス集計表に。createPivot 一発で行・列・集計を宣言し、ハンドルの update / refresh / remove でコードから操作。地域×商品の売上を使った完全な実例と、フィルター・総計・Lite 対 Pro の境界線まで。

JavaScriptスプレッドシートに「入力規則」を ― 不正なデータをセルの手前で止める

ドロップダウンリスト、数値・日付の範囲チェック、数式によるカスタム検証 ― フォームバリデーションのコードを1行も書かずに、不正な入力をタイプした瞬間に弾く。ReoGrid Web の Excel 互換データ検証を、受注入力シートの実コードで解説。入力時メッセージ・エラーアラート・xlsx ラウンドトリップまで。

JavaScriptスプレッドシートで作る「信号機ダッシュボード」 ― 条件付き書式を実例で

在庫が少なければ赤、売上が目標超なら緑、キャンセル行は自動でフラグ ― セルを値に応じて色分けする処理を、スタイルのループを一切書かずに。ReoGrid Web の3種類の条件付き書式ルールを、値の変化に連動して再評価される在庫ダッシュボードの実コードで解説します。

ニュースレター

開発の最新情報をお届けします

新しいリリース・機能追加・お知らせをいち早く受け取るには、
メーリングリストにご登録ください。