encoding.js を利用して Shift_JIS の CSV ファイルを SheetJS で取り込んでみた

2022.08.26

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは!DA(データアナリティクス)事業本部 サービスソリューション部の大高です。

SheetJSはExcelデータを扱えるJavaScriptライブラリなのですが、実はCSVファイルも読み込むことが出来ます。

一方で、単純に扱えるCSVファイルは「文字コードをUTF8として保存したCSVファイル」となり、それ以外の文字コードでは文字化けを起こします。また、SheetJS自体にCSVファイルの文字コードを指定して読み込む機能は無いようでした。

そこで今回、encoding.jsを利用することで Shift_JIS の CSV ファイルを文字コード変換し、 SheetJS で取り込む方法について書いていきたいと思います。

前提条件

今回試した環境における各パッケージのバージョンは、以下になります。

  • encoding-japanese (encoding.js)
    • ^2.0.0
  • xlsx (SheetJS)
    • 0.18.10
  • react-dropzone
    • ^14.2.1
  • next (NextJS)
    • ^11.1.4
  • react
    • 17.0.2

SheetJSの基本的な使い方については、ここでは触れません。また、ファイルを画面上から取り込むためにreact-dropzoneを利用していますが、こちらも詳細は割愛します。

はじめに

まず最初に「何故 Shift_JIS のCSVを扱おうとしているのか?」について、少し触れておきます。

CSVファイルのデータ元としては「自分で1からエディタで作成する」、「どこかからダウンロードする」というものがありますが、よくあるケースとして 「Excelファイルの内容をCSVとして保存する」 というケースがあるかと思います。

一方で、この場合には往々にして文字コードがShift_JISになっており、問題になることが多いです。

最近のバージョンのExcelだったり、明示的に文字コードを指定して保存することでUTF-8で保存することもできるのですが、良くあるケースとして、この「Shift_JIS のCSVファイルを、SheetJSでどうやって取り込むか」について取り上げています。

encoding.js について

こちらは文字コードの判定や変換をしてくれる素敵な JavaScript ライブラリになります。

利用データとしてUint8ArrayなどのTypedArrayNode.jsBufferがサポートされています。

更に README のAPI仕様にも記載されていますが、文字コード変換用のconvert関数は、「文字コードを自動判定して、目的の文字コードに変換してくれる」という素敵な仕様になっています。(もちろん明示的に指定もできます)

このライブラリがとても強力なので、今回はこのライブラリを利用させていただいています。

encoding.js を SheetJS と組み合わせて利用してみる

では、本題の SheetJS との組み合わせです。具体的なコードとしては以下のようにしました。

import Encoding from 'encoding-japanese'
import * as XLSX from 'xlsx/xlsx.mjs'
import { WorkBook, WorkSheet } from 'xlsx/xlsx.mjs'

(...snip...)

export default function FooBar(props) {

(...snip...)

  const onDrop = useCallback(
    (acceptedFiles) => {
      acceptedFiles.map(async (file: File) => {

        let fileData: ArrayBuffer = await file.arrayBuffer()
        fileData = Encoding.convert(new Uint8Array(fileData), {
          to: 'UNICODE',
          type: 'arraybuffer',
        })

        const workbook: WorkBook = XLSX.read(fileData, { type: 'buffer' })

(...snip...)

まず、react-dropzoneを利用してファイルをFileとして扱っています。これを以下のように変換しています。

File (Shift_JIS)
↓
ArrayBuffer (Shift_JIS)
↓
Uint8Array (Shift_JIS)
↓
Encoding.convert で変換
↓
ArrayBuffer (UNICODE)

そして、最後に SheetJS でファイルを読み込みますが、その際には{ type: 'buffer' }オプションを指定しています。

これにより、ArrayBufferのままExcelのワークブックとして取り込むことができます。

なお、最初はEncoding.convertで変換する際にarrayとして返却し、SheetJS では{ type: 'array' }として読み込もうとしていたのですが、こちらはうまくいきませんでした。

SheetJS のXLSX.readのオプションについては、以下が参考になりました。

実際にこのコードを利用して、文字コード変換をする前、文字コード変換をした後の画面サンプルがこちらです。

・Shift_JISのまま

・変換後

バッチリ変換できました!

まとめ

以上、encoding.js を利用して Shift_JIS の CSV ファイルを SheetJS で取り込んでみました。

Shift_JIS の CSV ファイルを取り扱うケースは割と多いかなと思われるので、文字コード変換ができるencoding.jsのことを覚えておきたいと思います。

どなたかのお役に立てば幸いです。それでは!