JavaScript
Node.js
XLSX

node.jsで画像入りExcelファイルを出力

はじめに

このドキュメントは、node.jsから画像入りExcelファイルの出力をする方法を共有するためのものです。

こちらの記事に触発され、自分でもxlsxファイルの出力を試してみました。
node.jsでxlsxファイルを読み込む:xlsxモジュールの使用

対象とするユーザー

  • node.js, npm, javascriptの基礎的な知識がある。
  • node.jsからExcelファイルを出力してみたい。

前提とする環境

このドキュメントは以下の環境を前提としています。

macOS 10.14.1
node.js 8.11.4

package.json
  "dependencies": {
    "excel4node": "^1.7.0",
  }

環境のバージョンが異なる場合、このドキュメントの内容をそのまま利用できない場合があります。

成果物

CLIで動作するnodeモジュールを作ってみました。
images-to-xlsx

npm install https://github.com/MasatoMakino/images-to-xlsx.git

でインストールして

npx images-to-xlsx -i ./images

と実行すると./imagesフォルダ以下の画像をリストアップしたimages.xlsxというファイルを出力します。

npx https://github.com/MasatoMakino/images-to-xlsx.git -i ./images

でインストールせずに一度だけ実行することもできます。

リスト画像
出力結果はこのようになります。

excel4node

このモジュールでは、画像入りxlsxファイルの出力のためにexcel4nodeを利用しています。

このライブラリは、xlsxのファイル生成に特化したライブラリで、xlsxの読み込み機能はありません。xlsxを読み込み、処理を行なった後に出力するならnode-libxlなどをお勧めします。

使い方

excel4nodeのREADMEから基本的な操作方法を以下に抜粋します。

var xl = require('excel4node');

// ワークブックを作成
var wb = new xl.Workbook();

// ワークシートを作成
var ws = wb.addWorksheet('Sheet 1');

// セルに記入
ws.cell(2, 1)
  .string('string');

// ワークブックを保存
wb.write('Excel.xlsx');

セルに対して画像を追加する場合は以下のようになります。

ws.addImage({
  path: './screenshot1.jpg',
  type: 'picture',
  position: {
    type: 'oneCellAnchor',
    from: {
      col: 1,
      colOff: '0.5in',
      row: 1,
      rowOff: 0,
    },
  },
});

画像のパスとセル番号、左上からのオフセット量を指定すると画像が挿入されます。

利点

Excelをマクロで操作するのと比較して、node.jsからxlsxファイルを操作するのには以下のような利点があります。

Excel不要

実行環境にExcelがインストールされている必要はありません。実行環境を選ばず、またライセンス料も不要です。

nodeモジュールの資産が利用できる

ファイルを収集するglobや画像ファイルのリサイズを行うsharpなど、多くのnode.jsのライブラリ資産を利用できます。
普段からnode.jsに親しまれている方なら、高度な機能もライブラリの助けを借りて短期間で実装することができます。

詰まったところ

ライブラリの選択が難しい

npmでxlsxを検索すると大量のライブラリが見つかります。この中から、目的に合い、かつメンテナンスやドキュメントが充実しているライブラリを選定するのは骨の折れる作業です。

セル指定は0からではなく1

セル番号の指定方法は、Excelに合わせて1からになります。0は指定できません。
配列を処理している時に、ついうっかり配列インデックスをセル番号にそのまま代入してしまい、しばらく詰まりました。

(node:77237) UnhandledPromiseRejectionWarning: Error: TypeError: Cannot read property 'toUpperCase' of undefined

セル番号にゼロを指定すると上記のエラーが出て処理が停止します。
解決方法はexcel4nodeのissueに記載されていました。
https://github.com/natergj/excel4node/issues/139

非同期処理が全て終了してからファイル出力

今回はセルに画像を挿入していますが、node.jsでの画像操作は非同期処理が多用されます。
非同期処理をPromiseやawait/asyncで処理しないとワークブックの保存処理が先に実行されてしまいます。
そうすると画像の挿入されていない空のxlsxファイルが出力されます。

以上、ありがとうございました。