Migaro. 技術Tips

                       

ミガロ. 製品の技術情報
IBMiの活用に役立つ情報を掲載!


グリッドの小計と総計へのコンテキスト追加

(※このトピックスは、Valence開発元(米CNX社)のブログ記事を翻訳・再編集したものとなります。原文記事は、コチラとなります。)

Webの世界においてグリッドは、ユーザーにビジネスデータをわかりやすく、かつ意味のある形で提示するために、最も欠かせないUIツールといっても過言ではありません。Nitro App Builder (NAB) のグリッドウィジェットを使用する際、集計レベルでデータの表示をカスタマイズすることで、さらに明確さを高めることができます。以前のブログ記事でも述べたように、グリッドセル内でカスタムレンダラーを利用すれば、通常セル、小計セル、総計セルの表示を自在に調整できます。

従来から、通常セルと集計セル(小計/総計)を区別することは可能でしたが、小計行と総計行のどちらにレンダリングが適用されているのかを判別する簡単な方法はありませんでした。幸いにも、Valence 6.3 ビルド (6.3.20250821.0) からは、新しいグループチェックプロパティが導入され、この課題が解決されました。

そこで今月のヒントでは、以前のブログ記事の内容を振り返りつつ、集計レベルでのカスタムレンダラーに焦点を当てます。具体的には、小計行(例:国別の顧客売上)と総計行を区別し、それぞれに異なるレンダリングロジックを適用する方法について解説します。

なぜカスタムレンダラーが重要なのか

売上データを地域別に集計したり、その他のビジネスメトリクスを分析したりする際、NABのグリッドでは数値の集計を簡単に行うことができます。チェックボックスをオンにするだけで、合計、平均、件数といった標準的な集計機能を有効にし、さらに別のチェックボックスでグループ化も可能です。

しかし、単純に数値だけで表現された標準的な集計では、文脈やフォーマットとして十分でない場合があります。特に「小計(例:国ごとの売上合計)」と「総計(例:全ての国を合わせた売上合計)」を区別したいときには、その違いが明確に伝わらないことがあります。

カスタムレンダラーを使えば、集計行の計算方法や表示方法を開発者が細かく制御できるようになります。例えば、顧客の国別にグループ化した売上グリッドで、小計行には「Total Sales for [Country]」と特定のフォーマットを適用し、総計行には「Global Sales Total」と別のスタイルや計算方法を使うことが可能です。こうした差別化によって可読性が向上し、混乱を避け、グリッドの出力をビジネス要件に合わせることができます。

さらに、カスタムレンダラーを活用すれば、他のカラムのデータを組み合わせたり、条件付きロジックを適用したり、HTMLによる装飾を追加したりして、より洗練されたユーザー体験を提供することもできます。

シナリオ:国別に売上を集計する

実際的な例を考えてみましょう。
グリッドで、国ごとにグループ化・ソートされたアクティブ顧客ごとの売上合計を一覧表示する場面です。各行には基本的な顧客情報と、売上合計のカラムが表示されます。ここで次のようにしたいとします:

  • 小計行:各国ごとの売上合計を「Total Sales for [Country]」とラベル付けし、通貨形式で表示する。こうすることで、ユーザーはグループの先頭までスクロールしなくても、小計がどの国に対応しているかをすぐに確認できます。
  • 総計行:すべての国の売上合計を「Global Sales Total」とラベル付けし、強調のために太字で表示する。

通常のアプリケーションでデフォルト設定を使った場合、小計行と総計行には同じ集計関数(例:SUM)が適用され、見た目上大きな違いはありません。

そこで、カスタムレンダラーを使えば、特定のテキストやフォーマット、ロジックを組み込むことで、異なる種類の集計行を見やすく際立たせることができます。

カスタムレンダラーの実装方法

ここでは、グリッドにカスタムレンダラーを追加する手順を説明します。ポイントは、小計行と総計行を区別することです。すでに売上データを含むデータソースに紐づいたグリッドウィジェットをセットアップ済みであることを前提とします。データには国別と各顧客ごとの売上合計額の列が含まれているものとします。以下の例では、Valence に含まれているおなじみの DEMOCMAST ファイルをデモ用に使用します。

1: グリッドをグループ化と集計用に設定する

Nitro App Builder で、顧客売上データに紐づいたグリッドウィジェットを作成または編集し、必要なすべての列(特に国と売上。DEMOCMAST では CCOUNTRY 列と CYTDSALES 列)をグリッドに含めてください。
次に、グリッドの全般設定(左の2番目のタブ)を開き、右側のカルーセルメニューの「Data」セクションを表示し、CCOUNTRY フィールドをグループ化するように設定します。

次に、グリッドの列設定(左側の最初のタブ)を開き、CYTDSALES 列を探します。電卓アイコンをクリックして「Total」チェックボックスをオンにし、集計を有効にします。これにより、グリッドには国ごとの小計行と総計行が含まれるようになります。

2: カスタムレンダラーを追加する

CYTDSALES 列の設定画面で、カスタムフォーマットオプション(<>)をクリックし、セルの値がどのように表示されるかを制御するカスタム JavaScript ロジックを定義します。これにより、レンダラーコードを記述するポップアップウィンドウが開きます。

ここで、小計行と総計行を区別するロジックを含んだカスタムレンダラー関数を書きます。レンダラー関数には、以下のパラメータが渡されます:

  • value(セルの値)
  • rec(レコードデータ)
  • summary(セルにサマリ関数が適用されている場合に渡されるオブジェクト。サマリ行に関する情報を持つ)

ここで重要なのが新しく追加された summary.isGroup プロパティです。

  • 小計行の場合は true に設定され、
  • 総計行の場合は false になります。

この仕組みを利用して、小計行と総計行をきちんと区別できるようになります。

レンダラーの各行を詳しく見てみましょう

v = Ext.util.Format.currency(v);

ここでは、渡されてきた数値(v)を Ext JS のユーティリティ関数で通貨形式(例:$0,000.00)にフォーマットしています。JavaScript ではこのようなフォーマットを行う方法は他にも多数あり、必要に応じてAI アシスタントに聞いてみると別のアプローチも教えてくれます。実際のところ、このレンダラー全体をAI アシスタントに書かせることも可能ですので、ぜひ試してみてください。

if (summary.isRow) {

この if ブロックは summary.isRow が true のときに実行されます。これはつまり、グループ小計行または総計行のセルに対して処理をしている場合です。通常の行(集計でない行)の場合は、この部分はスキップされます。

if (summary.isGroup) {

ここが新しく導入されたプロパティを利用して、グループ小計行と総計行を区別する部分です。summary.isGroup が true であれば、レンダラーは現在 グループ(この例では顧客の国)ごとの合計を処理しています。そのため、以下のようにグループ名を含めた値を返すことができます。

return `Total for ${summary.group.get('CCOUNTRY')} : ${v}`;

ここではセルに表示する最終的な値を返しています。そして、この行にはちょっとした JavaScript のお勉強要素が含まれています。

${xxx} という ドル記号 + 波括弧の形は、JavaScript で 変数や式を文字列に埋め込む省略記法です。これが正しく動作するためには、文字列を通常のシングルクォート(’)やダブルクォート(”)ではなく、バッククォート(“)で囲む必要があります。JavaScript ではこれを テンプレートリテラルと呼びます。

テンプレートリテラルを使うと、${xxx} 部分がその場で評価される特別な文字列になり、従来のように「文字列を一旦閉じて、値を連結して、また文字列を続ける」といった冗長な書き方をしなくても済むため、記述が短く分かりやすくなります。

  • summary.group.get(‘field_name’) は、グループ化対象の国名を返します(この式はレンダラーウィンドウ下部に「よく使われる式」としても表示されます)。
  • ${v} は、先ほど通貨形式に整えた売上値(v)を挿入します。
 } else {
      return `<b>Grand Total : ${v}</b>`;
 }

ここは summary.isGroup が false、つまり 総計行である場合に実行されます。ここでは単純に「Grand Total」の値を太字(<b>タグ)で表示し、小計行との差別化をしています。

} 
return v; 

最後に catch-all 的な処理があります。もし上記の return 文に当てはまらなかった場合、つまり 通常の明細行であれば、この行に到達します。その場合は、通貨形式に変換済みの値(v)をそのまま返して終了です。

カスタムレンダラーを実装した結果はこのようになります…

3: 書式設定やツールチップなどによる追加強化を検討する

グリッドの列をさらにユーザーフレンドリーにするために、次のような工夫が可能です:

  • HTML タグによる装飾(例:<b>、<i>、<div> タグなど)を使ってテキストをスタイル付けする(総計行で太字を使ったのと同じ要領)
  • 色を変更して、値が小さい・大きいなど特定の条件を強調表示する
  • ツールチップを追加して、セルにマウスを重ねた際に補足情報を表示する(data-qtip 属性を使用)

また、これらのシナリオに対応する JavaScript コードをAI アシスタントに生成させることもできます。ちょっとした指示を与えるだけで、何時間も Google で調べたり試行錯誤したりせずに、プロレベルの書式設定をすぐに実現できるはずです。