使用 ExcelJS 创建转换流以编写 xlsx
Creating Transform stream using ExcelJS for writing xlsx
我正在使用 ExcelJS module and writing wrapper for my purposes, which implements 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);
但这不起作用,输出为空。
输出为空,因为您没有从转换流中推出任何内容。您处于对象模式,因此如果:
,它永远不会进入此模式
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);
下面的代码片段适合我
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);
}
}
我正在使用 ExcelJS module and writing wrapper for my purposes, which implements 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);
但这不起作用,输出为空。
输出为空,因为您没有从转换流中推出任何内容。您处于对象模式,因此如果:
,它永远不会进入此模式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);
下面的代码片段适合我
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);
}
}