はじめに
APEXでINPUTデータを加工してから、OUTPUT(複数ビュー)をなどをcsvファイルにしてまとめてZip出来たらいいね!という話が合ったので、できるかどうかやってみました。 以下のblogを参考に作成しました。 https://www.apex-at-work.com/2015/10/custom-csv-export-as-zip-file.html https://apexcornies.wordpress.com/2020/04/04/create-a-download-zip-button-in-oracle-apex/事前準備
今回はTASKSとEMPLOYEEという表をcsvファイルに出力してZipでダウンロードしていきます。 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/681023/85f15715-8301-35a7-ced7-f647b76301f0.png) ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/681023/65f6e3c0-953b-be61-0053-d25df555192a.png)ボタンの作成
downloadボタンを作成します。 ボタン名を変更し、位置などは好きに配置してください。 基本はデフォルトのままで大丈夫です。ページプロセスの作成
プロセスを作成していきます。 左ペインの矢印のループになっているタブのプロセスを右クリックし、プロセスの作成をクリックします。プロセスを編集していきます。
名前にCreate_ZIPと付け、ソースの言語にをPL/SQLに、コードに以下のものを入力します。
ここでは、ZIPという名前のAPEX_COLLECTIONを作成し、ここにデータをcsv形式でBLOB化したものを追加していきます。
サーバー側の上条件で、ボタン押下時に先ほど作成したボタンを選択します。
declare
l_zip_file blob;
L_BLOB BLOB;
L_CLOB CLOB;
L_DEST_OFFSET INTEGER := 1;
L_SRC_OFFSET INTEGER := 1;
L_LANG_CONTEXT INTEGER := DBMS_LOB.DEFAULT_LANG_CTX;
L_WARNING INTEGER;
L_LENGTH INTEGER;
L_NAME VARCHAR2(200);
cursor c1 IS
select XMLCAST(XMLAGG(XMLELEMENT(E,COL_VALUE||CHR(13)||CHR(10))) AS CLOB) AS CLOB_VAL, 'TASKS' as TABLE_NAMES
FROM (
SELECT 'ID,PROJECT,TASK_NAME,STATUS' AS COL_VALUE FROM DUAL
UNION ALL
SELECT ID||','||
PROJECT||','||
TASK_NAME||','||
STATUS AS COL_VALUE FROM TASKS)
UNION ALL
select XMLCAST(XMLAGG(XMLELEMENT(E,COL_VALUE||CHR(13)||CHR(10))) AS CLOB) AS CLOB_VAL, 'EMPLOYEE' as TABLE_NAMES
from (
SELECT 'ID,LOCATION,DEPARTMENT,NAME' AS COL_VALUE FROM DUAL
UNION ALL
SELECT ID||','||
LOCATION||','||
DEPARTMENT||','||
NAME AS COL_VALUE FROM EMPLOYEE)
;
begin APEX_COLLECTION.CREATE_OR_TRUNCATE_COLLECTION(
p_collection_name => 'ZIP');
for rec in c1 loop
DBMS_LOB.CREATETEMPORARY(L_BLOB, FALSE);
L_DEST_OFFSET := 1;
L_SRC_OFFSET := 1;
L_LANG_CONTEXT := DBMS_LOB.DEFAULT_LANG_CTX;
L_WARNING := null;
DBMS_LOB.CONVERTTOBLOB( DEST_LOB => L_BLOB,
SRC_CLOB => rec.CLOB_VAL,
AMOUNT => DBMS_LOB.LOBMAXSIZE,
DEST_OFFSET => L_DEST_OFFSET,
SRC_OFFSET => L_SRC_OFFSET,
BLOB_CSID => NLS_CHARSET_ID('WE8MSWIN1252'),
LANG_CONTEXT => L_LANG_CONTEXT,
WARNING => L_WARNING
);
L_NAME := 'EXPORT_'||rec.table_names||'.csv';
APEX_ZIP.ADD_FILE(
p_zipped_blob => l_zip_file,
p_file_name => L_NAME,
p_content => L_BLOB
);
end loop;
/*---------------------------------------------------------*/
apex_zip.finish (
p_zipped_blob => l_zip_file );
APEX_COLLECTION.ADD_MEMBER(
p_collection_name => 'ZIP',
p_blob001 => l_zip_file);
END;
CURSORの中のSQLでcsvで取得したいデータを指定します。
引数を渡せば、合致するものだけでファイルを作成することができます。
ブランチの作成
ブランチを作成していきます。 左ペインの矢印のループになっているタブのブランチを右クリックし、ブランチの作成をクリックします。 名前にGet Zipとつけ、動作のターゲットをZIPを行うページに設定してください。 また、ターゲットの詳細でこの後作成するAjaxコールバックのプロセスの名前を指定します。Ajaxコールバックの作成
Ajaxコールバックを作成していきます。 左ペインの矢印のループになっているタブのAjaxコールバックを右クリックし、プロセスの作成をクリックします。 名前にdownload_zip_fileと付け、PL/SQLのコードに以下のものを入れます。declare
var_mimetype varchar2(50) := 'application/zip';
var_name varchar2(100) := 'files_by_project.zip';
var_blob blob;
begin
-- Get the BLOB from the ZIP collection
select blob001 into var_blob from apex_collections where collection_name = 'ZIP' and seq_id = 1;
sys.htp.init;
sys.owa_util.mime_header( var_mimetype, FALSE );
sys.htp.p('Content-length: ' || sys.dbms_lob.getlength( var_blob));
sys.htp.p('Content-Disposition: attachment; filename="' || var_name || '"' );
sys.htp.p('Cache-Control: max-age=3600'); -- tell the browser to cache for one hour, adjust as necessary
sys.owa_util.http_header_close;
sys.wpg_docload.download_file( var_blob );
apex_application.stop_apex_engine;
exception when apex_application.e_stop_apex_engine then
NULL;
end;
var_nameを変更すると、ダウンロードするZIPファイルの名前を変更できます。
実装結果
実際にdownloadしていきます! files_by_project.zipというファイルがダウンロードできました。zipファイルの中身はこんな感じです。
無事にどちらのcsvファイルも取得できています。