ExcelJSによるCSV出力とSJIS対応
ExcelJSを利用して出力したCSVファイルをSJIS対応させようとサイトを参考にコードを書いたらエラーを吐いて動かなかったので備忘録。
SJIS対応にはecoding.jsをnpm installしてインポートする。
CSVファイルを作成する部分は他サイトにお任せして、エラーになった部分を以下に抜粋。
Csv.ts
import Encoding from "encoding-japanese";
// 省略
const workbook = new ExcelJS.Workbook(); //ブックを作成
// 省略
const uint8Arr = new Uint8Array(
Encoding.convert((await workbook.csv.writeBuffer()), {
// await workbook.csv.writeBuffer()にエラーが表示される
from: "UTF8",
to: "SJIS",
})
);
Encoding.convert
の引数の定義を見てみると以下のように一つ目の引数はstring
型かIntArrayType
型である必要がある。
export function convert(data: IntArrayType, to: Encoding, from?: Encoding): number[];
export function convert(data: string, to: Encoding, from?: Encoding): string;
export function convert(data: IntArrayType | string, options: ConvertStringOptions): string;
export function convert(data: IntArrayType | string, options: ConvertArrayBufferOptions): ArrayBuffer;
export function convert(data: IntArrayType | string, options: ConvertArrayOptions): number[];
export function convert(data: string, options: ConvertUnknownOptions): string;
export function convert(data: IntArrayType, options: ConvertUnknownOptions): number[];
さらにIntArrayType
型は以下のように複数の配列の型で構成されている。
type IntArrayType =
| ReadonlyArray<number>
| Uint8Array
| Uint16Array
| Uint32Array
| Int8Array
| Int16Array
| Int32Array;
そしてconvert
の一つ目の引数に入れた関数writeBuffer
は以下のようにBuffer
を返してくれるようだが、Buffer
はArrayBuffer
を継承しただけの模様。
writeBuffer(options?: Partial<CsvWriteOptions>): Promise<Buffer>;
declare interface Buffer extends ArrayBuffer { }
ArrayBuffer
やUint8Array
についてはここが綺麗にまとまっていて読みやすい。
解決策
つまりエラーメッセージにもあるようにIntArrayType
型の引数が必要なのにBuffer
型の変数を入れてんじゃねぇと怒られているわけなので、以下のようにUint8Array
型にキャストしてあげるとエラーが解消され、SJISで文字化けしないCSVファイルが無事に出力される。
Csv.ts
const uint8Arr = new Uint8Array(
Encoding.convert((await workbook.csv.writeBuffer() as Uint8Array), {
// asでキャストする
from: "UTF8",
to: "SJIS",
})
);