HTTPサーバーとWeb開発

74. RPG# 入門bR

次にデータ・ベースのレコードを取り出してどのように表示するかという例とともに
イベントの処理について紹介しよう。
これから作成する CGI は初期画面で指定したレコードを取り出して表示するという
簡単なものである。
RPG# では「単票表示」と呼ばれているパターンである。

【 初期画面 : DSPHEAD.HTM 】

【 明細画面 : DSPDTA01.HTM】

最初に初期画面 DSPHEAD.HTM の HTML ソースは次のようになる。

-------------------------------------------------------------------------------------
<html>
<head>
<meta http-equiv="Content-Language" content="ja">
<meta http-equiv="Content-Type" content="text/html; charset=shift_jis">
<title>商品マスターファイル</title>
<STYLE TYPE="TEXT/CSS">
BODY{margin:15px;font-size:14px;background:#fff;}
FORM{margin:0;}
H1{font-size:26px; margin:10px 0px; color:#666;}
HR{height:1px;filter:Alpha(opacity=100,finishOpacity=0,style=1,startX=90,finishX=100) 
    Alpha(opacity=0,finishOpacity=100,style=1,startX=0,finishX=10);}
TABLE{margin:10px 3px;font-size:14px;}
INPUT{height:20px;border:1px solid #666;padding:2px;}
.HAND{cursor:hand;filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,
    StartColorStr=#EEEEEE, EndColorStr=#AAAAAA);}
.CLSBTN{width:100%;text-align:center;}
/* エラー反転スタイル */
.NORMAL{border:solid 1px #666666}
.ERR_RED{border:solid 1px #666666;background-color:#ffccee}
</STYLE>
</head>
<body onLoad="chkServerError();">
<center>
<h1>商品マスターファイル</h1>
</center>
<hr>
<form name="frmDsphead" method="POST" action="/cgi-bin/WEB004.PGM">
<!-- イベントドリブン用 Hidden -->
<input type="hidden" name=ID>
<input type="hidden" name=EVENT>
<input type="hidden" name=RECORD value="DSPHEAD">
<input type="hidden" name=RPG_JOBNO value="######">
<p>項目を入力して「GO」ボタンを押してください。</p>
<KEYFROM>
<p>商品コード&nbsp; <input type="text" name=SHCODE id="SHCODE"
    value="" onChange="chkInputValidity(this);" onKeyDown="FIELD_EXIT(this);"
    maxlength="10" size="12" alt="10A">&nbsp;&nbsp;
<KEYEND> 
<input type="button" class="HAND" id="GO" value="&nbsp;GO&nbsp;" onClick="setClickEvent();">
</p> 
</form>   

<hr>
<div class="CLSBTN">
<input type="button" class="HAND" value="閉じる" onClick="clsApplication();">
</div>
<!-- イベントドリブン用 Hidden -->
<input type="hidden" name="ERRMSG" value="$(ERRMSG)">
<input type="hidden" name="REVIMG" value="##########">
<input type="hidden" name="CURSOR" value="##########">
</body>   
<!-- JavaScript VBScript Lib-->
<script type="text/javascript" src="/AS400-NET.USR/JS/RPG_SP.JS"></script>
<script type="text/javascript" src="/AS400-NET.USR/JS/RPG_SP_CLCHK.JS"></script>
<script type="text/javascript" src="/AS400-NET.USR/JS/RPG_SP_GUI_EV.JS"></script>
<script type="text/vbscript" src="/AS400-NET.USR/JS/CHKFORMAT.VBS"></script>
<script type="text/vbscript" src="/AS400-NET.USR/JS/CHKLENGTH.VBS"></script>
</html>
-------------------------------------------------------------------------------------

明細画面 DSPDTA01.HTM の HTML ソースは次のようになる。

-------------------------------------------------------------------------------------
<html>
<head>
<meta http-equiv="Content-Language" content="ja">
<meta http-equiv="Content-Type" content="text/html; charset=shift_jis">
<title>商品マスターファイル</title>
<STYLE TYPE="TEXT/CSS">
BODY{margin:15px;font-size:14px;background:#fff;}
FORM{margin:0;}
H1{font-size:26px;margin:10px 0px;color:#666;}
HR{height:1px;filter: Alpha(opacity=100,finishOpacity=0,style=1,startX=90,finishX=100)
    Alpha(opacity=0,finishOpacity=100,style=1,startX=0,finishX=10);}
TABLE{margin:10px 3px;font-size:14px;}
A{text-decoration:underline;}
.MAIN{background:#fff;border:0px;border-width:2px 2px 1px 2px;border-style:solid;
    border-color:#666;float:left;clear:right;}
.MAIN TD{padding:5px 10px;}
.LST_HED{border-right:1px solid #666;border-bottom:1px solid #666;
    filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr=#FDFDFD,
    EndColorStr=#DFDFDF);}
.LST_BDY{border-bottom:1px solid #aaa;}
INPUT{height:20px;border:1px solid #666;padding:2px;}
.HAND{cursor:hand;filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,
    StartColorStr=#EEEEEE, EndColorStr=#AAAAAA);margin:10px auto -5px 10px;}
.BTNSIZ1{width:80px;}
/* エラー反転スタイル */
.NORMAL{border:solid 1px #666666}
.ERR_RED{border:solid 1px #666666;background-color:#ffccee}
</STYLE>
</head>
<body onLoad="chkServerError();">
<center><h1>商品マスターファイル</h1></center>
<hr>
<form name="frmDspdta01" method="POST" action="/cgi-bin/WEB004.PGM">
<!-- イベントドリブン用 Hidden -->
<input type="hidden" name=ID>
<input type="hidden" name=EVENT>
<input type="hidden" name=RECORD value="DSPDTA01">
<input type="hidden" name=RPG_JOBNO value="######">
<table><tr>
<td>
<table border="0" cellpadding="1" cellspacing="0" class="MAIN">
<FLDFROM>
<tr class="LST_REP">
<td nowrap class="LST_HED">商品コード</td>
<td class="LST_BDY">&nbsp;</td>
<td nowrap class="LST_BDY"><input type="text" name=SHCODE id="SHCODE"
    value="##########" onChange="chkInputValidity(this);" onKeyDown="FIELD_EXIT(this);"
    maxlength="10" size="12" alt="10A"></td>
</tr>
<tr class="LST_REP">
<td nowrap class="LST_HED">商品名</td>
<td class="LST_BDY">&nbsp;</td>
<td nowrap class="LST_BDY"><input type="text" name=SHNAME id="SHNAME"
    value="########################" onChange="chkInputValidity(this);" onKeyDown="FIELD_EXIT(this);"
    maxlength="24" size="26" alt="24O"></td>
</tr>
<tr class="LST_REP">
<td nowrap class="LST_HED">単価</td>
<td class="LST_BDY">&nbsp;</td>
<td nowrap class="LST_BDY"><input type="text" name=SHTANK id="SHTANK"
    value="##########" onChange="chkInputValidity(this);" onKeyDown="FIELD_EXIT(this);"
    maxlength="10" size="12" alt="7S0" EDTCDE(J) DDS="CHECK(RB)"></td>
</tr>
<tr class="LST_REP">
<td nowrap class="LST_HED">品種コード</td>
<td class="LST_BDY">&nbsp;</td>
<td nowrap class="LST_BDY"><input type="text" name=SHSCOD id="SHSCOD"
    value="####" onChange="chkInputValidity(this);" onKeyDown="FIELD_EXIT(this);"
    maxlength="4" size="6" alt="4A"></td>
</tr><FLDEND>

</table>
</td>
<td valign="top">
<input type="button" id="UPDATE" value="&nbsp;更&nbsp;&nbsp;&nbsp;新&nbsp;"
    class="HAND" onClick="setClickEvent();"><br />
<input type="button" id="DELETE" value="&nbsp;削&nbsp;&nbsp;&nbsp;除&nbsp;"
    class="HAND" onClick="setClickEventDeleteForDspdta()" /><br clear="all" />
</td>
</tr></table>
</form>
<input type="button" class="HAND BTNSIZ1" id="PRV" value="≪&nbsp;前へ" onClick="bakLockCondition();">
<br>
<!-- イベントドリブン用 Hidden -->
<input type="hidden" name="ERRMSG" value="$(ERRMSG)">
<input type="hidden" name="REVIMG" value="##########">
<input type="hidden" name="CURSOR" value="##########">
</body>
<!-- JavaScript VBScript Lib-->
<script type="text/javascript" src="/AS400-NET.USR/JS/RPG_SP.JS"></script>
<script type="text/javascript" src="/AS400-NET.USR/JS/RPG_SP_CLCHK.JS"></script>
<script type="text/javascript" src="/AS400-NET.USR/JS/RPG_SP_GUI_EV.JS"></script>
<script type="text/vbscript" src="/AS400-NET.USR/JS/CHKFORMAT.VBS"></script>
<script type="text/vbscript" src="/AS400-NET.USR/JS/CHKLENGTH.VBS"></script>
</html>
-------------------------------------------------------------------------------------

処理するRPG# ソースは次のとおりである。

-------------------------------------------------------------------------------------------
0001.00 H NOMAIN BNDDIR('ASNET.COM/MAIN') DATEDIT(*YMD/) DFTNAME(WEB003)         
0002.00 F********** RPG# 入門bR *******************************************    
0003.00 FWEB003H   CF   E             SPECIAL PGMNAME('ASNET.COM/HTMLDVR')       
0004.00 F                                     PLIST(HPARM)                       
0005.00 F                                     INFDS(INFDSF)                      
0006.00 FSHOHIN    IF   E           K DISK    EXTFILE(SHOHIN_LIB)                
0007.00 F**********************************************************************  
0008.00  /COPY ASNET.USR/QRPGLESRC,PROTOTYP5#                                    
0009.00 D DSPHEAD_GO      PR                                                     
0010.00 D HTM_FILE        S             10A   INZ('WEB003H   ')                  
0011.00 D HTM_LIB         S             10A   INZ('*LIBL     ')                  
0012.00 D SHOHIN_LIB      S             21    INZ('QTRFIL/SHOHIN')               
0013.00 D HTM_DIR         S            128A   INZ('/AS400-NET.USR/PROJECT/-      
0014.00 D                                     WEB003')                           
0015.00                                                                          
0016.00 D*( ファイル情報データ構造 )                                             
0017.00 D INFDSF          DS                                                     
0018.00 D                              512A                                      
0019.00 D  HTM_RECORD       *RECORD                                              
0020.00 D*( プログラム状況データ構造 )                                           
0021.00 D INFDSP         SDS                                                     
0022.00 D                              512A                                      
0023.00 D* CPFID                         7A   OVERLAY(INFDSP:40)                 
0024.00  /COPY ASNET.USR/QRPGLESRC,HPARM                                      
0025.00 *********************************************************             
0026.00 P EVENT           B                   EXPORT                          
0027.00 *********************************************************             
0028.00 D                 PI                                                  
0029.00  /FREE                                                                
0030.00     ON_CLICK('DSPHEAD': 'GO': %PADDR(DSPHEAD_GO));                    
0031.00  /END-FREE                                                            
0032.00 P                 E                                                   
0033.00 *********************************************************             
0034.00 P BEGIN           B                   EXPORT                          
0035.00 *********************************************************             
0036.00  * 最初の画面を出力します。                                           
0037.00 D                 PI                                                  
0038.00 C                   WRITE     DSPHEAD                                 
0039.00 P                 E                                                   
0040.00                                                                       
0041.00 *********************************************************             
0042.00 P DSPHEAD_GO      B                   EXPORT                          
0043.00 *********************************************************             
0044.00  * GO ボタンが押されたときの記述を行います。                          
0045.00 D                 PI                                                  
0046.00 C                   READ      DSPHEAD                              99 
0047.00 C                   SETOFF                                       90   
0048.00 C     SHCODE        CHAIN     SHOHIN                             90  
0049.00 C                   WRITE     DSPDTA01                               
0050.00 P                 E                                                  
0051.00                                                                      
0052.00 *********************************************************            
0053.00 P END             B                   EXPORT                         
0054.00 *********************************************************            
0055.00 D                 PI                                                 
0056.00 C                   CLOSE     WEB003H                                
0057.00 C                   CLOSE     SHOHIN                                 
0058.00 P                 E                                                  
-------------------------------------------------------------------------------------------

最初に BEGIN プロシージャーによって初期画面 DSPHEAD.HTM

      WRITE     DSPHEAD

によって出力される。
次にエンド・ユーザーが初期画面で商品コードを入力て GO ボタンを押すと
RPG# のメイン・モジュールは イベント・フロシージャー

0025.00 *********************************************************
0026.00 P EVENT           B                   EXPORT
0027.00 *********************************************************
0028.00 D                 PI
0029.00  /FREE
0030.00     ON_CLICK('DSPHEAD': 'GO': %PADDR(DSPHEAD_GO));
0031.00  /END-FREE
0032.00 P

を参照して DSPHEAD.HTM 上の GO という id を持つボタンが
クリックされたら(ON_CLICK) プロシージャー DSPHEAD_GO を呼び出すことを
知って

0041.00 *********************************************************
0042.00 P DSPHEAD_GO      B                   EXPORT
0043.00 *********************************************************
0044.00  * GO ボタンが押されたときの記述を行います。
0045.00 D                 PI
0046.00 C                   READ      DSPHEAD                              99
0047.00 C                   SETOFF                                       90
0048.00 C     SHCODE        CHAIN     SHOHIN                             90
0049.00 C                   WRITE     DSPDTA01
0050.00 P                 E

を実行する。DSPHEAD_GO 内では

   READ DSPHEAD

によって DSPHEAD.HTM からの入力値を READ DSPHEAD によって
すべて取り込むことができる。
これまで WRITE 命令で HTML を出力できると説明してきたのと同じように
READ 命令だけで HTML からの変数値をすべて、まとめて読み込むことができるのである。
これによって商品コード : SHCODE が入力されたので

   SHCODE CHAIN  SHOHIN

によって商品レコードの内容を取得して
WRITE DSPDTA01 によって明細レコード : DSPDTA01 の HTML: DSPDTA01.HTM を
ブラウザに戻す。

【 まとめ 】

データ・ベースのレコードの内容を取り出すのも、とても簡単である。
特に HTML からの変数値の取得は、これまでの Web化ツールでは、ひとつひとつの
フィールドに対して入力のための演算を記述しなければならなかったのであるが
RPG# であれば READ 命令一発ですべての変数値を取得することができる。
特に編集を伴う数字フィールドの入力では効果的である。
またイベントの記述はイベント・プロシージャー内に列挙するだけという
シンプルなものであった。

  /FREE
    ON_CLICK('DSPHEAD': 'GO': %PADDR(DSPHEAD_GO));
  /END-FREE

このイベント記述があえて言えばユーザーにとってのメイン・ルーチンかも知れない。
HTML という GUI 画面で様々なイベントが発生する都度、CGI を呼び出していたのでは
ひとつの HTML 画面に対して多くの CGI が必要となってしまうことを想像してみて欲しい。
特に最近では Ajax の使用は必須となりつつある。
ひとつの画面の GUI コントロールに対して、各々の CGI を作成していたのでは
開発だけでなく管理も複雑になってしまう。
しかしイベント駆動型の言語であれば、そうした記述をひとつのソースにまとめることが
できるのである。
Basic言語や C, C++ が VisualBASIC, VC++ のようなイベント駆動型に進化してきたのと
同じように RPG もまた RPG# としてイベント駆動型に進化しなければならないのは
自然であり必然的な流れである。