Node.jsでExcelを読み込むライブラリ「xlsx(旧:SheetJS)」を使ってみた。
皆さん、こんにちは。技術開発グループのn-ozawanです。
先日スーパーで、キャベツ1玉500円もしてました。高くてなかなか手が出ません。キャベツは炒め物はもちろんのこと、ごま油と塩でナムル風にしてもおいしいです。
本題です。
表形式の文書を記述するのにExcelは大変便利です。仕様書や設計書などはMarkdownやWikiなどで記述しますが、WBSやテスト仕様書など、表形式で表現するものはExcelで記述しています。今回はそんなExcelをNode.jsで読み込むライブラリ「xlsx」を使ってみましたので、紹介します。
目次
xlsx(旧:SheetJS)
概要
xlsxはExcelへの読み書きが出来るNode.jsのライブラリです。Excel関連のライブラリは数多く存在しますが、その中で一番ダウンロードされており、多くの人から支持されています。以前はSheetJSという名前だったのですが、xlsxに改名されました。
xlsxは有料版と無料版があります。無料版ではExcelのスタイル設定や、画像挿入など、多くのことが出来ません。とはいえ、単にExcelの内容を読み取るだけであれば無料版でも十分です。
インストール
xlsxのインストールは以下の通りです。当然ですが、Node.jsとnpmの環境が必要です。
npm i xlsx
Excelを読み込む
では早速Excelファイルを読み込むコードを実装してみましょう。Excelは事前に以下を用意しておきます。

ソースコードは以下の通りです。TypeScriptで記述しています。
import * as xlsx from "xlsx"
import { WorkBook, WorkSheet } from "xlsx"
const workbook: WorkBook = xlsx.readFile("example.xlsx");
const sheet: WorkSheet = workbook.Sheets["Example01"];
const rows: any[] = xlsx.utils.sheet_to_json(sheet);
console.log(rows);
4行目のxlsx.readFile(...)
は、Excelファイルを読み込み、WorkBook
を返却します。
取得したWorkBook
のSheets
からWorkSheet
を取得することが出来ます。WorkSheet
はその名の通り、シート情報になります。取得する際はシート名を指定します。
取得したWorkSheet
を使って、xlsx.utils.sheet_to_json(...)
関数により行配列を取得します。取得した行配列をconsole.log(...)
で表示すると以下のようになります。
[
{
'No.': 1,
'テスト内容': '自分の足で立って歩けること',
'実施日': 45597,
'実施者': 'n-ozawan',
'実施結果': 'OK'
},
{
'No.': 2,
'テスト内容': '自分の足で立って走れること',
'実施日': 45598,
'実施者': 'n-ozawan',
'実施結果': 'NG',
'備考': '歳には勝てない。'
}
]
値を取得したい場合は以下のようにします。
console.log(rows[1]["テスト内容"]); // 自分の足で立って走れること
日付を取得する方法
先ほどのソースコードでは、実施日がExcelのシリアル値になっています。xlsxは、デフォルトではシリアル値を返却します。日付を正しく取得するには以下のようにします。
const workbook: WorkBook = xlsx.readFile("example.xlsx", { cellText: false, cellDates: true });
const sheet: WorkSheet = workbook.Sheets["Example01"];
const rows: any[] = xlsx.utils.sheet_to_json(sheet, { raw: false, dateNF: 'yyyy"-"mm"-"dd' });
console.log(rows);
xlsx.readFile(...)
に{ cellText: false, cellDates: true }
を指定することで、日付のセルを正しく読み込めるようにします。また、xlsx.utils.sheet_to_json(...)
の第2引数を{ raw: false, dateNF: 'yyyy"-"mm"-"dd' }
とすることで、日付のフォーマットを指定することが出来ます。実行すると以下のようになります。
[
{
'No.': '1',
'テスト内容': '自分の足で立って歩けること',
'実施日': '2024-11-01',
'実施者': 'n-ozawan',
'実施結果': 'OK'
},
{
'No.': '2',
'テスト内容': '自分の足で立って走れること',
'実施日': '2024-11-02',
'実施者': 'n-ozawan',
'実施結果': 'NG',
'備考': '歳には勝てない。'
}
]
変則的な表の場合
これまでのコードは、rows[1]["テスト内容"]
のように、ヘッダーを自動識別して値を設定してくれています。これは、xlsxが1行目をヘッダーとして処理してくれているためです。例えば以下の表があったとします。

この場合、以下のようになります。
[
{ '総数': '2', 'OK件数': '1' },
{
__EMPTY: 'No.',
__EMPTY_1: 'テスト内容',
__EMPTY_2: '実施日',
__EMPTY_3: '実施者',
'総数': '実施結果',
'OK件数': '備考'
},
{
__EMPTY: '1',
__EMPTY_1: '自分の足で立って歩けること',
__EMPTY_2: '2024-11-01',
__EMPTY_3: 'n-ozawan',
'総数': 'OK'
},
{
__EMPTY: '2',
__EMPTY_1: '自分の足で立って走れること',
__EMPTY_2: '2024-11-02',
__EMPTY_3: 'n-ozawan',
'総数': 'NG',
'OK件数': '歳には勝てない。'
}
]
xlsxは1行目にある「総数」と「OK件数」をヘッダー項目と認識します。しかし、A列などは空欄となっていますので、実際に取得するとkeyが__EMPTY
となってしまいます。
この問題を解決する方法として、xlsx.utils.sheet_to_json(...)
を呼ぶ際に、header
にA
を指定することで、アルファベットの列名が扱われるようになります。
const rows: any[] = xlsx.utils.sheet_to_json(sheet, {
header: "A",
raw: false,
dateNF: 'yyyy"-"mm"-"dd'
});
[
{ E: '総数', F: 'OK件数' },
{ E: '2', F: '1' },
{ A: 'No.', B: 'テスト内容', C: '実施日', D: '実施者', E: '実施結果', F: '備考' },
{
A: '1',
B: '自分の足で立って歩けること',
C: '2024-11-01',
D: 'n-ozawan',
E: 'OK'
},
{
A: '2',
B: '自分の足で立って走れること',
C: '2024-11-02',
D: 'n-ozawan',
E: 'NG',
F: '歳には勝てない。'
}
]
アルファベットじゃ使いにくい!という方は、ヘッダー項目を直接指定することも出来ます。
const rows: any[] = xlsx.utils.sheet_to_json(sheet, {
header: [ "No.", "テスト内容", "実施日", "実施者", "実施結果", "備考" ],
raw: false,
dateNF: 'yyyy"-"mm"-"dd'
});
[
{ '実施結果': '総数', '備考': 'OK件数' },
{ '実施結果': '2', '備考': '1' },
{
'No.': 'No.',
'テスト内容': 'テスト内容',
'実施日': '実施日',
'実施者': '実施者',
'実施結果': '実施結果',
'備考': '備考'
},
{
'No.': '1',
'テスト内容': '自分の足で立って歩けること',
'実施日': '2024-11-01',
'実施者': 'n-ozawan',
'実施結果': 'OK'
},
{
'No.': '2',
'テスト内容': '自分の足で立って走れること',
'実施日': '2024-11-02',
'実施者': 'n-ozawan',
'実施結果': 'NG',
'備考': '歳には勝てない。'
}
]
余計な行はslice(...)
などで適宜削除してください。
おわりに
無料版のxlsxはスタイルや画像が扱えませんので、Excelファイルの書き出しには不向きかと思います。しかし、単純にExcelの中身を見たいのであれば十分ではないでしょうか。
なお、Excel関連のライブラリで、xlsx以外にはExcelJSというライブラリもあります。xlsxに次いで2番目に人気のライブラリです。こちらはxlsxと違って高機能で色々出来そうですが、Issueの数が多いのが気になります。機会があればExcelJSも使ってみたいと思います。
ではまた。