[React / JavaScript] ExcelJSで実装したCSV出力機能でSJIS変換対応をしてみた
こんにちは、CX事業本部 IoT事業部の若槻です。
前回のエントリでは、ExcelJSを使用してアプリにExcel/CSVのダウンロード機能を実装しましたが、その際のCSVの文字コードはUTF8でした。
今回は、ReactアプリでExcelJSで実装したCSV出力機能で文字コードをSJIS(Shift-JIS)に変換する対応をしてみました。
デモ
下記リンクを別タブで開きます。上記サンドボックスのプレビューが開けます。
SJIS形式でダウンロード
[CSV形式(SJIS)]をクリックして、ファイルをダウンロードします。
ダウンロードしたファイルをVSCodeで開くと、日本語文字(ダブルバイト文字)が文字化けします。
[UTF-8]をクリックして、[Reopen with Encoding]をクリックします。
[Japanese (Shift JIS)]をクリックしてファイルをSJISで開き直します。
すると文字化けが解消して日本語文字が正常に表示されました。
ファイルをExcelで開いても文字化けなく日本語文字を表示させられました。
UTF8形式でダウンロード
UTF8の方も試してみます。
[CSV形式(UTF8)]をクリックして、ファイルをダウンロードします。
ダウンロードしたファイルをVSCodeで開くと、UTF8で文字化けなく開けました。
ファイルをExcelで開くとこちらはちゃんと(?)文字化けしました。
コード概要
import React from "react"; import "./styles.css"; import ExcelJS from "exceljs"; import encoding from "encoding-japanese"; export const App: React.FC = () => { const handlerClickDownloadButton = async ( e: React.MouseEvent<HTMLButtonElement, MouseEvent>, format: "xlsx" | "csv", charcode?: "UTF8" | "SJIS" ) => { e.preventDefault(); const workbook = new ExcelJS.Workbook(); workbook.addWorksheet("sheet1"); const worksheet = workbook.getWorksheet("sheet1"); worksheet.columns = [ { header: "ID", key: "id" }, { header: "作成日時", key: "createdAt" }, { header: "名前", key: "name" } ]; worksheet.addRows([ { id: "f001", createdAt: 1629902208, name: "りんご" }, { id: "f002", createdAt: 1629902245, name: "ぶどう" }, { id: "f003", createdAt: 1629902265, name: "ばなな" } ]); const uint8Array = format === "xlsx" ? await workbook.xlsx.writeBuffer() : charcode === "UTF8" ? await workbook.csv.writeBuffer() : new Uint8Array( encoding.convert(await workbook.csv.writeBuffer(), { from: "UTF8", to: "SJIS" }) ); const blob = new Blob([uint8Array], { type: "application/octet-binary" }); const url = window.URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = "sampleData." + format; a.click(); a.remove(); }; return ( <> <header> <h1>データ出力</h1> </header> <> <button onClick={(e) => handlerClickDownloadButton(e, "xlsx")}> Excel形式 </button> <button onClick={(e) => handlerClickDownloadButton(e, "csv", "UTF8")}> CSV形式(UTF8) </button> <button onClick={(e) => handlerClickDownloadButton(e, "csv", "SJIS")}> CSV形式(SJIS) </button> </> </> ); };
- 文字コードの変換にはencoding-japaneseを使用しています。
await workbook.csv.writeBuffer()
により作成したuint8ArrayはUTF8となります。「CSV形式(SJIS)」ボタンが押された時はそれをencoding.convert()
によりUTF8からSJISに変換して新しいuint8Arrayを作成しています。
参考
以上