kintoneでテーブルの行をデータの昇順・降順で並べ替える



kintoneのテーブルでデータを管理する際、データを昇順・降順に並び替える機能は不可欠な要件です。これにより、データの追跡、比較、および迅速な情報集計が容易になります。しかし、標準のkintoneにはこの機能が備わっていません。

この記事では、kintoneのテーブルをカスタマイズし、ヘッダーをクリックするだけでデータを自動的に昇順・降順にソートする方法を解説します。

準備アプリ
前回の記事で作成したアプリを引き続き使用します。
Excelのデータをkintoneのテーブルにまとめてコピー&ペーストしたい(やれそうでやれないことの補完)

JavaScriptプログラム
※「JSEdit for kintone」プラグインを使用して、ソースコードを編集します。JSEdit for kintone の画面から jQuery を追加・インストールすることで、HTML 要素のコーディングがより簡単になります。

プログラムの処理流れ

  1. サブテーブル「商品一覧」のHTML要素を特定する
    cybozu.data.page[‘FORM_DATA’] を使用して、フィールドコードとHTMLクラス間のマッピングを作成します。
    参考; kintoneの新規・編集レコード画面のフィールドをカスタマイズする裏技
  2. ヘッダーにソートアイコンを追加する
    各ヘッダーセルに を追加し、↑↓の矢印アイコンを表示させます。
    このアイコンにより、ソート方向(昇順/降順)を視覚的に示し、クリックで切り替えられるようにします。
  3. ヘッダーをクリックしてデータをソートする
    a) ヘッダーのインデックスに基づいて、対応する列のフィールドコードを取得します。
    b) 列のデータタイプを特定します:
    NUMBER の場合、数値としてソートします。
    例: [2, 10, 3] → 数値ソートで [2, 3, 10]
    文字列ソート (localeCompare) を使うと [10, 2, 3] となり、正しい順序になりません。
    その他のデータタイプの場合、文字列としてソートします。
    例: [“B”, “A”, “C”] → ソートで [“A”, “B”, “C”]
    c) 現在の状態に応じて、サブテーブルのデータ配列 (record[tableFieldCode].value) を昇順または降順にソートします。
  4. レコードを更新する
    ソート後、kintone.app.record.set() を使ってレコードのデータを更新します。
  5. ソート状態を保存する
    ヘッダーがクリックされるたびに、ソート状態(asc または desc)を保存し、次のクリック時にソート方向が切り替わるようにします。
(function() {
  "use strict";

  // FORM_DATAからサブテーブルのフィールドコードとHTMLクラス名をマッピング
  const FORM_DATA = cybozu.data.page['FORM_DATA'];
  const ELEMENT_FIELD_ID = {};
  for (const subTableId of Object.keys(FORM_DATA.schema.subTable)) {
    const subTable = FORM_DATA.schema.subTable[subTableId];
    ELEMENT_FIELD_ID[subTable.var] = subTableId;
  }

  const tableFieldCode = '商品一覧'; // 対象のサブテーブルフィールドコード

  // レコード作成・編集画面が表示されたときに処理
  kintone.events.on(['app.record.create.show', 'app.record.edit.show'], function(event) {

    // サブテーブル「商品一覧」のHTMLクラス名を取得
    const subtableClass = `.subtable-${ELEMENT_FIELD_ID[tableFieldCode]}`;

    // 各ヘッダーセルに対して処理
    $(`${subtableClass} .subtable-label-gaia`).each(function(index){
      const th = $(this);

      // ソートアイコンがなければ追加
      if(th.find('.sort-icon').length === 0){
        th.append('<span class="sort-icon" style="font-size:20px; margin-right: 10px"></span>');
      }

      // クリックイベントを設定
      th.off('click').on('click', function(){

        // 最新のレコードデータを取得
        const rec = kintone.app.record.get().record;

        // 現在のソート状態を反転(昇順/降順)
        const asc = !th.data('asc');

        // 他のヘッダーのソートアイコンをリセット
        $(`${subtableClass} .subtable-label-gaia .sort-icon`).text('');
        // 現在のヘッダーにアイコン表示
        th.find('.sort-icon').text(asc ? '↑' : '↓');

        // クリックされた列のフィールドコードを取得
        const fieldCode = Object.keys(rec[tableFieldCode].value[0].value)[index];
        // フィールドのデータ型を取得(NUMBER / SINGLE_LINE_TEXT / ...)
        const fieldType = rec[tableFieldCode].value[0].value[fieldCode].type;

        // サブテーブルの値をソート
        rec[tableFieldCode].value.sort(function(a, b){
          const valA = a.value[fieldCode].value || ""; // 値が未入力の場合は空文字
          const valB = b.value[fieldCode].value || "";

          // データ型に応じてソート方法を変更
          if(fieldType === 'NUMBER'){
            // NUMBER型は数値としてソート
            return asc ? (+valA) - (+valB) : (+valB) - (+valA);
          } else {
            // 文字列は文字順でソート
            return asc ? valA.localeCompare(valB) : valB.localeCompare(valA);
          }
        });

        // ソート結果をレコードに反映
        kintone.app.record.set({record: rec});

        // ソート状態を保存
        th.data('asc', asc);
      });
    });

    return event;
  });
})();

結果

記事を読んでいただきありがとうございます。
次回の記事では、テーブルの各列のデータでフィルターをかける方法についてご説明します。ぜひお楽しみに!

参照

レコードに値をセットする