2021年3月22日月曜日

対話グリッドに計算結果を加える

元々の相談は対話グリッドの合計行をレポートの末尾ではなく先頭に表示させることができないか?でした。それでちょっと実装してみました。

対話グリッドの機能が使えなくなるといった不都合はあるのですが、色々な機能を組み合わせるとこんなこともできるよ、という演習として手順を示します。

最初にクイックSQLでモデルを定義します。

# prefix: ttl
# semantics: default
sums
   col1 num
   col2 num
   col3 num

作成される表TTL_SUMSのCOL1, COL2, COL3の全列の合計を対話グリッドの一行に表示します。対話グリッドは編集可能である状態を維持します。

空のアプリケーションを作成します。名前行の合計としました。アプリケーションの作成を実行します。

アプリケーションが作成されたら、ホーム・ページをページ・デザイナで開き、対話グリッドのリージョンを作成します。ソースとなるSQL問合せとして、以下を指定します。

select
id,
col1,
col2,
col3,
'UD' prot
from
ttl_sums
union all
select
0 id,
sum(col1) col1,
sum(col2) col2,
sum(col3) col3,
'' as prot
from ttl_sums

合計を計算した行をUNION ALLで一行追加しています。行の主キーとなるIDはとすることで、表TTL_SUMS自体には含まれない値を指定します。行PROTを許可された行操作列に指定することにより、通常の行はUD - 更新と削除が可能とし、合計行は編集も削除もできないようにします。

リージョンのタイトル行の合計タイプ対話グリッドを指定します。

IDタイプ非表示にし、主キーONにします。

PROTタイプ非表示にし、問合せのみONにします。

対話グリッドのAttributesを開き、編集有効ONにします。また、許可された行操作列として、PROTを選択します。

後ほど動的アクションからリージョンを参照するために、静的IDSUMS_ON_TOPとして設定しておきます。

対話グリッドのソースとなるSQLにはUNION ALLが含まれているので、そのままでは行の更新できません。続いて、プロセスの設定を変更します。

ターゲット・タイプをRegion SourceからTable / View に変更し、表名としてTTL_SUMSを選択します。行のロックもRegion Sourceに対しては行えないため、以下のPL/SQL Codeを設定します。

declare
rec ttl_sums%rowtype;
begin
select * into rec from ttl_sums where id = :ID for update nowait;
end;


最後に対話グリッド上の合計行がデータの更新時に再表示されるように、動的アクションを設定します。

対話グリッド上で動的アクションの作成を実行し、名前合計の更新とします。タイミングイベント保存 [対話グリッド]で、選択タイプリージョンリージョンとして行の合計を選択します。

TrueアクションとしてJavaScriptコードの実行を選択し、設定コードに以下を記述します。

let myGrid = apex.region("SUMS_ON_TOP").call("getViews", "grid");
let model = myGrid.model;
model.fetchRecords( model.getRecord(0) );

対話グリッドでのIDが0の行(つまり合計行)を再取得して表示し直します。

以上で作業は完了です。アプリケーションを実行すると、先頭のGIF動画のように動作します。

対話グリッド自体の設定、プロセスの設定、動的アクションを組み合わせることで、このような機能も比較的簡単に実装できます。

合計だと対話グリッドにすでにある機能なので、あまり必要性は感じないかもしれません。しかし、この方法であればSQLの分析関数でも活用できます。動的アクションについては、同じ対話グリッドよりは別のリージョンに対して再表示(リージョンのリフレッシュ)を行うようにする場合が多いかもしれません。

作成したアプリケーションのエクスポートを以下に置きました。

https://github.com/ujnak/apexapps/blob/master/exports/sumsontop.sql

Oracle APEXのアプリケーション開発の参考になれば幸いです。