sheet js xlsx writeFile callback

时间:2018-04-12 14:00:17

标签: javascript reactjs promise xlsx sheetjs

我正在尝试使用工作表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)
}

使用此代码只会编写一些文件,因为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)
})

但是......这不起作用,再次只写入一些文件,并且没有任何内容记录到控制台。任何人都可以给我任何想法如何使这项工作或更好的方法来实现写这样的多个文件的目标?有一个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)

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

3 个答案:

答案 0 :(得分:1)

我刚尝试过这个(第一次)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)
});

运行它会生成workbook_0.xls,workbook_1.xls和workbook_2.xls,每个都有一个名为&#34; SheetJS&#34;的工作表。它们在excel中看起来都很好,例如,workbook_0有......

enter image description here

我认为你以异步方式进行写作,并建议对以上内容进行以下调整......

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));

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

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

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

答案 1 :(得分:0)

XLSX.writeFileAsync确实具有使用以下语法的回调。

xlsx.writeFileAsync(workbookName, workbook, (err) => {
   // It's a callback
});

但这只能处理异步写入一个文件。

您的情况很典型,如果您想做一系列事情,其中​​每个项目都是异步的,那么您不应该只使用循环/映射/ forEach之类的迭代方法。

为此,我建议的一个最好的库是“异步”。 “ async.parallel”函数接收一系列异步执行的函数,并在所有函数完成后调用回调。

https://caolan.github.io/async/docs.html#parallel

答案 2 :(得分:0)

如果关心的是异步使用库来不阻塞服务器,你应该知道这个库实现似乎是同步的,你应该查看库的服务器演示自述文件,因为它有几个解决这个问题的建议:{ {3}}