第136回「実用WEBアプリ 文書管理システム(17) 複数選択によるディレクトリ移動(その2)」
2015.08.27
こんにちは。インストラクターの蓑島です。
前回は複数選択のためのフォーム画面を用意しましたが、フォームの送信先の処理であるディレクトリ移動処理プロシージャそのものはまだ作成していません。そのため複数選択によるディレクトリ移動処理はまだ未完成です。
今回でディレクトリ移動処理プロシージャを作成するので、複数選択によるディレクトリ移動機能は完成します。そのディレクトリ移動処理プロシージャの名前は、前回第135回のソースコード(FORMタグのACTION属性)から、「doc_dir_man_exe」でしたね。
では早速、このプロシージャのソースコードを掲載します。以下のように作成してみました。
注意)以下のソースコードはブラウザ表示のために、山括弧(「<」と「>」)を全角にしています。 コピーして実行する方は、必ず、すべての山括弧(「<」と「>」)を半角に変換してください。
SQL> SHOW USER
ユーザーは"SCOTT"です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
CREATE OR REPLACE PROCEDURE DOC_DIR_MAN_EXE (P_BUTTON IN VARCHAR2, -- クリックしたボタンの名前 P_OYA_DIR IN VARCHAR2, -- 移動先のディレクトリ番号 P_SEL_ID IN OWA.VC_ARR) -- チェックした文書やディレクトリの番号 IS USER_ERROR EXCEPTION; V_ERR_MSG VARCHAR2(800); V_ERROR_EXISTS BOOLEAN := FALSE ; BEGIN IF P_BUTTON = '移動' THEN -- 一括ディレクトリ移動処理 IF P_SEL_ID. COUNT = 1 THEN -- COUNTが1ということはDUMMYのみなので、一つも選択されていない V_ERR_MSG := '移動する文書やディレクトリをチェックしてください' ; RAISE USER_ERROR; END IF; IF P_OYA_DIR IS NULL THEN V_ERR_MSG := '移動先のディレクトリが指定されていません<BR>' ; V_ERR_MSG := V_ERR_MSG || '最上位のディレクトリとして移動したいときは個別の更新画面から親ディレクトリIDをNULLにしてください' ; RAISE USER_ERROR; END IF; ELSE V_ERR_MSG := 'P_BUTTONの値が"移動"ではありません' ; RAISE USER_ERROR; END IF; -- 以下はディレクトリ移動処理 FOR I IN 2 .. P_SEL_ID. LAST LOOP -- ループ処理 DECLARE -- ネストしたブロック V_SQLCODE NUMBER; BEGIN -- 移動先のディレクトリチェック(循環しないなど) IF DOC_FUNC_OYA_CHECK(TO_NUMBER(P_SEL_ID(I)),TO_NUMBER(P_OYA_DIR)) THEN -- OKであれば、ディレクトリを移動させる UPDATE DOCS SET OYA_DIR = TO_NUMBER(P_OYA_DIR) WHERE ID = TO_NUMBER(P_SEL_ID(I)); END IF; EXCEPTION WHEN NO_DATA_FOUND THEN V_ERROR_EXISTS := TRUE ; V_ERR_MSG := '移動先番号の番号が存在しません。 移動先番号=' || P_OYA_DIR; RAISE USER_ERROR; WHEN OTHERS THEN V_SQLCODE := SQLCODE; IF V_SQLCODE = -20000 THEN V_ERROR_EXISTS := TRUE ; HTP.P( '文書の親ディレクトリ番号をNULLにできません 番号=' ||P_SEL_ID(I) || '<BR>' ); ELSIF V_SQLCODE = -20001 THEN V_ERROR_EXISTS := TRUE ; V_ERR_MSG := '移動先番号がディレクトリでなく文書です 移動先番号=' || P_OYA_DIR; RAISE USER_ERROR; ELSIF V_SQLCODE = -20002 THEN V_ERROR_EXISTS := TRUE ; HTP.P( 'ディレクトリが循環します 番号=' ||P_SEL_ID(I)); ELSE V_ERROR_EXISTS := TRUE ; RAISE; END IF; END ; -- ネストしたブロックの終わり END LOOP; HTP.P( '選択された文書・ディレクトリを指定されたディレクトリに移動しました' ); EXCEPTION WHEN USER_ERROR THEN IF V_ERROR_EXISTS THEN ROLLBACK ; END IF; HTP.P(V_ERR_MSG); WHEN OTHERS THEN V_ERR_MSG := SQLERRM; ROLLBACK ; HTP.P(V_ERR_MSG); END DOC_DIR_MAN_EXE; / プロシージャが作成されました。 |
最初に注目していただきたいのは、ソースコード4行目の以下のパラメータ宣言です。
4行目 P_SEL_ID IN OWA.VC_ARR
P_SEL_IDはチェックボックスのパラメータ名なので、おなじ名前で複数の番号が送信されてきます。そのため、コレクション(OWA.VC_ARR型)で宣言しているものです。OWA.VC_ARR型については事前定義されているパッケージ内の型ですが、バックナンバー 113回「チェックボックスによる複数選択処理 2/2」で解説してありますので、そちらをご参照ください。
次に注目していただきたいところは、11行目のIF文です。
11行目 IF P_SEL_ID.COUNT = 1 THEN
PL/SQLではコレクションのパラメータの省略値(デフォルト値)が宣言できないので、たとえ一つも選択されていなくても、最低一つの値は必要でした。そこで、前回のフォーム画面のなかで、DUMMYの値を隠し項目(TYPE=HIDDEN)で設定していました。そのため、P_SEL_IDのCOUNTが1であるということはチェックボックスが一つもチェックされていないことを示します。ということで、11行目のIF文でその判定を行い、一つも選択されていなければエラーにしているわけです。
形式上のパラメータチェックがOKであれば、26~58行目のLOOP文により、P_SEL_IDの一つ一つの値について、ディレクトリ移動の処理を行います。この部分で見ていただきたいのは、31行目のIF文です。このIF文のファンクション「FUNC_OYA_CHECK」は、バックナンバー第127回「ディレクトリの循環を防ぐ」のときに作成したファンクションです。このファンクションでディレクトリが循環しないかどうかをさらに深くチェックします。バックンナンバー第127回を参照するとわかりますが、このファンクションはディレクトリが循環すると判断した場合は、-20002のシステムエラーを発生さたり、その他、状況により、-20000や-20001のエラーを発生させます。それらのエラーに対する例外処理が、43~52行目となっているわけです。
エラーなく処理ができれば 59行目のメッセージ
「選択された文書・ディレクトリを指定されたディレクトリに移動しました」を表示します。
以上が、今回作成したディレクトリ移動処理プロシージャ「DOC_DIR_MAN_EXE」の内容です。これを作成すれば複数選択によるディレクトリ移動機能が完成しますので、ぜひお試しください。
今後の予定ですが、複数選択の削除処理や、ディレクトリ内の表示順番(DOCS表のSEQ列)を一括で更新させるような処理を実装すればより便利になると考えています。
それではまた次回、ご期待ください。