2015年2月26日木曜日

CSVファイルのアップロードとインポート(2/2)

この記事の解説動画を配信中!

みなさん!XPages開発していますか!?

前回に引き続き、CSVファイルのインポート処理について書いていきます。

前回は、アップロードしたファイルの取得までをやりましたので、今回はCSVファイルの解析と文書保管までを書いていきます。

今回は、郵便局のホームページ で配布している、郵便番号のCSVファイルをインポートしてみます。

サンプルDBのファイルを、GitHubにアップロードしておきましたので、参考にしてください。
GitHub download

CSVファイルの解析

CSVファイルの解析を自前で頑張って書いてもいいんですが、CSVはカラムごとにカンマで区切られている、という他に、ダブルクォーテーションでくくられてたりいなかったり、ダブルクォーテーションの中のカンマはデリミタとして扱わなかったり、とか案外面倒です。

様々なパターンに対応するとなると、テストも含めて実装が大変ですよね。

そこで、オープンソースのJavaのライブラリを利用することにします。

今回は、SuperCSVというものを利用します。

Super CSV

ライブラリの登録

下記ページから、super-csv-distribution-2.2.1-bin.zipをダウンロードします。

download(GitHub)

ZIPファイルを展開したら、その中の"super-csv"フォルダ下にある、super-csv-2.2.1.jar を、NotesDBに取り込みます。

取り込む方法は、Designerで「ソース」→「jar」で右クリック→「新規jar...」をクリックすることで開くダイアログで、上記jarファイルを指定すると登録できます。

CSVの解析

Super CSVで解析するには、下記のサンプルを参考にしてください

var csvReader = new org.supercsv.io.CsvListReader(
 fileReader,
 org.supercsv.prefs.CsvPreference.STANDARD_PREFERENCE);
var line = csvReader.read();
 

まずは、CsvListReaderのオブジェクトをnewで作成します。引数には、前回作成したアップロードされたファイルのReaderである"fileReader"と、CSVのタイプを表す定数を指定します。

CSVのタイプを表す定数は、特殊なものでなければ上記例のもので良いと思います。

そのオブジェクトから、"read()"メソッドで1行づつデータを取り出します。取り出されたデータは、文字列の配列になっているので、CSVの1番目のカラムを取得する場合は、"line[0]"と指定します。

ドキュメントの保存

ここまでできれば、後はループして1行ずつ文書を保存していけばいいだけですね。

"read()"メソッドは、行が進んでこれ以上読み込めない場合には"null"を返しますので、その条件になるまで繰り返し処理をすればいいです。

while(!!line){
    //Documentの作成・保存
    var newDoc:NotesDocument = database.createDocument();
    newDoc.replaceItemValue("form", "PostalCode");
    newDoc.replaceItemValue("postalCode", line[2]);
    newDoc.replaceItemValue("ken", line[6]);
    newDoc.replaceItemValue("shikuchouson", line[7]);
    newDoc.replaceItemValue("chouiki", line[8]);
    newDoc.save();
    line = csvReader.read();
}

できあがり

最後に

このように、ライブラリを使用することで、意外と少ないコード量でCSVのインポートができたのではないかと思います。

もちろん、文書の保存時には値のチェックが必要な場合が多いでしょうから、そういった処理は適宜入れてくださいね。

海老原 賢次(EBIHARA Kenji)

リコーITソリューションズ株式会社(RICOH IT SOLUTIONS CO.,LTD.)

鹿児島ソリューション部(Kagoshima Department)

2015年2月22日日曜日

CSVファイルのアップロードとインポート(1/2)

この記事の解説動画を配信中!

みなさん!XPages開発していますか!?

去年の11月のXPages Dayでは、Excelへのエクスポートの話をさせていただきましたが、 インポートに関する質問をいくつか受けました。

イベントで紹介したツールでは、エクスポートしか対応していないので、 今回は、インポートについて書きたいと思います。

エクセルのインポートはちょっと難しいので、要件としてよくあるCSVファイルのインポートについて説明します。

サンプルプログラム

今回は、郵便局のホームページ で配布している、郵便番号のCSVファイルをインポートしてみます。

サンプルDBのファイルを、GitHubにアップロードしておきましたので、参考にしてください。
GitHub download

CSVファイルのインポートでの要点

CSVファイルのインポートをXPagesで行う時に問題になるのは、下記の2点ですよね。

  1. アップロードされたファイルの取得
  2. CSVファイルから値ごとの分解

これらについて説明します。

ファイルアップロードのコントロール

標準のコントロールにも、ファイルアップロード・コントロールがありますが、これはリッチテキストに添付するために利用しますね。なので、これからファイルを取得するのはちょっと至難の業が必要です。

そこで、このコントロールは使用せずにHTMLのinputタグを利用します。

<input type="file" name="postalCodeCsv" />
<xp:button value="import" id="button1">
    <xp:eventHandler event="onclick" submit="true"
        refreshMode="complete">
        <xp:this.action><![CDATA[#{javascript:
PostalCodeImport.csvImport();}]]></xp:this.action>
    </xp:eventHandler>
</xp:button>

標準のコントロールを使わなくても、ファイルはアップロードされます。

このようにアップロードされたファイルはDomino Server上の一時領域に保存されます。

"name"の属性値は任意の値ですが、SSJSで利用するので、わかり易い名前にします。

また、複数のfileタグを使用する場合は、"name"の値が重複しないようにしましょう。

ボタンは、ファイルのアップロードをインポートの処理を呼び出しています。

処理自体は、SSJSに記載します。

アップロードされたファイルの取得

ボタンを押した時に実行する関数を宣言しましょう。上のコードにあるように”PostalCodeImport.csvImport”という名前で作ります。

その中に、アップロードされたファイルの取得方法はこうなります。

PostalCodeImport = {};
PostalCodeImport.csvImport = function csvImport(){
    // step1 httpリクエストからパラメータを取得する
    var con = facesContext.getExternalContext();
    var request = con.getRequest(); 
    var map = request.getParameterMap(); 
    
    // step2 パラメータの中からアップロードファイルの情報を取得する
    //<input type="file" name="postalCodeCsv" />
    //の "name"に指定した値を指定する
    var fileData = map.get("postalCodeCsv"); 
    var file = fileData.getServerFile();

    // Step3 ファイルを取得し、JavaのFileReaderを生成する。
    var fileReader = new java.io.FileReader(file);

    //下記にCSVの解析と文書の登録が続きます

}

ステップは大きく3つに分かれています。

step1 では、HTTPリクエストの実態を取得しています。これは通常XPagesによってラップされていて、普段操作することはないオブジェクトです。

"request.getParameterMap"でブラウザからリクエストされた全パラメータ(入力データ)が取得できる、Mapオブジェクトを取得します。

step2 では、Step1で取得したパラメータの中から input type="file" タグの値、つまりアップロードファイルの情報”fileData"を取得します。

"fileData"の中には、上で説明した一時領域に保存された、ファイルのパス情報が入っています。それを"getServerFile()"メソッドで取得できます。

step3 では、そのファイルパスから、JavaのFileReaderクラスを利用して内容を取得します。

今回はここまで

次回は、CSVのの解析を説明します!