如何使用 Nodejs 创建 Excel 文件?

我是 Nodejs 程序员。现在我有一个数据表,我要保存在 Excel 文件格式。我该怎么做呢?

我找到了几个 Node 库。但是它们中的大多数是 Excel 解析器而不是 Excel 编写器。我正在使用 Linux 服务器。因此需要一些可以在 Linux 上运行的东西。请让我知道,如果有任何有用的图书馆,你知道。

或者有没有一种方法可以将 CSV 文件转换为 xls 文件(通过编程) ?

242217 次浏览

I just figured a simple way out . This works -

Just create a file with Tabs as delimiters ( similar to CSV but replace comma with Tab ). Save it with extension .XLS . The file can be opened in Excel .

Some code to help --

var fs = require('fs');
var writeStream = fs.createWriteStream("file.xls");


var header="Sl No"+"\t"+" Age"+"\t"+"Name"+"\n";
var row1 = "0"+"\t"+" 21"+"\t"+"Rob"+"\n";
var row2 = "1"+"\t"+" 22"+"\t"+"bob"+"\n";


writeStream.write(header);
writeStream.write(row1);
writeStream.write(row2);


writeStream.close();

This creates the file in XLS file format . It doesnt work if you try XLSX instead of XLS .

XLSx in the new Office is just a zipped collection of XML and other files. So you could generate that and zip it accordingly.

Bonus: you can create a very nice template with styles and so on:

  1. Create a template in 'your favorite spreadsheet program'
  2. Save it as ODS or XLSx
  3. Unzip the contents
  4. Use it as base and fill content.xml (or xl/worksheets/sheet1.xml) with your data
  5. Zip it all before serving

However I found ODS (openoffice) much more approachable (excel can still open it), here is what I found in content.xml

<table:table-row table:style-name="ro1">
<table:table-cell office:value-type="string" table:style-name="ce1">
<text:p>here be a1</text:p>
</table:table-cell>
<table:table-cell office:value-type="string" table:style-name="ce1">
<text:p>here is b1</text:p>
</table:table-cell>
<table:table-cell table:number-columns-repeated="16382"/>
</table:table-row>

Use msexcel-builder. Install it with:

npm install msexcel-builder

Then:

// Create a new workbook file in current working-path
var workbook = excelbuilder.createWorkbook('./', 'sample.xlsx')


// Create a new worksheet with 10 columns and 12 rows
var sheet1 = workbook.createSheet('sheet1', 10, 12);


// Fill some data
sheet1.set(1, 1, 'I am title');
for (var i = 2; i < 5; i++)
sheet1.set(i, 1, 'test'+i);


// Save it
workbook.save(function(ok){
if (!ok)
workbook.cancel();
else
console.log('congratulations, your workbook created');
});

Or - build on @Jamaica Geek's answer, using Express - to avoid saving and reading a file:

  res.attachment('file.xls');


var header="Sl No"+"\t"+" Age"+"\t"+"Name"+"\n";
var row1 = [0,21,'BOB'].join('\t')
var row2 = [0,22,'bob'].join('\t');


var c = header + row1 + row2;
return res.send(c);

excel4node is a maintained, native Excel file creator built from the official specification. It's similar to, but more maintained than msexcel-builder mentioned in the other answer.

// Require library
var excel = require('excel4node');


// Create a new instance of a Workbook class
var workbook = new excel.Workbook();


// Add Worksheets to the workbook
var worksheet = workbook.addWorksheet('Sheet 1');
var worksheet2 = workbook.addWorksheet('Sheet 2');


// Create a reusable style
var style = workbook.createStyle({
font: {
color: '#FF0800',
size: 12
},
numberFormat: '$#,##0.00; ($#,##0.00); -'
});


// Set value of cell A1 to 100 as a number type styled with paramaters of style
worksheet.cell(1,1).number(100).style(style);


// Set value of cell B1 to 300 as a number type styled with paramaters of style
worksheet.cell(1,2).number(200).style(style);


// Set value of cell C1 to a formula styled with paramaters of style
worksheet.cell(1,3).formula('A1 + B1').style(style);


// Set value of cell A2 to 'string' styled with paramaters of style
worksheet.cell(2,1).string('string').style(style);


// Set value of cell A3 to true as a boolean type styled with paramaters of style but with an adjustment to the font size.
worksheet.cell(3,1).bool(true).style(style).style({font: {size: 14}});


workbook.write('Excel.xlsx');

Using fs package we can create excel/CSV file from JSON data.

Step 1: Store JSON data in a variable (here it is in jsn variable).

Step 2: Create empty string variable(here it is data).

Step 3: Append every property of jsn to string variable data, while appending put '\t' in-between 2 cells and '\n' after completing the row.

Code:

var fs = require('fs');


var jsn = [{
"name": "Nilesh",
"school": "RDTC",
"marks": "77"
},{
"name": "Sagar",
"school": "RC",
"marks": "99.99"
},{
"name": "Prashant",
"school": "Solapur",
"marks": "100"
}];


var data='';
for (var i = 0; i < jsn.length; i++) {
data=data+jsn[i].name+'\t'+jsn[i].school+'\t'+jsn[i].marks+'\n';
}
fs.appendFile('Filename.xls', data, (err) => {
if (err) throw err;
console.log('File created');
});

Output

You should check ExcelJS

Works with CSV and XLSX formats.

Great for reading/writing XLSX streams. I've used it to stream an XLSX download to an Express response object, basically like this:

app.get('/some/route', function(req, res) {
res.writeHead(200, {
'Content-Disposition': 'attachment; filename="file.xlsx"',
'Transfer-Encoding': 'chunked',
'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
})
var workbook = new Excel.stream.xlsx.WorkbookWriter({ stream: res })
var worksheet = workbook.addWorksheet('some-worksheet')
worksheet.addRow(['foo', 'bar']).commit()
worksheet.commit()
workbook.commit()
}

Works great for large files, performs much better than excel4node (got huge memory usage & Node process "out of memory" crash after nearly 5 minutes for a file containing 4 million cells in 20 sheets) since its streaming capabilities are much more limited (does not allows to "commit()" data to retrieve chunks as soon as they can be generated)

See also this SO answer.

install exceljs

npm i exceljs --save

import exceljs

var Excel = require('exceljs');
var workbook = new Excel.Workbook();

create workbook

var options = {
filename: __dirname+'/Reports/'+reportName,
useStyles: true,
useSharedStrings: true
};


var workbook = new Excel.stream.xlsx.WorkbookWriter(options);

after create worksheet

var worksheet = workbook.addWorksheet('Rate Sheet',{properties:{tabColor:{argb:'FFC0000'}}});

in worksheet.column array you pass column name in header and array key pass in key

worksheet.columns = [
{ header: 'column name', key: 'array key', width: 35},
{ header: 'column name', key: 'array key', width: 35},
{ header: 'column name', key: 'array key', width: 20},


];

after using forEach loop append row one by one in exel file

array.forEach(function(row){ worksheet.addRow(row); })

you can also perfome loop on each exel row and cell

worksheet.eachRow(function(row, rowNumber) {
console.log('Row ' + rowNumber + ' = ' + JSON.stringify(row.values));
});
row.eachCell(function(cell, colNumber) {
console.log('Cell ' + colNumber + ' = ' + cell.value);
});

Although this question has several answers, they may now be a little dated.

New readers may prefer to consider the xlsx or "sheetsJS" package, which now seems to now be by far the most popular node package for this use case.

The current top answer recommends excel4node , which does look quite good - but the latter package seems less maintained (and far less popular) than the former.

Answering the question directly, using xlsx:

const XLSX = require('xlsx');


/* create a new blank workbook */
const wb = XLSX.utils.book_new();


// Do stuff, write data
//
//


// write the workbook object to a file
XLSX.writeFile(workbook, 'out.xlsx');

Use exceljs library for creating and writing into existing excel sheets.

You can check this tutorial for detailed explanation.

link

First parameter is the source file

Second parameter is the separator

Third parameter is the resulting file (*.xlsx)

Attention: to increase node heap use: node --max-old-space-size=4096 index.js

const fs = require('fs');
var xl = require('excel4node');
const data = fs.readFileSync(process.argv[2], 'utf-8');
const lines = data.split(/\r?\n/);
const linesFromOne = [null].concat(lines);
var wb = new xl.Workbook();
var ws = wb.addWorksheet('Planilha 1');
for (let j=1;j<=linesFromOne.length-1;j++){
// Create a reusable style
var style = wb.createStyle({
font: {
color: '#050000',
size: 12,
},


});


pieces = linesFromOne[j].split(process.argv[3])
pieces.forEach((element, index) =>{
ws.cell(j, index+1).string(element)
.style(style);
});


}


wb.write(process.argv[4]);