ボタンをクリックして表のデータをJSONドキュメントとしてダウンロードする機能を、動的アクションのダウンロードを使って実装してみました。
ダウンロードするJSONドキュメントは、対話モード・レポートに表示されているデータを元に生成します。対話モード・レポートのソースとしてビューALL_OBJECTSを設定しています。また、リージョンIDを取得するために、対話モード・レポートに静的IDとしてALL_OBJECTSを割り当てています。
ページ・アイテムP1_FILENAMEに設定したファイル名を、ダウンロードするファイル名にします。
ボタンをクリックしたときに実行される動的アクションの実行のタイプとしてデバウンスを選択し、時間は2000ミリ秒、即時はオンにします。
TRUEアクションとしてダウンロードを作成します。設定の複数のファイルはオフ、ファイルの表示形式として添付を選択します。
ソースのSQL問合せとして以下を記述します。OracleのSQLで使えるJSONファンクションはデフォルトでVARCHAR2(4000)を返します。そのため、4000バイトを超えるデータを扱う場合はreturning clobを明示する必要があります。
select
json_serialize(
json_object(
'objects' value
json_arrayagg(
json_object(*)
returning clob)
returning clob)
returning clob pretty)
,:P1_FILENAME
,'application/json'
from all_objects
動的アクションによるダウンロードが開始した時点で、アクションの処理は終了します。大抵の場合、JSONドキュメントの準備はすぐに終了し、そのデータをサーバーからブラウザにダウンロードする際に時間がかかります。その間にボタンをクリックすると、クリックした回数分同じJSONドキュメントがダウンロードされます。
JSONドキュメントのダウンロードが完了するまで新たなボタン・クリックを許可しないように実装できればよいのですが、かなり難しい実装になります。次善の策として、動的アクションにデバウンスを設定しています。即時をオンにしているため、最初のクリック時はすぐにダウンロードが呼び出されます。時間を2000ミリ秒(2秒)としているので、その後2秒間はボタン・クリックを無視します。ボタンを何回クリックするかにかかわらず、最大で2秒に一回しかダウンロードは実行されません。ユースケースに応じて秒数を延長することで、サーバーへの負荷を軽減できます。
ボタンDOWNLOAD_SELECTEDをクリックすると、対話モード・レポートに一覧されているデータをJSONドキュメントとしてダウンロードします。
ダウンロードを開始する前に、対話モード・レポートからダウンロード対象のデータを取り出し、JSONに変換します。
TRUEアクションとしてサーバー側のコードを実行を作成し、設定のPL/SQLコードとして以下を記述します。取り出したJSON形式のデータは、一旦APEXコレクションJSON_CONTENTに保存して、後続のアクションにデータを渡します。
declare
l_region_id apex_application_page_regions.region_id%type;
l_context apex_exec.t_context;
l_clob clob;
begin
select region_id into l_region_id from apex_application_page_regions
where static_id = 'ALL_OBJECTS';
l_context := apex_region.open_query_context(
p_page_id => :APP_PAGE_ID
,p_region_id => l_region_id
);
apex_json.initialize_clob_output;
apex_json.open_object;
apex_json.write_context( 'objects', l_context );
apex_json.close_object;
--
l_clob := apex_json.get_clob_output;
apex_collection.create_or_truncate_collection('JSON_CONTENT');
apex_collection.add_member(
p_collection_name => 'JSON_CONTENT'
,p_n001 => 1
,p_clob001 => l_clob
);
--
apex_json.free_output;
end;
後続の処理でAPEXコレクションのデータを参照するため、実行の結果の待機はオンにします。
ダウンロードのソースのSQL問合せでは、APEXコレクションよりCLOBを取り出し、ダウンロード対象とします。
select
clob001
,:P1_FILENAME
,'application/json'
from apex_collections
where collection_name = 'JSON_CONTENT' and N001 = 1;
今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/sample-json-download-for-report.zip
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完