使用ExcelJS创建转换流以编写xlsx

时间:2016-02-08 15:13:40

标签: javascript node.js xlsx

我使用ExcelJS模块并为我的目的编写包装器,它实现了Transform Stream API(是的,节点版本是0.10.40)。

ExcelJS有一个流API,根据ExcelJS模块中的示例,我们可以使用这样的一个(执行node index.js > test.xlsx):

var stream = require('stream'),
    Excel = require('exceljs');

var rs = new stream.Readable({objectMode: true});
rs.push({name: 'one'});
rs.push({name: 'two'});
rs.push({name: 'three'});
rs.push(null);

var workbook = new Excel.stream.xlsx.WorkbookWriter({stream: process.stdout}),
    worksheet = workbook.addWorksheet('sheet 1');

worksheet.columns = [{header: 'Name', key: 'name'}];

rs.on('data', function(doc) {
    worksheet.addRow({
        name: doc.name
    }).commit();
});

rs.on('end', function(doc) {
    worksheet.commit();
    workbook.commit();
});

它工作正常,但看起来不是很干净。因为我们无法使用.pipe

我需要什么:

'use strict';

var buffer = require('buffer'),
    stream = require('stream'),
    util = require('util'),
    Excel = require('exceljs');

var rs = new stream.Readable({objectMode: true});
rs.push({name: 'one'});
rs.push({name: 'two'});
rs.push({name: 'three'});
rs.push(null);

var ExcelTransform = function(options) {
    stream.Transform.call(this, options);
    this._writableState.objectMode = true;
    this._readableState.objectMode = false;

    this.workbook = new Excel.stream.xlsx.WorkbookWriter({stream: this});
    this.worksheet = this.workbook.addWorksheet('sheet 1');
    this.worksheet.columns = [{header: 'Name', key: 'name'}];
};

util.inherits(ExcelTransform, stream.Transform);

ExcelTransform.prototype._transform = function(chunk, encoding, callback) {
    if (buffer.Buffer.isBuffer(chunk)) {
        this.push(chunk);
    } else {
        this.worksheet.addRow({
            name: chunk.name
        }).commit();
    }
    callback();
};

ExcelTransform.prototype._flush = function(callback) {
    this.worksheet.commit();
    this.workbook.commit();
    callback();
};

rs.pipe(new ExcelTransform()).pipe(process.stdout);

但这不起作用,给我空的输出。

2 个答案:

答案 0 :(得分:4)

输出为空,因为您没有从变换流中推送任何内容。您处于对象模式,因此如果出现以下情况,它将永远不会出现:

if (buffer.Buffer.isBuffer(chunk)) {
  this.push(chunk);
}

这是一个可工作的可管理版本(数据最后一次流式传输):

var stream = require('stream');
var util = require('util');
var Excel = require('exceljs');
var bl = require('bl');

var ExcelTransform = function(options) {
  stream.Transform.call(this, { objectMode: true });

  this.workbook = options.workbook;
  // you can make this optional by checking for it and
  // creating an empty worksheet if none provided
  this.worksheet = options.worksheet;
}

util.inherits(ExcelTransform, stream.Transform);

ExcelTransform.prototype._transform = function(doc, encoding, callback) {
  this.worksheet.addRow({ name: doc.name });    
  callback();
};

ExcelTransform.prototype._flush = function(callback) {
  this.workbook.commit(); // commit only when you're done

  var that = this;
  // bl drains the stream and create a Buffer object you can then push
  this.workbook.stream.pipe(bl(function(err, data) {
    that.push(data);
    callback();
  }));
};

// it's better to provide the workbook as a parameter to ExcelTransform
var workbook = new Excel.stream.xlsx.WorkbookWriter();
var worksheet = workbook.addWorksheet('sheet 1');
worksheet.columns = [{
  header: 'Name',
  key: 'name'
}];

var rs = new stream.Readable({ objectMode: true });
rs.push({ name: 'one' });
rs.push({ name: 'two' });
rs.push({ name: 'three' });
rs.push(null);

rs.pipe(new ExcelTransform({
  workbook: workbook,
  worksheet: worksheet
})).pipe(process.stdout);

另一种解决方案,一直流式传输:

var stream = require('stream');
var util = require('util');
var Excel = require('exceljs');

var ExcelTransform = function(options) {
  stream.Transform.call(this, {
    writableObjectMode: true,
    readableObjectMode: false
  });

  this.workbook = options.workbook;
  var that = this;
  this.workbook.stream.on('readable', function() {
    var chunk = workbook.stream.read();
    that.push(chunk);
  });
  this.worksheet = options.worksheet;
}

util.inherits(ExcelTransform, stream.Transform);

ExcelTransform.prototype._transform = function(doc, encoding, callback) {
  this.worksheet.addRow({
    name: doc.name
  }).commit();

  callback();
};

ExcelTransform.prototype._flush = function(callback) {
  this.workbook.commit(); // final commit
};

// it's better to provide the workbook as a parameter to the ExcelTransform
var workbook = new Excel.stream.xlsx.WorkbookWriter();
var worksheet = workbook.addWorksheet('sheet 1');
worksheet.columns = [{
  header: 'Name',
  key: 'name'
}];

var rs = new stream.Readable({ objectMode: true });
rs.push({ name: 'one' });
rs.push({ name: 'two' });
rs.push({ name: 'three' });
rs.push(null);

rs.pipe(new ExcelTransform({
  workbook: workbook,
  worksheet: worksheet
})).pipe(process.stdout);

答案 1 :(得分:0)

下面的代码片段对我有用

import { Workbook } from 'exceljs';
import { createReadStream } from 'fs';

function readExcelFile(){

const stream = createReadStream("./test.xlsx");
const workbook = new Workbook();
const streamWorkBook = await workbook.xlsx.read(stream);
const sheet = streamWorkBook.getWorksheet("Sheet1");

//Get all the rows data [1st and 2nd column]
 for (let i = 1; i <= sheet.rowCount; i++) {
  console.log(sheet.getRow(i).getCell(1).value);
  console.log(sheet.getRow(i).getCell(2).value);
 }

}