「Private Node でExcel → JSON変換ノードを作ってみる」の記事では、 Private Node 機能を使ってExcelファイルをJSONオブジェクトに変換するオリジナルのノード”Xlsx2Json”を作りました。この記事では、”Xlsx2Json”ノードをさらに使いやすく便利にしてみます。また、 Private Nodeのバージョン管理についても説明します。
目次
はじめに
enebularのPrivate Node機能では、NPM に公開することなく自作のNode-REDノードを作成して使用することができます。「Private NodeでExcel → JSON変換ノードを作ってみる」の記事では、ExcelファイルをJSONオブジェクトに変換するノード”Xlsx2Json”をPrivate Nodeとして作成しました。
この記事では、“Xlsx2Json”ノードに機能を追加して、バージョンアップする様子を紹介します。
NPM や Node-RED Libraryに公開されたノードを見ていると、人気のノードの多くが頻繁にバージョンアップを繰り返して、機能を追加したりバグを修正したりしていますね。
自作のPrivate Nodeでも、やはり機能追加やバグ修正は必要になってきます。はじめは最小限の機能でリリースして、後から機能を少しずつ追加していくような開発方法を取る場合は、頻繁なバージョンアップは必須になってきます。
enebularには、Private Nodeのバージョン管理機能があります。この機能を使うことで、古いバージョンを保存しておいたり、古いバージョンに戻したりすることができます。
Private Node “Xlsx2Json” の課題と解決策
“Xlsx2Json” ノードの使いづらさ
「Private Node でExcel → JSON変換ノードを作ってみる」の記事の “おわりに” では、以下のような課題について記載しました。
ところで、今回作った Xlsx2Json ノードには、まだまだ改良の余地があります。上のフローの図を見ても違和感があるように、どうせなら Http-Requestノードの出力をそのままXlsx2Jsonノードに入力できるようにしたいですよね。
前回の記事で作ったフローは下図です。
フローが2つに分割されています。前回の記事で作った "Xlsx2Json"
ノードは、Excelファイルをノード内で読み込んでJSONオブジェクトに変換します。そのため、"Http-request"
ノードでダウンロードしたExcelファイルは、わざわざ一度 "File"
ノードを使ってファイルに書き込まなければいけません。
解決策 “ファイルを直接受け取れるようにする”
"Http-request"
ノードは、msg
オブジェクトのpayload
としてダウンロードしたファイルを出力します。"Xlsx2Json"
ノードがこの出力を直接受け取ることができれば、一度ファイルに書き込む手間がなくなります。
そこで、 "Xlsx2Json"
ノードを以下のように修正します。
- FilenameにExcelファイルのファイル名(パス)が指定されていた場合は、Excelファイルを読み込んでJSONオブジェクトに変換する
- Filenameが空の場合は、入力される
msg
オブジェクトのmsg.payload
をExcelファイルとして読み込んで、JSONオブジェクトに変換する
ソースコードの修正
では、 msg.payload
を読み込む処理を追加します。
以下が元のファイルです。
const XLSX = require('xlsx');
module.exports = function(RED) {
function Xlsx2JsonNode(config) {
RED.nodes.createNode(this,config);
this.filename = config.filename;
const node = this;
node.on('input', function(msg, send, done) {
send = send || function() { node.send.apply(node,arguments) };
if (node.filename) {
try {
const workbook = XLSX.readFile(node.filename);
msg.payload = XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]]);
}
catch(err) {
msg.payload = {
"error": err,
"filename": node.filename,
};
}
} else {
msg.payload = { "error": "no filename" };
}
node.send(msg);
if (done) {
done();
}
});
}
RED.nodes.registerType("xlsx2json",Xlsx2JsonNode);
}
以下のソースコードが、修正後のファイルです。
const XLSX = require('xlsx');
module.exports = function(RED) {
function Xlsx2JsonNode(config) {
RED.nodes.createNode(this,config);
this.filename = config.filename;
const node = this;
node.on('input', function(msg, send, done) {
send = send || function() { node.send.apply(node,arguments) };
if (node.filename) {
try {
const workbook = XLSX.readFile(node.filename);
msg.payload = XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]]);
}
catch(err) {
msg.payload = {
"error": err,
"filename": node.filename,
};
}
} else {
try {
const workbook = XLSX.read(msg.payload, {type:"buffer"});
msg.payload = XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]]);
}
catch (err) {
msg.payload = {
"error": err,
"filename": "msg.payload",
};
}
}
node.send(msg);
if (done) {
done();
}
});
}
RED.nodes.registerType("xlsx2json",Xlsx2JsonNode);
}
node.filename
に値が設定されていなかった場合(if (node.filename)
の処理)、 msg.payload
のデータをExcelファイルのバイナリデータとみなして読み込み、JSONオブジェクトに変換します。具体的には以下の処理です。
const workbook = XLSX.read(msg.payload, {type:"buffer"});
msg.payload = XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]]);
Excelファイルの読み込みか、JSONオブジェクトへの変換で例外が発生した場合に備えて、try … catchで包んでいます。
バージョンアップしたので、package.json
のバージョンも0.1.0
→0.2.0
に変更しておきましょう。
{
"name": "enebular-privatenode-contrib-xlsx2json",
"version": "0.2.0",
"description": "",
...
enebularへの登録に備えて、enebular-privatenode-contrib-xlsx2json
フォルダで以下のコマンドを入力して、.tgzファイルを作成しておきます。
npm pack
バージョンが0.2.0
に変わっているので、出来上がるファイルもenebular-privatenode-contrib-xlsx2json-0.2.0.tgz
になります。
Private Node のバージョン管理
既存バージョンにバージョン名を付ける
enebularのPrivate Node機能には、バージョンを管理する機能があります。enebularの公式ドキュメントの「プライベートノードのバージョン管理」でも詳しく説明されていますので、読んでみてください。
せっかくなので、この機能を使って新しいバージョンの Xlsx2Json
ノードを管理してみます。enebularにSign-Inしたら、Xlsx2Json
ノードを開いてください。”Version”タブを選択します。
まず、既存のXlsx2Json
ノードにバージョン名をつけます。package.jsonのバージョンに合わせて、”0_1_0″にしてみましょう(機能の制約でピリオドはバージョン名に使えないので、アンダースコアで代替します)。”Create New Version”ボタンを押すと以下のような画面になりますので、”Title”に”0_1_0″と入力します。”Comment”欄には好きな説明を入力してください。
入力が終わったら”Create”ボタンを押せば、”0_1_0″と名前のついたバージョンが生成されます。
これで、いつでも古いバージョンに戻すことができるようになりました。
新しいノードをアップロードする
それでは、新しくなったノードをアップロードしてみましょう。
enebularの”Overview”タブを選択します。
”Update”ボタンを押すと以下のような画面になりますので、先ほど作成したenebular-privatenode-contrib-xlsx2json-0.2.0.tgz
ファイルを選択します。
ファイルをアップロードすると、”Overview”タブに表示される”Package Version”が0.2.0
に変わったのが確認できます。
新バージョンにバージョン名をつける
新しいバージョンにもバージョン名をつけておきましょう。package.jsonのバージョンに合わせて、”0_2_0″にします。
”Overview”タブから、”Version”タブに移動します。”Create New Version”ボタンを押してバージョン作成の画面を表示して、”Title”に”0_2_0″、”Comment”には好きな説明(例えば「Excelファイルをmsg.payloadとして受け取る処理を追加」)を入力し、”Create”ボタンを押してください。
これで、新しいバージョンが作成されます。
“Xlsx2Json” を使ってみる
いよいよ、バージョンアップした Xlsx2Json
ノードを使ってみます。
下のフロー図を見てください。これは「Private Node でExcel → JSON変換ノードを作ってみる」の記事で作成したフローを改造したものです。フローが一本に繋がっています。Http-request
ノードの出力が直接Xlsx2Json
ノードに入力されています。
前回の記事では、Http-request
ノードの出力は、一旦File
ノードでファイルに保存していました。その処理を削除して、Xlsx2Json
ノードの入力に接続されています。
以下のJSONファイルは、図のフローをエクスポートしたものです。インポートして利用してください。
[{"id":"5554444f.0eef5c","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"9d08eb63.43f558","type":"xlsx2json","z":"5554444f.0eef5c","name":"","filename":"","x":400,"y":200,"wires":[["a7441d02.0d52"]]},{"id":"6a087103.8934c","type":"debug","z":"5554444f.0eef5c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":790,"y":200,"wires":[]},{"id":"a7441d02.0d52","type":"split","z":"5554444f.0eef5c","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":590,"y":200,"wires":[["6a087103.8934c"]]},{"id":"b95f6ef4.47ec1","type":"http request","z":"5554444f.0eef5c","name":"","method":"GET","ret":"bin","paytoqs":false,"url":"https://www.mext.go.jp/content/20201221-mxt_syogai03-000010378_1.xlsx","tls":"","persist":false,"proxy":"","authType":"","x":410,"y":140,"wires":[["9d08eb63.43f558"]]},{"id":"81f73788.75bb38","type":"inject","z":"5554444f.0eef5c","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":220,"y":140,"wires":[["b95f6ef4.47ec1"]]}]
簡単なフローですが、少しだけ説明します。
Http-request
ノードの設定を確認してみます。Return
の設定が”a binary buffer”になっていますね。ここはデフォルト値ではありませんので、注意してください。
Xlsx2Json
ノードの設定を確認してみます。空っぽです。”Filename”に値が入力されていると、ファイルシステム上のファイルを探してしまいますので、ここには何も設定しないでください(”Name”は設定しても構いません)。
Split
ノードはデフォルト設定のまま接続していますので、特別な設定は不要です。
フローの左端にある Injection
ノードをクリックするとフローが動作します。Debugウィンドウに、JSONオブジェクトに変換された、Excelファイルが出力されれば成功です。
おわりに
この記事では、Private Node を改良してバージョンアップする様子を記事にしてみました。 Xlsx2Json
ノードには、まだまだ改良の余地があると思います。興味のある方は、さらに改良したバージョンの作成にチャレンジしてみてください。
また、バージョン管理機能は、ファイルやフローの機能でも使うことができます。ぜひ、活用してみてください。