こちらの記事の続きです。同じページを表APEX_APPLICATION_TEMP_FILESではなく、自分で作成した表を使って実装します。
アップロードしたExcelファイルを保存する表を作成します。クイックSQLの以下のモデルから表FUP_FILESを作成します。
# prefix: fup
# semantics: default
files
content file
生成されるDDLは以下になります。生成したDDLを実行し、表を作成します。
create table fup_files (
id number generated by default on null as identity
constraint fup_files_id_pk primary key,
content blob,
content_filename varchar2(512),
content_mimetype varchar2(512),
content_charset varchar2(512),
content_lastupd date
)
;
すでに作成済みのアプリケーション、ファイルのアップロードにページを追加します。アプリケーション・ビルダーよりページの作成を実行し、ページ作成ウィザードでフォームをクリックします。
フォームをクリックします。
ページ名をユーザー表とします。ページ・モードは標準、送信時にここにブランチ、取り消してページに移動の双方とも、自ページのページ番号(この場合は3)を指定します。次に進みます。
ナビゲーションのプリファレンスとして、新規ナビゲーション・メニュー・エントリの作成を選択します。次に進みます。
データ・ソースはローカル・データベースとし、表/ビューの名前にFUP_FILES(表)を選択します。次に進みます。
主キー型は主キー列の選択とし、主キー列としてID(Number)を選びます。作成をクリックします。
ページが作成されます。最初にP3_CONTENT_MIMETYPE、P3_CONTENT_CHARSET、P3_CONTENT_LASTUPDを表示させないため、これらのページ・アイテムを選択して、サーバー側の条件をなしに変更します。
ファイル参照のページ・アイテムP3_CONTENTを選択し、前の記事のP2_FILEと同様の動作になる設定を行なっていきます。
ラベルはアップロードするファイル、設定の表示形式はBlock Dropzone、ドロップ・ゾーンの説明はExcelファイル(XLSX形式)をドロップしてください。とします。記憶域タイプはBLOB column specified in Item Source attributeとします。MIMEタイプ列はCONTENT_MIMETYPE、ファイル名列はCONTENT_FILENAME、文字セット列はCONTENT_CHARSET、BLOB最終更新列はCONTENT_LASTUPDを指定します。最大ファイル・サイズは5000KBとします。
一旦ファイルが選択されたら、その後にページ・アイテムが変更されることを防ぐため、サーバー側の条件でタイプにアイテムがNULLを選択し、アイテムにP3_CONTENTを指定します。この設定によりファイルが未選択のときに限り、ファイル参照が表示されます。
主キーであるページ・アイテムP3_IDを、ページ送信後に設定されたIDの値を維持するよう、セッション・ステートの保持をセッションごと(ディスク)に変更します。
ファイルを選択した時点でアップロードを行うよう、ページ・アイテムP3_CONTENTに動的アクションの作成を行います。
動的アクションの名前をファイルのアップロードとします。タイミングはデフォルトでイベントが変更、選択タイプはアイテム、アイテムはP3_CONTENTとなり、P3_CONTENTが変更されるとアクションが実行されます。
Trueアクションを選択し、アクションとしてページの送信を選択します。設定のリクエスト/ボタン名としてCREATEを入力します。この指定により、動的アクションから実行されるページの送信で、ボタンCREATE(ラベルは作成)を押した時と同じ動作、つまり表へのデータの挿入が行われます。
この時点でファイルのアップロードまでは実装できています。
アップロードされた結果をプレビューするために、クラシック・レポートのリージョンを作成します。
リージョンを作成し、名前をプレビュー、タイプをクラシック・レポートとします。ソースの位置はローカル・データベース、タイプをSQL問合せとし、SQL問合せに以下のSELECT文を記載します。
select
col001 "PREFECTURE",
col002 "CITY",
col003 "COUNT"
from
apex_data_parser.parse(
p_content =>
(
select content from fup_files
where id = :P3_ID
),
p_file_name => :P3_CONTENT_FILENAME,
p_skip_rows => 1,
p_file_charset => 'AL32UTF8',
p_max_rows => 10
)
ページ作成ウィザードによって生成されたボタンはすべて使用しないので、ボタンCANCEL、DELETE、SAVE、CREATEを選択し、サーバー側の条件のタイプをなしにします。
表FUD_CITYLISTにデータを投入するプロセスを作成します。データの送信を行うボタンを作成します。ボタン名をB_SUBMIT、ラベルを送信とします。
続いて、ボタンB_SUBMITが押された時に実行されるプロセスを作成します。名前を表にロードとし、タイプはコードを実行、ソースの位置はローカル・データベース、言語はPL/SQLを選択し、PL/SQLコードとして以下を記述します(プレビューではないのでp_max_rowsの指定を除いています)。サーバー側の条件として、ボタン押下時にB_SUBMITを指定することにより、送信ボタンを押した時のみ実行されるようにします。
begin
delete from fup_citylist;
insert into fup_citylist(prefecture, city, count)
select
col001 "PREFECTURE",
col002 "CITY",
col003 "COUNT"
from
apex_data_parser.parse(
p_content =>
(
select content from fup_files
where id = :P3_ID
),
p_file_name => :P3_CONTENT_FILENAME,
p_skip_rows => 1,
p_file_charset => 'AL32UTF8'
);
end;
上記のコードは、送信をクリックした際に、すでに保存されているデータをすべて削除し、新たにアップロードしたデータで入れ替えています。追加やマージといった動作にしたい場合は、PL/SQLのコードを変更することになります。
以上で表へのデータのロードも実行されるようになりました。動作確認をもう少し簡単にするため、ページを初期化するボタンと表FUD_CITYLISTの内容を表示するレポートを追加します。この作業は前の記事とまったく同じです。
ボタンの作成を行い、ボタン名をB_CLEAR、ラベルをクリアとします。
ボタンB_CLEARを押した時に実行されるプロセスを作成します。作成したプロセスの名前をページの初期化とし、タイプにセッション・ステートのクリアを選択します。サーバー側の条件として、ボタン押下時にB_CLEARを選択します。これでクリアのボタンを押した時に、ページが初期化されます。
アップロード結果を表示するクラシック・レポートを作成します。新規にリージョンの作成を行います。
名前をアップロード結果とし、タイプはクラシック・レポートを選択します。ソースの表名にFUP_CITYLISTを選択し、プレビューと横並びになるよう、レイアウトの新規行の開始をOFFとします。
以上で完成です。ページを実行し、実装を確認します。以下の動作になります。
ユーザーが作成した表にアップロードしたファイルを保存しているので、不要になったデータを削除する処理を実装する必要があります。共有コンポーネントのアプリケーション・ロジックに含まれる自動化を、そのような用途に使うことができます。
Oracle APEX 21.1では、これらの作業のほとんどがページ作成ウィザードによって行われる予定です。ですので、いちからページを作成することはありませんが、自動的に生成されたコンポーネントをカスタマイズする際には、役に立つ知識かと思います。
作成したアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/excelfileupload.sql
サンプルのデータはこちらです。
https://github.com/ujnak/apexapps/blob/master/exports/citylist.xlsx
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完