js で excel / csv うにょるやつ。そのまんま。
$ npm i exceljs
URL.createObjectURL
BOMやBlobを理解してJavaScriptでCSVを出力する
[React / JavaScript] ExcelJSで実装したCSV出力機能でSJIS変換対応をしてみた
- client 側で api から返ったデータを blob にして csv とか download させるやつ
- server 側で複雑な stream donwload 組むまでもないデータ量なら使えるかな
- 将来 File System Access API が普及すれば blob 生成を複数 api kick の promise で構成して client side 主体で streaming download とかできるようになる気がする
以下は react query 使って react component 側から操作する例。
import ExcelJS from 'exceljs'
import { useMutation } from '@tanstack/react-query'
/**
* client side で取得済み data を utf8 csv へ変換して download させる
*
* NOTE client 主体なので、大きいファイルには利用しないこと
* 将来 File System Access API が普及すれば client 主体で streaming
* download できるようになるかも
*/
export const useDownloadCsv = ({ filename, header, rows }: {
filename: string
header: Partial<ExcelJS.Column>[]
rows: { [key: NonNullable<ExcelJS.Column['key']>]: any }[]
}) => {
return useMutation(
['download-csv'],
async () => {
const worksheet = new ExcelJS.Workbook().addWorksheet('sheet1')
worksheet.columns = header
worksheet.addRows(rows)
/**
* @link https://dev.classmethod.jp/articles/react-i-tried-sjis-conversion-support-with-csv-output-function-implemented-in-exceljs/
*/
const dynamicATag = document.createElement('a')
const url = window.URL.createObjectURL(new Blob(
[
new Uint8Array([0xEF, 0xBB, 0xBF]), // UTF8 BOM for Windows
new Uint8Array(await worksheet.workbook.csv.writeBuffer())
],
{ type: 'application/octet-binary' },
))
dynamicATag.href = url
dynamicATag.download = filename
dynamicATag.click()
dynamicATag.remove()
window.URL.revokeObjectURL(url) // destruct
return url
},
)
}
const users = [
{ id: 1, name: 'john' },
{ id: 2, name: 'jane' },
]
const { mutate, isLoading } = useDownloadCsv({
filename: `example.csv`,
header: [
{ header: 'ID', key: 'id' },
{ header: 'ユーザ名', key: 'name' },
],
rows: users,
})
return <>
<Button onClick={async () => await mutate()}>
Download Users
</Button>
<LoadingOverlay isOpen={isLoading} />
</>