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

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

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]];

シートの表示・非表示のチェックはややこしいです。

シートオブジェクトは表示・非表示の情報を持っていません。

book.Workbook.Sheets」という、ワークブックが持っているシートの、名前と表示状態を持っている配列があり、その配列を見て調べる必要があります。

配列内のオブジェクトは、シート名の「name」プロパティと、表示状態の「Hidden」プロパティを持ち、「Hidden」が「0」だと表示、それ以外だと非表示と分かります。

例えば、シート名で表示・非表示をチェックするには下記になります。

const _sheets = book.Workbook.Sheets;
const idx = _sheets.map((v:any)=>v.name).indexOf(<sheet_name>);
console.log(_sheets[idx].Hidden);
// 表示なら0 非表示なら1または2

セル

セルは、「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.utils.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.utils.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に出力することはほとんどなくなってしまったのでやめました。

関連記事

www.kwbtblog.com

関連カテゴリー記事

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com