新しいことにはウェルカム

技術 | 電子工作 | ガジェット | ゲーム のメモ書き

JavaScriptでExcelファイルを、SheetJS(xlsx)を使って読み込む方法メモ

JavaScript(TypeScript)でExcelファイルを読み込むのに、SheetJS(xlsx)を使っています。

使い方はちょっとクセがあって、すぐに忘れてしまうので自分用使い方メモです。

マニュアル

インストール

npm install xlsx

ファイル読み込み

import * as xlsx from 'xlsx';
const book = xlsx.readFile('test.xlsx');

シート

シートはシート名を指定して取得します。

const sheet = book.Sheets['<sheet_name>'];

シート一覧はbook.SheetNamesなので、シートをインデックスで指定するには下記のようにします。

const sheet = book.Sheets[book.SheetNames[0]];

セル

セルは、「A1表記」でアドレスを指定して、取得します。

const cel = sheet['B2'];

取得したセルの説明の前に、まずセルのアドレス指定方法に関する説明を。

アドレス指定の「A1表記」と「インデックス表記」

SheetJS(xlsx)への指定は「A1表記」を使います。

ただ、プログラム的には、行・列をインデックス(数値)で表した方が扱いやすいので、「A1表記」と「インデックス表記」を相互変換するユーティリティー関数が用意されています。

プログラムでは「インデックス表記」でアドレスを指示し、それを「A1表記」に変換して、SheetJSの引数に渡すといった使い方をします。

インデックス表記

セル

行(row)をr、列(column)をcで表します。

インデックスは「0」始まりです。

// 'A1'
{ c:0, r:0 }

領域

左上のセル(start)をs、右下のセル(end)をeで表します。

// 'A1:B2'
{
    s:{c:0, r:0},
    e:{c:1, r:1}
}

A1インデックス変換

セル

const id = xlsx.util.decode_cell('A1');
// {c:0, r:0}

const a1 = xlsx.util.encode_cell({c:0, r:0});
// 'A1'

領域

const id = xlsx.util.decode_range('A1:B2');
// { s:{c:0, r:0}, e:{c:1, r:1} }

const a1 = xlsx.util.encode_range({ s:{c:0 ,r:0}, e:{c:1, r:1} });
// 'A1:B2'

シートのデータ範囲

シートのデータが入っている領域はsheet['!ref']で取得できます。

領域は「A1表記」で表されるので、「インデックス表記」に変換して、forループを回す時の範囲として使います。

const range_a1 = sheet['!ref'];
const range = xlsx.util.decode_range(range_a1);

値取得

値はセル単位で、A1表記でアドレス指定して取得します。

値はJSONで返されます。

const cel = sheet['A1'];
console.log(cel);
// {v:123, w:123, t:'n'}

JSONフォーマット

key名 内容
v 生データ
w 表示データ
t データ型

値の取得方法

  • wはExcelで開いた時に表示される値で、Stringで返されます。
  • vはセルに入っている実データです。例えば、wが「1900/1/1」の時はvは「1」になります。
  • 一般的にデータを取得する際は、wを使うと間違いが少ないです。
  • ただし、wが無い場合もあるので、その場合はvの値を使います。
  • wはStringなので、取得したい値の型が明確に分かっている場合は、変換して使用します。
  • t(データ型)は信用せず、無視した方がいいです。

空白セル

空白セルは、取得したセルが「undefined」になります。

日付値取得

  • 基本wを取得して使います。
  • ほとんどの場合、日付表示であってもtd(日付型)になりません。
  • しかし、極々まれに、td(日付型)になる時があります。
  • その場合は、下記のように、vの値からDateを作成します。
import * as moment from 'moment';

const cell = sheet['A1'];
let dt = null;
if( cell.t==='d'){
    dt = moment(cell.v);
} else {
    dt = moment(cell.w);
}
console.log(dt.format('YYYY-MM-DD'));

JSON・CSV取得

シートのデータをJSON・CSVで取得するユーティリティー関数があります。

シートのデータが、ヘッダー付きの表データなら、これを使ってJSONで取得するのが一番楽です。

CSVはそのままファイル出力すると、CSVファイルとして保存できます。

const json = xlsx.util.sheet_to_json(sheet);
const csv = xlsx.util.sheet_to_json(sheet);
fs.writeFileSync('test.csv', csv);

サンプル(シートの全データを出力する)

import * as xlsx from 'xlsx';

const book = xlsx.readFile('test.xlsx');
const sheet = book.Sheets[book.SheetNames[0]];
const range = xlsx.util.decode_range(sheet['!ref']);

for(let row=range.s.r; row<=range.e.r; row++){
    for(let col=range.s.c; col<=range.e.c; col++){
        const address = xlsx.util.encode_cell({r:row, c:col});
        const cell = sheet[address];
        if(cell){
            console.log( cell.w ? cell.w : cell.v );
        } else {
            console.log( '' );
        }
    }
}

感想など

Excel出力もまとめようかと思ったのですが、BIツールを使うようになってからは、Excelを読み込むことはあっても、Excelに出力することはほとんどなくなってしまったのでやめました。