ValenceではRPGプログラムを作成しなくても、Gridウィジェットのダウンロード設定にて、チェックボックスにチェックを設定するだけで、CSVファイルのダウンロード機能を追加することが可能です。
出力されるCSVファイルのエンコードはUTF-8/BOM無し、UTF-8/BOM付きを選択することできます。
連携する外部システム等によっては、CSVファイルをUTF-8以外の文字コードで出力したい場合もあると思います。Tipsでは、RPG Toolkitを使用して、Shift_JISのCSVファイルをダウンロードする方法をご紹介します。
ValenceのCSVダウンロード機能 Gridウィジェット
Valenceではプログラムを作成しなくても、ウィジェットの編集画面でチェックを設定するだけでCSVファイルのダウンロードができます。
BOM付きのCSVファイルをダウンロードしたい場合は、「BOM付き」のチェックボックスにチェックを設定してください。
CSVダウンロードを実行すると、ダイアログが表示されて、「現在のページ」、「すべてのページ」を選択して出力することができます。
Valence RPG Toolkit vvOut_execSqlToCSV CSVファイル出力
Valenceでは、グリッドの設定でCSVファイルを出力する方法以外に、RPGプログラムでCSVファイルを出力する方法もあります。
ValenceのApp Builderでは、ボタンをクリックした際にRPGプログラムを呼び出すことができます。
呼び出すRPGのテンプレートはVALENCEライブラリのQRPGLESRCのメンバー「EXNABBTN」です。
呼び出したRPGプログラムでRPG Toolkitの「vvOut_execSqlToCSV」を実行すると、CSVファイルが出力できます。
例えば、ボタンを配置したウィジェットに関連付けられたデータソースの情報から、CSVファイルを出力する場合には、以下のようなプログラムになります。
(CRTUTF8CSV.sqlrpgle)
/copy qcpylesrc,vvHspec
/include qcpylesrc,vvNabBtn
** --------------------------------------------------------------
** program start
** --------------------------------------------------------------
/free
Initialize();
Process();
CleanUp();
*inlr=*on;
/end-free
** --------------------------------------------------------------
p Process b
d pi
d csvname s 20a
d stmt s 65535a varying
/free
// ** 設定箇所 *******************
// CSVファイル名設定
csvname = 'jutyu.csv';
// ******************************
// SQLの取得
stmt = GetSqlStatement();
// IFSに出力する設定
vvOut.download = '1';
// CSVファイル名
vvOut.file = csvname;
// vvOut_execSqlToCSVでSQLからCSV出力
vvOut_execSqlToCSV(vvOut:stmt);
/end-free
p e
/include qcpylesrc,vvNabBtn
ソースコードの黒文字の箇所はテンプレートの部分で、実際に記述するのは赤文字の箇所になります。
「GetSQLStatement」は呼び出し元のデータソースに設定されているSQLを取得します。
vvOutはデータセットでValenceの出力系の制御をします。
downloadに’1’を設定すると、ブラウザに直接レスポンスを返却します。
また、downloadに’F’が設定されている場合には、IFS上にファイルを出力できます。
vvOut.fileはファイル名の指定です。
「vvOut_execSqlToCSV」にvvOutデータセットと、SQLを設定すると、CSVファイルのダウンロードが可能です。
上記のように、数行のプログラムでCSVファイルを簡単に出力できます。
ただし、デフォルトのCSVファイル出力のエンコードはUTF-8となるため、Shift_JISでファイルを取得したい場合には、工夫が必要となります。
Shift_JISでCSVファイルを出力する方法
CSVファイルをShift_JISにするには、vvOut_execSqlToCSVで出力するUTF-8のCSVファイルをIFS上に出力後、IFS上に出力したUTF-8のCSVファイルをValenceのAPIで読込み、新しいShift_JISのCSVファイルを作成して書き込む必要があります。
つまり、上記画像のような流れになります。
ソースコードの完成形は以下です。
なお、以下のソースファイルは、コピーいただき、設定箇所の部分でcsvnameフィールドをダウンロードしたいファイル名に変更頂くことでご使用頂けます。
ソースコードの詳細な説明も、記事に記載しておりますのでご興味がございましたらご確認ください。
(CRTSJISCSV.sqlrpgle)
/copy qcpylesrc,vvHspec
/include qcpylesrc,vvNabBtn
** --------------------------------------------------------------
** program start
** --------------------------------------------------------------
/free
Initialize();
Process();
CleanUp();
*inlr=*on;
/end-free
** --------------------------------------------------------------
p Process b
d pi
d csvname s 20a varying
d stmt s 65535a varying
d path s 1000a varying
d fileHandleR s 10i 0
d fileHandleW s 10i 0
d writeWorked s n
d record s 65535a varying
d status s 10i 0
d writefile s 500a varying
d sid s 64a varying
d csvbasename s 20a varying
d csvrplname s 20a varying
/free
// *** 設定箇所 ****************************
// CSVファイル名設定
csvname = 'jutyu.csv';
// ****************************************
// 一時的に出力するUTF-8 CSVファイルの名前
csvbasename = 'utf8_temp_';
// 一時的に出力するShift_JIS CSVファイルの名前
csvrplname = 'sjis_temp_';
// *** 2. IFS上にUTF-8のCSV出力 ************
// 2-1.sessionIDの取得
sid = vvIn_char('sid');
// CSV出力
// SQLの取得
stmt = GetSqlStatement();
// 2-2.tempパスの取得
path = vvUtility_getValenceSetting('TEMP_PATH');
// 2-3.IFSに出力する設定
vvOut.download = 'F';
// CSV出力パス
vvOut.file = %trim(path) + csvbasename +
sid + '.csv';
// vvOut_execSqlToCSVでSQLからCSV出力
vvOut_execSqlToCSV(vvOut:stmt);
// *** 3. IFS上にShift_JISのCSV出力と転送 **
// Shift_JISのCSV出力ファイルパス
writefile = %trim(path) + csvrplname +
sid + '.csv';
// Shift_JISのCSV出力ファイル削除
if vvIFS_pathExists(writefile);
vvIFS_deleteFile(writefile);
endif;
// 3-1.Shift_JISファイルの作成
fileHandleW = vvIfs_openFile(writefile
:OCRTNOEXIST+OWRITEONLY
:S_IRWXU
:943);
// 3-2.UTF-8のCSVオープン
fileHandleR = vvIfs_openFile(vvOut.file
:OREADONLY
:S_IRWXU
:UTF8);
// ループ処理CSV出力ファイルを読込み 出力ファイルに書き込む
dou status=-1;
// 3-3.UTF-8のCSV読込み
record = vvIfs_readFile(fileHandleR:status:READLINE);
// statusが 0 の場合は最終行
if status = 0 ;
leave;
endif;
// 3-4.UTF-8からShift_JISに変換
record = vvUtility_convertCCSID(record:UTF8:943);
// 3-5.CSVファイル書き込み
writeWorked = vvIfs_writeFile(fileHandleW
:%addr(record:*DATA)
:%len(record));
enddo;
// 3-6.ファイルハンドルのクローズ
vvIfs_closeFile(fileHandleR);
vvIfs_closeFile(fileHandleW);
// *** 4. UTF-8のCSV削除 *****************
// CSVファイルの削除 vvOut_execSqlToCSV 出力分
vvIFS_deleteFile(vvOut.file);
// *** 5. Shift_JISのCSVをブラウザに返却 **
vvOut.download = '1';
vvOut.file = csvname;
vvOut_file(writefile:vvOut);
// *** 6. Shift_JISのCSV削除 *************
vvIFS_deleteFile(writefile);
/end-free
p e
/include qcpylesrc,vvNabBtn
1. RPGの呼び出し
RPGプログラムの呼び出し方法は、ウィジェットに設定したボタンにRPGプログラムを指定する方法で、通常のRPGプログラム呼び出しと変わりません。
例では、RPGプログラム名をCRTSJISCSVとしています。
2. IFS上にUTF-8のCSV出力
IFSにファイルを出力する場合には、同時実行時にファイルが上書きされる可能性があるため、一時的に作成するCSVファイル名にsessionID等の一意となる名前を設定する必要があります。
プログラムでは、sessionIDを取得して、ファイル名に一意の名前を設定して出力を行います。
2-1. sessionIDの取得
sid = vvIn_char('sid');
Valenceでは64桁のsessionIDはsidという引数でバックエンド側に送信されています。
RPG側で「vvIn_char」APIを使用してsessionIDを取得することができます。
2-2. tempパスの取得
path = vvUtility_getValenceSetting('TEMP_PATH');
tempパスはValenceのAPI「vvUtility_getValenceSetting」を使用して、VVSETTINGSファイルの設定内容から取得できます。
引数に「TEMP_PATH」を指定することで、Valenceインスタンスのtempディレクトリ(作業ディレクトリ)を取得できます。
2-3. IFSにCSVファイルを出力
vvOut.download = 'F';
// CSV出力パス
vvOut.file = %trim(path) + csvbasename +
sid + '.csv';
// vvOut_execSqlToCSVでSQLからCSV出力
vvOut_execSqlToCSV(vvOut:stmt);
vvOutデータセットのdownloadに「F」を設定、vvOutデータセットのfileにIFSのファイルパスを設定します。
vvOut_execSqlToCSV でvvOutデータセットとSQLを渡せば、vvOut.fileに設定されたIFSパスにUTF-8のCSVファイルを出力します。
3. IFS上でShift_JISのCSV出力と転送
次に、Shift_JISのCSVファイルをIFS上に作成して、一時的に作成したUTF-8のCSVからデータを読込み、Shift_JISのCSVファイルに書き込みます。
3-1. Shift_JISファイルの作成
// Shift_JISのCSV出力ファイルパス
writefile = %trim(path) + csvrplname +
sid + '.csv';
if vvIFS_pathExists(writefile);
vvIFS_deleteFile(writefile);
endif;
新規に作成するShift_JISのCSVファイルパスを変数に格納後、すでにIFS上に同じ名前のファイルが存在しないかを確認します。
ValenceのAPI「vvIFS_pathExists」を使用すると、ファイルやパスが存在しないかをチェックすることができます。
もし、ファイルが存在している場合には「vvIFS_deleteFile」APIで、IFS上のファイルを削除します。
ValenceのAPI「vvIfs_openFile」は、IFS上のファイルをオープンしたり、オープンと同時にファイルを作成することができます。
fileHandleW = vvIfs_openFile(writefile
:OCRTNOEXIST+OWRITEONLY
:S_IRWXU
:943);
ファイルを書き込むために、第一引数にIFSファイルのパスを指定します。
第二引数のファイルオープンフラグには「OCRTNOEXIST」(ファイルが存在しない場合にはファイルを作成)、「OWRITEONLY」( 書き込み専用)を指定しています。
第三引数には、ファイルの権限を指定します。
「S_IRWXU」は所有者のみが使用できる権限です。
■Valence_RPG_Toolkit.vvIfs_openFile
Valence_RPG_Toolkit.vvIFS_openFile – Valence 6 API Docs (cnxcorp.com)
3-2. UTF-8のCSVオープン
vvOut_execSqlToCSVでIFSに出力した、UTF-8のCSVファイルを読みます。
fileHandleR = vvIfs_openFile(vvOut.file
:OREADONLY
:S_IRWXU
:UTF8);
ファイルの読み込みは、書込みと同じvvIfs_openFileを使用します。
第一引数はIFSファイルのパス、第二引数のファイルオープンフラグには、読み込み専用のOREADONYを指定しています。第三引数には、ファイルの権限で「S_IRWXU」を指定しています。
3-3. UTF-8のCSV読込み
record = vvIfs_readFile(fileHandleR:status:READLINE);
// statusが 0 の場合は最終行
if status = 0 ;
leave;
endif;
レコードの読込みには、「vvIfs_readFile」を使用します。
IFS上ファイルのデータをEOFまで取得したり、1行毎に読み込むことができます。
第二引数の「status」はレコードの読込み状態が格納されます。
IFS上のファイルデータをEOFまで読み込んだ場合には、0が格納されます。
0の場合はleaveにてループを抜けるように記述しています。
■Valence_RPG_Toolkit.vvIfs_readFile
http://service.cnxcorp.com/valence-6/index.html#!/api/Valence_RPG_Toolkit.vvIFS
3-4. UTF-8からShift_JISに変換
// UTF-8から Shift_JIS に変換
record = vvUtility_convertCCSID(record:UTF8:943);
読込んだデータをUTF-8 から Shift_JIS へ変換します。
変換には「vvUtility_convertCCSID」が使用できます。
第一引数に変換対象のデータ、第二引数に変換元の文字コード、第三引数には変換後の文字コードを指定します。
Valenceでは、UTF8が定数として定義されており、1208が格納されています。
第三引数は943(Shift_JIS)に変換しています。
3-5. CSVファイル書き込み
writeWorked = vvIfs_writeFile(fileHandleW
:%addr(record:*DATA)
:%len(record));
CSVファイルへの書き込みは、「vvIfs_writeFile」APIを使用します。
第一引数にファイルハンドル、第二引数に、データのポインターアドレス、第三引数にデータ長を渡します。
第二引数の%addr関数に設定されている第二引数は、*DATAを指定しています。
これは、可変長の変数からデータ部のアドレスを取得する場合に指定します。
■%ADDR(変数のアドレスの検索)
https://www.ibm.com/docs/ja/i/7.4?topic=functions-addr-get-address-variable
3-6. ファイルハンドルのクローズ
vvIfs_closeFile(fileHandleR);
vvIfs_closeFile(fileHandleW);
「vvIfs_closeFile」APIを使用してファイルハンドルを閉じます。
■Valence_RPG_Toolkit.vvIfs_closeFile
http://service.cnxcorp.com/valence-6/index.html#!/api/Valence_RPG_Toolkit.vvIFS
4. UTF-8のCSV削除
UTF-8のCSVファイルを削除します。
ValenceのAPI「vvIFS_deleteFile」を使用して IFS上のファイルを削除することができます。
// CSVファイルの削除 vvOut_execSqlToCSV 出力分
vvIFS_deleteFile(vvOut.file);
■Valence_RPG_Toolkit.vvIfs_deleteFile
http://service.cnxcorp.com/valence-6/index.html#!/api/Valence_RPG_Toolkit.vvIFS
5. Shift_JISのCSVをブラウザに返却
vvOut.download = '1';
vvOut.file = csvrplname + 'sjis.csv';
vvOut_file(writefile:vvOut);
vvOutデータセットのdownloadに1を設定、vvOutデータセットのfileにファイル名を指定後
「vvOut_file」を使用してブラウザにIFS上のファイルを返却します。
第一引数にIFS上のファイル、第二引数にvvOutデータセットを設定してください。
6. Shift_JISのCSV削除
vvIFS_deleteFile(writefile);
最後に、vvIFS_deleteFileを使用して、Shift_JISのCSVファイルも削除します。
以上で、Shift_JISのCSVファイルを出力することができます。
おわりに
ValenceのRPG Toolkit を使用するとIFS上のファイルが自由に操作できることがお分かりいただけたと思います。
App BuilderからRPGプログラムを呼び出す際には、RPG Toolkitの便利なAPIを使用して頂ければ幸いです。