我正在尝试使用 SheetJS 从 构建 Workbook 对象Blob
,而不是像拖放或文件输入元素事件这样的客户端事件。后两者在文档的示例Blob
中有所介绍,但我缺乏从我拥有的,通过FileReader
事件和XLSX.read()
API向后转换所需的 JS-fu 。
在浏览器中给定 a Blob
,如何实现,或者可以吗?
我正在尝试使用 SheetJS 从 构建 Workbook 对象Blob
,而不是像拖放或文件输入元素事件这样的客户端事件。后两者在文档的示例Blob
中有所介绍,但我缺乏从我拥有的,通过FileReader
事件和XLSX.read()
API向后转换所需的 JS-fu 。
在浏览器中给定 a Blob
,如何实现,或者可以吗?
你可以做
var wb = XLSX.read(await blob.arrayBuffer(), { type: "array" });
我正在使用以下代码保存到 XLSX:
import XLSX from 'xlsx'
import { saveAs } from 'file-saver'
export function saveAsXlsx({ fileName = 'export', worksheets }: Params) {
const blob = getXlsxBlob(worksheets)
saveAs(blob, `${fileName}.xlsx`)
}
export function getXlsxBlob(worksheets: Worksheet[]) {
const workbook = XLSX.utils.book_new()
worksheets.forEach(({name, header, body}) => {
const worksheet = XLSX.utils.json_to_sheet(body, {header})
XLSX.utils.book_append_sheet(workbook, worksheet, name)
})
const workbookOutput = XLSX.write(workbook, {
type: 'binary',
bookType: 'xlsx'
})
return new Blob([stringToArrayBuffer(workbookOutput)], {
type: 'application/octet-stream'
})
}
interface Params {
fileName?: string
worksheets: Worksheet[]
}
export interface Worksheet<T extends string = string> {
name: string
header: T[]
body: Record<T, string | number>[]
}
function stringToArrayBuffer(string: string) {
const buffer = new ArrayBuffer(string.length)
const view = new Uint8Array(buffer)
for (let i = 0; i < string.length; i++) view[i] = string.charCodeAt(i) & 0xff
return buffer
}
然后我正在尝试测试该代码。我决定不弄乱真实文件,所以我将大部分复杂性提取到getXlsxBlob
并专注于测试该部分。
这是我尝试测试的代码:
import xlsx from 'xlsx'
import { getXlsxBlob, Worksheet } from './saveAsXlsx'
const people: Worksheet = {
name: 'People',
header: ['Name', 'Age'],
body: [
{
Name: 'John Doe',
Age: 37
},
{ Name: 'Jane Doe', Age: 35 }
]
}
const cars: Worksheet = {
name: 'Cars',
header: ['Brand', 'Model', 'Color'],
body: [
{ Brand: 'Toyota', Model: 'RAV4', Color: 'red' },
{ Brand: 'SAAB', Model: '9-3', Color: 'blue' }
]
}
test('getXlsxBlob', async () => {
const blob = getXlsxBlob([people, cars])
const arrayBuffer = await blob.arrayBuffer()
const workbook = xlsx.read(arrayBuffer, {type: 'array'})
expect(workbook.SheetNames).toEqual(['People', 'Cars'])
expect(xlsx.utils.sheet_to_json(workbook.Sheets['People']))
.toEqual(people.body)
expect(xlsx.utils.sheet_to_json(workbook.Sheets['Cars'])).toEqual(cars.body)
})
它爆炸了
TypeError: blob.arrayBuffer is not a function
26 | test('getXlsxBlob', async () => {
27 | const blob = getXlsxBlob([people, cars])
> 28 | const arrayBuffer = await blob.arrayBuffer()
| ^
(很想知道为什么,如果你知道 - 请在评论中分享)
但诉诸FileReader
帮助:
test('getXlsxBlob', async () => {
// ...
const arrayBuffer = await readAsArrayBuffer(blob)
// instead of
// const arrayBuffer = await blob.arrayBuffer()
// ...
})
function readAsArrayBuffer(blob: Blob) {
return new Promise((resolve) => {
const reader = new FileReader()
reader.onload = (event) => {
resolve(event.target?.result)
}
reader.readAsArrayBuffer(blob)
})
}