2022年5月26日木曜日

レポート上で選択した行のIDをページ・アイテムに設定する

 レポート上で行を選択して、その情報を使いたいというのはよくある要件です。簡単に実装方法をまとめてみました。

サンプルの実装には、サンプル・データセットに含まれるEMP/DEPTのEMPのデータを使用しています。表EMPに含まれる従業員を選択し、選択された従業員の従業員番号をページ・アイテムに設定します。

対話グリッドでは動的アクションとして実装します。行セレクタや選択行の変更イベントなどが標準で実装されているため、追加で記述するコードが少なくて済みます。また、動的アクションなので、選択を確定するためにページを送信する必要がありません。

推奨は、対話グリッドを使った実装です。

クラシック・レポートでも実装できます。APEX_ITEM.CHECKBOX2を使って、チェックボックの列をレポートに追加します。


以下より、両方の実装について紹介します。


アプリケーションの作成


あらかじめサンプル・データセットEMP/DEPTをインストールします。

SQLワークショップユーティリティサンプル・データセットからインストールします。

アプリケーション作成ウィザードを起動します。作成するアプリケーションの名前サンプル・レコード選択とします。アプリケーションには、対話グリッドとクラシック・レポートのページを作成します。

最初にホーム・ページの編集を開いて、ページを削除します。

ページの追加をクリックし、対話グリッドを選択します。

ページ名対話グリッドとし、表またはビュー編集を許可を選択します。表またはビューとして表EMPを選択します。

以上で、ページの追加をクリックします。


再度、ページの追加をクリックします。今度はクラシック・レポートを追加します。追加ページを開いて、クラシック・レポートを選択します。


ページ名クラシック・レポートとし、表またはビュークラシック・レポートを選択します。表またはビューとして表EMPを選択します。

以上で、ページの追加をクリックします。


アプリケーションの作成を実行します。


以上で、アプリケーションの準備は完了です。


対話グリッドでの実装



対話グリッドの行セレクタを使って、選択した行をページ・アイテムに設定します。

対話グリッドのページを開き、静的コンテンツのリージョンを作成します。作成したリージョンにページ・アイテムP1_SELECTED_EMPLOYEESを作成します。このページ・アイテムに選択した行、つまり複数の従業員の従業員番号を','区切りで設定します。


対話グリッドのリージョンEmployees動的アクションを作成します。

識別名前従業員の選択とします。タイミングイベントとして選択の変更[対話グリッド]を指定します。選択タイプリージョンリージョンEmployeesになります。


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

// Fetch model.getRecord in Row Select mode of the IG
// https://community.oracle.com/tech/developers/discussion/4478408/fetch-model-getrecord-in-row-select-mode-of-the-ig
let selectedRecords = this.data.selectedRecords,
recordIds = [];
if (selectedRecords.length > 0) {
let model = this.data.model;
// got some selected records
// turn the records into record ids
recordIds = selectedRecords.map(r => { return model.getRecordId(r);});
} else {
// maybe there is nothing selected or maybe this is grid view and it is in cell range selection mode
let region = apex.region(this.triggeringElement.id),
view = region.call("getCurrentView");
if (view.internalIdentifier === "grid" && view.view$.grid("option", "selectCells")) {
// yup it is grid view in cell range mode
let range = view.view$.grid("getSelectedRange");
if (range) {
recordIds = range.recordIds;
}
}
}
apex.items.P1_SELECTED_EMPLOYEES.setValue(recordIds);

対話グリッドでの実装は以上で完成です。

対話グリッドのAttributesの設定を変更し、行の追加行の更新行の削除をできないようにしたり、ツール・バー表示OFFにして、行の選択以外できないようにすると、より使いやすくなるでしょう。



クラシック・レポートでの実装


クラシック・レポートでも同様に、選択した従業員を設定するページ・アイテムP2_SELECTED_EMPLOYEESを作成します。さらに、送信ボタンB_SUBMITも作成します。ボタンの動作アクションページの送信とします。


クラシック・レポートのリージョンEmployeesを選択し、ソースタイプSQL問合せに変更します。レポートにチェックボックスが含まれるよう、SQL問合せにAPEX_ITEM.CHECKBOX2を含んだSELECT文を記述します。

select
apex_item.checkbox2(
p_idx => 1
, p_value => empno
, p_attributes =>
case when instr(:P2_SELECTED_EMPLOYEES,':' || empno) <> 0 then
'CHECKED'
else
null
end
) "Select"
, empno
, ENAME
, JOB
, MGR
, HIREDATE
, SAL
, COMM
, DEPTNO
from EMP



追加した列SelectはHTMLが生成されるため、セキュリティ特殊文字をエスケープOFFにします。


レポート上での選択結果は、ページの送信時にAPEX_APPLICATION.G_F01としてサーバーに渡されます。それを受け取って、ページ・アイテムP2_SELECTED_EMPLOYEESに設定するプロセスを作成します。

作成したプロセスの名前従業員の選択とし、ソースPL/SQLコードとして以下を記述します。

declare
l_count number;
l_string varchar2(4000);
l_value varchar2(80);
begin
l_count := apex_application.g_f01.count;
for i in 1..l_count
loop
l_value := '';
if apex_application.g_f01.exists(i) then
l_value := apex_application.g_f01(i);
end if;
l_string := l_string || ':' || l_value;
apex_debug.info(l_string);
end loop;
:P2_SELECTED_EMPLOYEES := l_string;
end;



以上でクラシック・レポートでの実装も完了です。

今回作成したアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/sample-record-selection.sql

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