sheet js xlsx writeFile 回调

Jim*_*mme 5 javascript xlsx promise reactjs sheetjs

我正在尝试从使用 sheet js 库加载的一组数据中写入多个 csv 文件。我的第一次尝试是这样的:

    for (let i = 0; i < dataSetDivided.length; i++) {
      let exportSet = dataSetDivided[i]
      console.log(exportSet)
      let ws = XLSX.utils.json_to_sheet(exportSet, {header: finalHeaders})
        let wb = XLSX.utils.book_new()
        XLSX.utils.book_append_sheet(wb, ws, "SheetJS")

      let todayDate = this.returnFormattedDate()

      let originalFileName = this.state.fileName
      let exportFileName = 'import_' + originalFileName + '_' + todayDate + '(part_' + (i + 1) + ').csv'

      XLSX.writeFile(wb, exportFileName)
}
Run Code Online (Sandbox Code Playgroud)

使用此代码,我猜只写入了一些文件,因为 for 循环在继续之前不会等待写入文件。

所以我试图将每个文件写入如下承诺中:

Promise.all(
  dataSetDivided.map((exportSet, i) => {
    return new Promise((resolve, reject) => {

      console.log(exportSet)
      let ws = XLSX.utils.json_to_sheet(exportSet, {header: finalHeaders})
      let wb = XLSX.utils.book_new()
      XLSX.utils.book_append_sheet(wb, ws, "SheetJS")

      let todayDate = this.returnFormattedDate()

      let originalFileName = this.state.fileName
      let exportFileName = 'import_' + originalFileName + '_' + todayDate + '(part_' + (i + 1) + ').csv'

      XLSX.writeFile(wb, exportFileName, (err) => {
        if (err) {
          console.log(err)
          reject(err)
        } else {
          console.log('Created ' + exportFileName)
          resolve()
        }
      })
    })
  })
)
.then(() => {
  console.log('Created multiple files successfully')
})
.catch((err) => {
  console.log('ERROR: ' + err)
})
Run Code Online (Sandbox Code Playgroud)

但是......这不起作用,同样只写入了一些文件并且没有任何内容记录到控制台。谁能给我任何想法如何使这项工作或更好的方法来实现编写这样的多个文件的目标?有一个 XLSX.writeFileAsync 方法,但我找不到任何关于它如何工作的例子,我不确定这是否是我需要的。

带着感谢,

詹姆士

更新:

我现在正在使用 setTimeout 来延迟下一次 writeFile 调用......这适用于我的测试用例,但我知道这不是一个好的解决方案,在文件成功写入时进行回调会更好:

    writeFileToDisk(dataSetDivided, i) {

    if (dataSetDivided.length > 0) {

      let exportSet = dataSetDivided[0]
      let ws = XLSX.utils.json_to_sheet(exportSet, {header: finalHeaders})
        let wb = XLSX.utils.book_new()
        XLSX.utils.book_append_sheet(wb, ws, "SheetJS")

      let todayDate = this.returnFormattedDate()

      let originalFileName = this.state.fileName
      let exportFileName = 'import_' + originalFileName + '_' + todayDate + '(part_' + i + ').csv'

      XLSX.writeFile(wb, exportFileName)

      dataSetDivided.splice(0, 1)

      i += 1

      setTimeout(() => {this.writeFileToDisk(dataSetDivided, i)}, 2500)
    }
  }

  this.writeFileToDisk(dataSetDivided, 1)
Run Code Online (Sandbox Code Playgroud)

任何如何在不模拟文件写入时间的情况下使其工作的建议将不胜感激。

dan*_*anh 8

我刚刚尝试了这个(第一次)XLSX 代码,可以确认它编写了预期的工作簿并同步运行......

'use strict'

const XLSX = require('xlsx');

let finalHeaders = ['colA', 'colB', 'colC'];
let data = [
    [ { colA: 1, colB: 2, colC: 3 }, { colA: 4, colB: 5, colC: 6 }, { colA: 7, colB: 8, colC: 9 } ],
    [ { colA:11, colB:12, colC:13 }, { colA:14, colB:15, colC:16 }, { colA:17, colB:18, colC:19 } ],
    [ { colA:21, colB:22, colC:23 }, { colA:24, colB:25, colC:26 }, { colA:27, colB:28, colC:29 } ]
];

data.forEach((array, i) => {
    let ws = XLSX.utils.json_to_sheet(array, {header: finalHeaders});
    let wb = XLSX.utils.book_new()
    XLSX.utils.book_append_sheet(wb, ws, "SheetJS")
    let exportFileName = `workbook_${i}.xls`;
    XLSX.writeFile(wb, exportFileName)
});
Run Code Online (Sandbox Code Playgroud)

运行它会产生 workbook_0.xls、workbook_1.xls 和 workbook_2.xls,每个都有一个名为“SheetJS”的工作表。它们在 excel 中看起来都不错,例如,workbook_0 有...

在此处输入图片说明

我认为您应该异步编写,并建议对上述内容进行以下改编......

function writeFileQ(workbook, filename) {
    return new Promise((resolve, reject) => {
        // the interface wasn't clearly documented, but this reasonable guess worked...
        XLSX.writeFileAsync(filename, workbook, (error, result) => {
            (error)? reject(error) : resolve(result);
        })
    })
}


let promises = data.map((array, i) => {
    let ws = XLSX.utils.json_to_sheet(array, {header: finalHeaders});
    let wb = XLSX.utils.book_new()
    XLSX.utils.book_append_sheet(wb, ws, "SheetJS")
    let exportFileName = `workbook_${i}.xls`;
    return writeFileQ(wb, exportFileName)
});

Promise.all(promises).then(result => console.log(result)).catch(error => console.log(error));
Run Code Online (Sandbox Code Playgroud)

运行这个异步代码,我发现它产生了相同的预期结果并且是异步的。

所以你的原始循环看起来是正确的,并且应该同步工作。您没有获得预期结果的事实一定是由时间以外的原因引起的(或者可能是由反应引起的某些时间问题?)。

无论如何,如果您确实想使用我强烈推荐的异步方法,我已经展示了如何做到这一点(但我担心这可能无法完全解决问题,除非您在第一次尝试时弄清楚发生了什么)。

  • 非常感谢这个丹。我试图使用承诺来实现解决方案......但得到 TypeError: _fs.writeFile is not a function。我认为您在之前的评论中是正确的,即我使用 Node 和 React 的设置可能会产生此类问题。 (2认同)