2025年5月2日金曜日

任意のSELECT文をデータ・ソースとしたOracle JETの表を動的に生成する

以前の記事「任意のSELECT文をデータ・ソースとしたJETチャートを動的に生成する」では、Oracle JETのoj-chart要素を動的に生成してチャートを表示しました。本記事ではoj-chartの代わりにoj-table要素を動的に生成することにより、任意のSELECT文をソースとした表を表示します。

作成したアプリケーションは以下のように動作します。


アプリケーション自体はチャートの記事で作成したものとほぼ同じです。oj-chart要素は表示するデータを静的に割り当てることができましたが、oj-table要素はDataProviderとして割り当てる必要があります。そのため、アプリケーションの作り方が少し変わります。

このアプリケーションのエクスポートは以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/dynamic-jet-table.zip

以下よりチャートを表示するアプリケーションとの差分について説明します。

ページ・プロパティJavaScriptページ・ロード時に実行は以下になります。ojs/ojchartの代わりにojs/ojtableをロードします。

require(['ojs/ojtable'], function() {});


任意のSELECT文を渡して実行結果を得るAjaxコールバックGET_TABLEとして作成します。ソースPL/SQLコードとして以下を記述します。チャートのときはAjaxコールバックでHTMLを生成しましたが、oj-table要素はデータをHTMLの記述に含めることはできないため、列情報をcolumns属性、データをdata属性として持つJSONドキュメントを返すようにしています。

declare
/* SQLの実行 */
l_sql varchar2(32767);
l_cursor integer;
l_col_cnt integer;
l_desc_tab dbms_sql.desc_tab;
l_label_name varchar2(128);
l_value varchar2(32767);
l_rows number;
e_invalid_sql exception;
/* oj-tableのcolumnsに渡す */
l_columns_arr json_array_t;
l_column_obj json_object_t;
/* oj-tableのdataに渡す */
l_data_arr json_array_t;
l_data_obj json_object_t;
/* GET_TABLEの出力 */
l_response json_object_t;
l_response_blob blob;
begin
/* 与えられたSQLの検証 */
l_sql := :P1_SQL;
if l_sql is null or l_sql = '' then
raise e_invalid_sql;
end if;
/* カーソルのオープン */
l_cursor := dbms_sql.open_cursor;
/* SQLのパース */
dbms_sql.parse(l_cursor, l_sql, dbms_sql.native);
/*
* 列定義をoj-tableのcolumnsに渡せるJSON配列に変換する。
*/
l_columns_arr := json_array_t();
dbms_sql.describe_columns(l_cursor, l_col_cnt, l_desc_tab);
for i in 1..l_col_cnt
loop
l_column_obj := json_object_t();
l_label_name := l_desc_tab(i).col_name;
l_column_obj.put('headerText', l_label_name);
l_column_obj.put('field', l_label_name);
l_columns_arr.append(l_column_obj);
dbms_sql.define_column(l_cursor, i, l_value, 32767);
end loop;
/*
* SELECT文の実行して取り出した行をoj-tableのdataに渡せる
* JSON配列に変換する。
*/
l_rows := dbms_sql.execute(l_cursor);
l_data_arr := json_array_t();
loop
exit when dbms_sql.fetch_rows(l_cursor) = 0;
l_data_obj := json_object_t();
for i in 1..l_col_cnt
loop
dbms_sql.column_value(l_cursor, i, l_value);
l_data_obj.put(l_desc_tab(i).col_name, l_value);
end loop;
l_data_arr.append(l_data_obj);
end loop;
/* カーソルのクローズ */
dbms_sql.close_cursor(l_cursor);
/*
* 呼び出し元にSQLの実行結果を返す。
*/
l_response := json_object_t();
l_response.put('data', l_data_arr);
l_response.put('columns', l_columns_arr);
l_response_blob := l_response.to_blob();
/*
* GET_TABLEの呼び出し元にJSONを返す。
*/
sys.htp.init;
sys.htp.p('Content-Length: ' || dbms_lob.getlength(l_response_blob));
sys.htp.p('Content-Type: application/json');
sys.owa_util.http_header_close;
sys.wpg_docload.download_file(l_response_blob);
end;
view raw get_table.sql hosted with ❤ by GitHub


表の出力先となるDIV要素のIDをchartからtableに変更しています。

<div id="table"></div>


oj-table要素を生成するJavaScriptのコードは以下になります。ボタンGENERATEをクリックしたときに実行されるTRUEアクション設定コードを置き換えます。

require(['ojs/ojarraydataprovider'], function(ArrayDataProvider) {
apex.server.process( "GET_TABLE", {
pageItems: "#P1_SQL"
}, {
success: function( response ) {
apex.debug.info(response);
// this.tableDataProvider = new ArrayDataProvider( data.data, { keyAttributes: "EMPNO" } );
this.tableDataProvider = new ArrayDataProvider( response.data );
const jetTable = document.createElement("oj-table");
jetTable.columns = response.columns;
jetTable.data = this.tableDataProvider;
const elem = document.getElementById("table");
elem.prepend(jetTable);
}
});
});

以上でアプリケーションは完成です。

Oracle JETのoj-tableのリファレンスは以下になります。今回はoj-tableを表示するために最低限必要な属性であるcolumnsとdataのみを設定しています。他の属性を設定することにより、より使い勝手を向上させることも可能でしょう。

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