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
を取得して使います。 - ほとんどの場合、日付表示であっても
t
がd
(日付型)になりません。 - しかし、極々まれに、
t
がd
(日付型)になる時があります。 - その場合は、下記のように、
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に出力することはほとんどなくなってしまったのでやめました。