intramartスクリプト開発でApachePOIを使ってみた

#はじめに
intramartスクリプト開発に際して、初めてApachePOIを使用してEXCELへのデータ出力を行うシーンがあったので今後の備忘録として記します。

#参考サイト
* [Apache POIでExcelワークブックに画像を挿入してみる。(株式会社システムトラスト様)](https://it-engineer-info.com/intra-mart/apache-poi-image-insert)


#基本となるフォーマット

```.js

function createFile(){

  // ワークブック作成
  var workbook = new Packages.org.apache.poi_v3.8.xssf.usermodel.XSSFWorkbook();
  // シート作成
  var sheet = workbook.createSheet();
  // シート名
  workbook.setSeetname(0, "テストシート");

  // 行と列を生成
  var row;
  var cell;
  row = sheet.createRow(0);
  cell = row.createCell(0);

  // 値の設定
  cell.setCellValue("設定したい値");

  // ストレージの指定
  var EXCEL_PATH = "export/excel/session";
  var excelDirStorage = new SessionScopeStorage(EXCEL_PATH);
  if(!excelDirStorage.exists()){
      excelDirStorage.makeDirectories();
  }

  // ファイル保存
  var strFileName = Client.identifer() + ".xlsx"
  var tempFile = new Packages.jp.co.intram_mart.foundation.service.cilent.file.SessionScopeStorage(EXCEL_PATH + "/" + strFileName);
  var baos = new java.io.ByteArrayOutputStream();
  workbook.write(baos);
  tempFile.save(baos.toByteArray());

  fileNm = strFileName;
  filepath = tempFile.getPath();
}

function downloadFile(request){
  var taregetFile = new SessionScopeStorage(request.file_path);
  Module.download.send(taregetFile, request.file_nm)
}
```

* ストレージの指定として[SessionScopeStorageオブジェクト](https://www.intra-mart.jp/apidoc/iap/apilist-ssjs/doc/platform/SessionScopeStorage/index.html)を用いています。セッションが消えるときにファイルもシステムによって消されるストレージです。
永続化を図るのであれば、[PublicStorageオブジェクト](https://www.intra-mart.jp/apidoc/iap/apilist-ssjs/doc/platform/PublicStorage/index.html)を指定し、ファイル名も変更したほうがよいでしょう。

* 上記例では、createFile関数ではModule.dowonload.sendは行わず、ファイル名、ファイルパスを一旦画面に返し、別途downloadFile関数を画面側からコールするつくりを想定しています。
Module.dowonloadはコールされたら以降の処理が中断してしまうため、アクションを分けるようにしています。⇒[前記事](https://qiita.com/ten_characters/items/48f7b89cf6774affef8c)


#テンプレートファイルを使用する場合
なんらかのテンプレートファイルが存在して、そのファイルに対して読み書きを行う例です。
下記はB列1行目に値を設定しようとしています。

```.js
var inputStream = new java.io.FileInputStream("※ファイルパスを指定");
var workbook = new Packages.org.apache.poi_v3.8.ss.usermodel.WorkbookFactory.create(inputStream);
var sheet1 = workbook.getSheet("Sheet1");
var row = org.apache.poi_v3_8.ss.util.CellUtil.getRow(0, sheet1);
var cell = org.apache.poi_v3_8.ss.util.CellUtil.getCell(row,1)
cell.setCellValue("値の設定") 
```

* シートオブジェクトのgetRow()やgetCell()ではデータがない場合にNULLで帰ってくるため、CellUtilクラスを使用しています。


#オブジェクトの描画
もはやintramartうんぬんは関係なくApachePOIの機能ですが…。
下記は、E列3行目からF列5行目にかけてのテキストボックスを設定しています。
　※XSSFClientAnchorクラスの引数の指定のうち前半４つがオフセットの指定、
　　後半４つが位置の指定(開始列、開始行、終了列、終了行…いずれも右下を指定)です。

```.js
var drawing = sheet.createDrawingPatriarch();
var clientAnchor = new Packages.org.apache.poi_v3.8.xssf.usermodel.XSSFClientAnchor(0,0,0,0,4,2,6,5);
var textbox = drawing.createTextbox(clientAnchor);
textbox.setText(new Packages.org.apache.poi_v3.8.xssf.usermodel.XSSFRichTextString("値の指定"));


```

#その他
* 上記までではJavaのクラスを使用する際に、ひとつひとつPackages句を用いてフルパッケージ付で呼び出していますが、可読性や処理速度を考慮すると、事前に変数に代入したり、グローバル関数の初期化時に変数に代入しておくほうがよいそうです。
[Packagesの利用に関しての注意事項(公式)](https://www.intra-mart.jp/document/library/iap/public/development/script_programming_guide/texts/use_java_class/custom_class.html#id6)


以上です。