Migaro. 技術Tips

                       

ミガロ. 製品の技術情報
IBMiの活用に役立つ情報を掲載!


Valence RPG toolkitを使用してShift_JISのCSVファイルを出力

ValenceではRPGプログラムを作成しなくても、Gridウィジェットのダウンロード設定にて、チェックボックスにチェックを設定するだけで、CSVファイルのダウンロード機能を追加することが可能です。
出力されるCSVファイルのエンコードはUTF-8/BOM無し、UTF-8/BOM付きを選択することできます。
連携する外部システム等によっては、CSVファイルをUTF-8以外の文字コードで出力したい場合もあると思います。Tipsでは、RPG Toolkitを使用して、Shift_JISのCSVファイルをダウンロードする方法をご紹介します。

ValenceのCSVダウンロード機能 Gridウィジェット

GridウィジェットでCSVファイルダウンロードの設定

Valenceではプログラムを作成しなくても、ウィジェットの編集画面でチェックを設定するだけでCSVファイルのダウンロードができます。
BOM付きのCSVファイルをダウンロードしたい場合は、「BOM付き」のチェックボックスにチェックを設定してください。

ウィジェットの機能でCSVダウンロードの実行

CSVダウンロードを実行すると、ダイアログが表示されて、「現在のページ」、「すべてのページ」を選択して出力することができます。

Valence RPG Toolkit vvOut_execSqlToCSV CSVファイル出力

ボタンからRPGプログラム呼び出し

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ファイルを出力する方法

Valence Shift_JISでCSVファイルを出力する流れ

CSVファイルをShift_JISにするには、vvOut_execSqlToCSVで出力するUTF-8のCSVファイルをIFS上に出力後、IFS上に出力したUTF-8のCSVファイルをValenceのAPIで読込み、新しいShift_JISのCSVファイルを作成して書き込む必要があります。
つまり、上記画像のような流れになります。

ソースコードの完成形は以下です。
なお、以下のソースファイルは、コピーいただき、設定箇所の部分でcsvnameフィールドをダウンロードしたいファイル名に変更頂くことでご使用頂けます。

ダウンロード(CRTSJISCSV.zip)

ソースコードの詳細な説明も、記事に記載しておりますのでご興味がございましたらご確認ください。

(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を使用して頂ければ幸いです。