【问题标题】:SheetJS (js-xlsx) in browser: read a workbook from a Blob浏览器中的 SheetJS (js-xlsx):从 Blob 中读取工作簿
【发布时间】:2019-02-12 23:04:21
【问题描述】:

我正在尝试使用 SheetJS 从Blob 构建工作簿对象,而不是像拖放或文件输入元素事件这样的客户端事件。后两者包含在 documentation's examples 中,但我缺少从 Blob 向后翻译所需的 JS-fu,通过 FileReader 事件并进入 XLSX.read() API。

在浏览器中给定一个Blob,这怎么能实现,或者可以吗?

【问题讨论】:

    标签: typescript filereader sheetjs


    【解决方案1】:

    你可以的

    var wb = XLSX.read(await blob.arrayBuffer(), { type: "array" });
    

    【讨论】:

    • 不幸的是,我现在与这段代码有点分离,但我会尽可能地验证这一点。感谢您查看这个问题!当任何超过几天的东西被看到时,总是让我感到惊讶。
    • 很简单,我遇到了同样的问题,发现你的问题没有答案。经过我自己的几次尝试(文档非常有限),我找到了一个解决方案并想分享它以防万一它可以节省半个小时。
    • 谢谢@FranckJeannin。我为此苦苦挣扎了一个小时。
    【解决方案2】:

    我正在使用此代码保存到 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()
             |                                  ^
    

    (很想知道原因,如果您知道 - 请在 cmets 中分享)

    但是求助于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)
      })
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-01-26
      • 2022-10-24
      • 2014-12-23
      • 2014-09-15
      • 1970-01-01
      • 1970-01-01
      • 2018-03-22
      • 2018-05-27
      相关资源
      最近更新 更多