久々の業務で役立つ(かも?)シリーズです。
「受け取ったデータが.xlsx
だった...」
「社内システムが.xlsx
しか吐き出してくれない...」
「」.xlsx
をこねくり回すと全身に拒絶反応が...
そのような絶望とも今日でおさらば!
js-xlsx
.xlsx
以外にも.xls
や.ods
など、大抵の表計算ファイルをJavaScriptから扱えます。
もちろんShift-JISにも対応しており、なんとNode/Browserどちらでも使えます。
まさに救世主!
導入
<script src="https://cdn.jsdelivr.net/npm/xlsx@latest/dist/xlsx.full.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/xlsx@latest/dist/cpexcel.js"></script>
グローバル領域にXLSX
オブジェクトが展開されます。
cpexcel.js
は追加の文字コードセットで、これが無いとShift-JISを認識できません。
const XLSX = require("xlsx");
こちらは単純明快。
文字コードセットは全て内包されているので問題ありません。
コード
function parseSheet(blob){
return new Promise((res, rej)=>{
const fr = new FileReader();
fr.addEventListener("load", () => res(fr.result));
fr.addEventListener("error", () => rej(fr.error));
fr.readAsArrayBuffer(blob);
}).then((bin)=>{
const book = XLSX.read(bin, {
type: "array",
codepage: 932
});
const sheets = book.SheetNames.map((name)=>{
const sheet = XLSX.utils.sheet_to_csv(book.Sheets[name], {
FS: "\u001F"
}).split("\n").map((row)=>{
return row.split("\u001F").map((field)=>{
if(/^$/.test(field)){
return null;
}
else if(/^true$/i.test(field)){
return true;
}
else if(/^false$/i.test(field)){
return false;
}
else if(/^((|-)((\d{1,3},){0,}\d{3}|\d+)|0(X|x)[0-9a-fA-F]+|0(B|b)[0-1]+)$/.test(field)){
const s = field.replace(/,/g, "");
const n = Number(s);
return Number.isSafeInteger(n) ? n : BigInt(s);
}
else{
return String(field);
}
});
});
return {
[name]: sheet
};
});
return Object.assign(...sheets);
});
}
各シートを一旦CSVにしてから、各フィールドの型判定を行い二次元配列化しています。
空白セルはnull
となります。
Number
は、桁区切りでカンマが入っていたり16進や2進の表記でも問題ありません。
値が巨大な場合はBigInt
となります。
それ以外の文字列はString
です。
出力されるオブジェクトは、下記のようなデータ構造です。
{
"シート名": [/*行番号*/][/*列番号*/],
...
}
使う
const file; // 任意の表計算ファイル
const parsed = parseSheet(file);
console.log(parsed["シート1"][0][0]); // シート1のA1セルに相当
行/列の番号が0
スタートなところさえ気を付ければ、特に難しい操作はありません。
これで正規表現での総当りも、条件付きSUMも、フォームへの自動入力も思いのまま!
おわりに
Excelのない朝は
今よりずっと素晴らしくて
すべての歯車が噛み合った
きっとそんな世界だ