excel4node、exceljs、node-xlsx、xlsx 和 xlsx-populate 都是 Node.js 生态中用于处理 Excel 文件(主要是 .xlsx 格式)的 npm 包,但它们在功能侧重、API 设计、维护状态和支持的操作(读/写)上有显著差异。这些库使开发者能够在服务器端生成、解析和操作电子表格,常用于数据导出、报表生成或文件导入等场景。
在现代 Web 应用中,Excel 文件的生成与解析是常见需求 —— 无论是导出报表、导入配置,还是处理用户上传的数据。Node.js 生态中有多个成熟的库可选,但它们在 API 设计、功能覆盖、性能表现和使用场景上差异显著。本文将从专业前端工程师的视角,深入剖析 excel4node、exceljs、node-xlsx、xlsx 和 xlsx-populate 这五个主流库的技术细节,帮助你在架构设计阶段做出合理选择。
首先明确一点:并非所有库都同时支持读取和写入 Excel 文件。
xlsx 是唯一一个双向全能型选手,既能读也能写 .xlsx、.xls、.csv 等多种格式。exceljs 和 xlsx-populate 同样支持完整的读写操作,且专注于现代 .xlsx 格式。excel4node 仅支持写入(生成)Excel 文件,无法解析已有文件。node-xlsx 本质上是对 xlsx 的轻量封装,因此继承了其读写能力,但仅暴露部分接口。⚠️ 注意:
node-xlsx自 2018 年后已无实质性更新,官方 GitHub 仓库归档,npm 页面标记为“不再维护”。新项目应避免使用node-xlsx,直接选用xlsx更可靠。
假设我们要创建一个包含两列(姓名、年龄)的工作表,并保存为 output.xlsx。
excel4node
const xl = require('excel4node');
const wb = new xl.Workbook();
const ws = wb.addWorksheet('Sheet1');
ws.cell(1, 1).string('姓名');
ws.cell(1, 2).string('年龄');
ws.cell(2, 1).string('张三');
ws.cell(2, 2).number(25);
wb.write('output.xlsx');
exceljs
const ExcelJS = require('exceljs');
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('Sheet1');
worksheet.addRow(['姓名', '年龄']);
worksheet.addRow(['张三', 25]);
await workbook.xlsx.writeFile('output.xlsx');
xlsx
const XLSX = require('xlsx');
const ws = XLSX.utils.aoa_to_sheet([
['姓名', '年龄'],
['张三', 25]
]);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
XLSX.writeFile(wb, 'output.xlsx');
xlsx-populate
const XlsxPopulate = require('xlsx-populate');
const workbook = await XlsxPopulate.fromBlankAsync();
workbook.sheet('Sheet1')
.cell('A1').value('姓名')
.cell('B1').value('年龄')
.cell('A2').value('张三')
.cell('B2').value(25);
await workbook.toFileAsync('output.xlsx');
node-xlsx(不推荐)
// 仅作参考,实际应使用 xlsx
const nodeXlsx = require('node-xlsx');
const buffer = nodeXlsx.build([{ name: 'Sheet1', data: [['姓名','年龄'],['张三',25]] }]);
require('fs').writeFileSync('output.xlsx', buffer);
当需要设置字体、颜色、边框等样式时,各库能力差异明显:
excel4node 提供细粒度的样式控制(如字体加粗、背景色、对齐方式),但 API 较为冗长。exceljs 的样式系统最完善,支持单元格样式、列宽、行高、条件格式甚至图表。xlsx-populate 基于 xlsx 内核,通过链式 API 提供直观的样式设置(如 .style('bold', true))。xlsx 本身对样式支持有限,需手动构造底层对象,通常需配合 sheetjs-style 等扩展。node-xlsx 几乎不支持样式。exceljs 设置样式示例
worksheet.getCell('A1').font = { bold: true, color: { argb: 'FF0000FF' } };
worksheet.getCell('A1').fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFFFFF00' }
};
xlsx-populate 设置样式示例
workbook.sheet('Sheet1')
.cell('A1')
.value('标题')
.style('bold', true)
.style('fill', 'yellow');
读取场景下,xlsx 和 exceljs 表现最佳。
xlsx 读取并转为 JSON
const workbook = XLSX.readFile('input.xlsx');
const worksheet = workbook.Sheets[workbook.SheetNames[0]];
const data = XLSX.utils.sheet_to_json(worksheet);
// [{ 姓名: '张三', 年龄: 25 }]
exceljs 读取并遍历行
const workbook = new ExcelJS.Workbook();
await workbook.xlsx.readFile('input.xlsx');
const worksheet = workbook.getWorksheet('Sheet1');
worksheet.eachRow((row, rowNumber) => {
if (rowNumber > 1) { // 跳过标题行
console.log(row.values); // [undefined, '张三', 25]
}
});
xlsx-populate 读取
const workbook = await XlsxPopulate.fromFileAsync('input.xlsx');
const sheet = workbook.sheet('Sheet1');
const name = sheet.cell('A2').value();
const age = sheet.cell('B2').value();
注意:excel4node 和 node-xlsx 无法读取 Excel 文件。
xlsx 在处理大型文件时内存占用较高,因其将整个工作簿加载到内存。exceljs 提供流式写入(stream.xlsx.write())和部分读取能力,更适合大文件场景。xlsx-populate 基于 xlsx,同样存在内存压力。excel4node 生成文件时内存效率尚可,但仅限写入场景。xlsx-populate 和 exceljs 是首选,它们能保留原模板的样式和公式。exceljs 的 API 更现代、灵活。excel4node 适合简单报表生成,但缺乏模板支持。| 场景 | 推荐库 | 理由 |
|---|---|---|
| 需要读写 Excel,且要求高性能、大文件支持 | exceljs | 流式 I/O、完整样式、活跃维护 |
| 需要基于模板填充数据,保留原有格式 | xlsx-populate | 直观的链式 API,专为模板设计 |
| 仅需生成简单 Excel 文件,无读取需求 | excel4node | 轻量,但功能有限 |
| 需要最大格式兼容性(含旧版 .xls) | xlsx | 支持最广的 Excel 格式 |
| 新项目 | 避免 node-xlsx | 已停止维护,功能被 xlsx 覆盖 |
exceljs:它在功能完整性、API 设计、性能和社区支持上最为均衡,适合绝大多数企业级应用。xlsx-populate 的链式语法能显著提升开发体验。.xls 等旧格式时,才选用 xlsx。node-xlsx:技术债风险高,无维护保障。选择合适的工具,能让 Excel 处理逻辑更健壮、可维护 —— 这正是专业前端架构师的价值所在。
选择 excel4node 仅当你需要一个轻量级的库来生成简单的 Excel 文件,且不需要读取功能或复杂样式。它的 API 直接但略显冗长,适合一次性导出基础数据表格的场景。由于仅支持写入且社区活跃度较低,不建议用于需要长期维护或复杂格式的项目。
选择 exceljs 如果你需要一个功能全面、维护活跃且支持流式处理的现代 Excel 库。它同时支持读写操作,提供强大的样式控制、图表支持和大文件处理能力,非常适合企业级应用中的复杂报表生成或数据导入导出需求。
不要在新项目中选择 node-xlsx。该包自 2018 年起已停止维护,官方仓库已归档,其功能完全被底层依赖 xlsx 所覆盖。直接使用 xlsx 可获得更好的稳定性、文档支持和安全更新。
选择 xlsx 如果你需要处理最广泛的电子表格格式(包括旧版 .xls、.csv、.ods 等),并且对样式要求不高。它是读写能力最全面的底层库,但高级样式支持有限,API 较为底层。适合需要最大格式兼容性而非复杂格式化的场景。
选择 xlsx-populate 如果你的核心需求是基于现有 Excel 模板进行数据填充,同时保留原有样式和公式。它提供直观的链式 API,简化了模板操作,但底层依赖 xlsx,在处理超大文件时可能面临内存压力。适合固定格式报表生成的业务场景。
A full featured xlsx file generation library allowing for the creation of advanced Excel files.
excel4node conforms to the ECMA-376 OOXML specification 2nd edition
REFERENCES
OpenXML White Paper
ECMA-376 Website
OpenOffice Excel File Format Reference
OpenOffice Anatomy of OOXML explanation
MS-XSLX spec (pdf)
Code references specifications sections from ECMA-376 2nd edition doc
ECMA-376, Second Edition, Part 1 - Fundamentals And Markup Language Reference.pdf
found in ECMA-376 2nd edition Part 1 download at http://www.ecma-international.org/publications/standards/Ecma-376.htm
// Require library
var xl = require('excel4node');
// Create a new instance of a Workbook class
var wb = new xl.Workbook();
// Add Worksheets to the workbook
var ws = wb.addWorksheet('Sheet 1');
var ws2 = wb.addWorksheet('Sheet 2');
// Create a reusable style
var style = wb.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
ws.cell(1, 1)
.number(100)
.style(style);
// Set value of cell B1 to 200 as a number type styled with paramaters of style
ws.cell(1, 2)
.number(200)
.style(style);
// Set value of cell C1 to a formula styled with paramaters of style
ws.cell(1, 3)
.formula('A1 + B1')
.style(style);
// Set value of cell A2 to 'string' styled with paramaters of style
ws.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.
ws.cell(3, 1)
.bool(true)
.style(style)
.style({font: {size: 14}});
wb.write('Excel.xlsx');
excel4node comes with some generic functions and types
xl.getExcelRowCol(cellRef)
Accepts cell reference (i.e. 'A1') and returns object with corresponding row and column
xl.getExcelRowCol('B5');
// returns { row: 5, col: 2}
xl.getExcelAlpha(column)
Accepts column as integer and returns corresponding column reference as alpha
xl.getExcelAlpha(10);
// returns 'J'
xl.getExcelCellRef(row, column)
Accepts row and column as integers and returns Excel cell reference
xl.getExcelCellRef(5, 3);
// returns 'C5'
xl.getExcelTS(date)
Accepts Date object and returns an Excel timestamp
var newDate = new Date('2015-01-01T00:00:00.0000Z');
xl.getExcelTS(newDate);
// Returns 42004.791666666664
xl.PAPER_SIZE
An instance of the Workbook class contains all data and parameters for the Excel Workbook.
Workbook constructor accepts an optional configuration object.
var xl = require('excel4node');
var wb = new xl.Workbook({
jszip: {
compression: 'DEFLATE',
},
defaultFont: {
size: 12,
name: 'Calibri',
color: 'FFFFFFFF',
},
dateFormat: 'm/d/yy hh:mm:ss',
workbookView: {
activeTab: 1, // Specifies an unsignedInt that contains the index to the active sheet in this book view.
autoFilterDateGrouping: true, // Specifies a boolean value that indicates whether to group dates when presenting the user with filtering options in the user interface.
firstSheet: 1, // Specifies the index to the first sheet in this book view.
minimized: false, // Specifies a boolean value that indicates whether the workbook window is minimized.
showHorizontalScroll: true, // Specifies a boolean value that indicates whether to display the horizontal scroll bar in the user interface.
showSheetTabs: true, // Specifies a boolean value that indicates whether to display the sheet tabs in the user interface.
showVerticalScroll: true, // Specifies a boolean value that indicates whether to display the vertical scroll bar.
tabRatio: 600, // Specifies ratio between the workbook tabs bar and the horizontal scroll bar.
visibility: 'visible', // Specifies visible state of the workbook window. ('hidden', 'veryHidden', 'visible') (§18.18.89)
windowHeight: 17620, // Specifies the height of the workbook window. The unit of measurement for this value is twips.
windowWidth: 28800, // Specifies the width of the workbook window. The unit of measurement for this value is twips..
xWindow: 0, // Specifies the X coordinate for the upper left corner of the workbook window. The unit of measurement for this value is twips.
yWindow: 440, // Specifies the Y coordinate for the upper left corner of the workbook window. The unit of measurement for this value is twips.
},
logLevel: 0, // 0 - 5. 0 suppresses all logs, 1 shows errors only, 5 is for debugging
author: 'Microsoft Office User', // Name for use in features such as comments
});
wb.addWorksheet(name, options);
Adds a new Worksheet to the Workbook
Accepts name of new Worksheet and options object (see Worksheet section)
Returns a Worksheet instance
wb.setSelectedTab(id);
Sets which tab will be selected when the Workbook is opened
Accepts Sheet ID (1-indexed sheet in order that sheets were added)
wb.createStyle(opts);
Creates a new Style instance
Accepts Style configuration object (see Style section)
Returns a new Style instance
wb.write();
The write() method can accept a single filename, a filename with callback function or an HTTP response object.
var xl = require('excel4node');
var wb = new xl.Workbook();
wb.write('ExcelFile.xlsx'); // Writes the file ExcelFile.xlsx to the process.cwd();
wb.write('ExcelFile.xlsx', function(err, stats) {
if (err) {
console.error(err);
} else {
console.log(stats); // Prints out an instance of a node.js fs.Stats object
}
});
// sends Excel file to web client requesting the / route
// server will respond with 500 error if excel workbook cannot be generated
var express = require('express');
var app = express();
app.get('/', function(req, res) {
wb.write('ExcelFile.xlsx', res);
});
app.listen(3000, function() {
console.log('Example app listening on port 3000!');
});
wb.writeToBuffer();
The writeToBuffer() method access no parameters and returns a promise that resolves with the nodebuffer generated by the JSZip library. This buffer can then be sent to other streams.
var xl = require('excel4node');
var wb = new xl.Workbook();
wb.writeToBuffer().then(function(buffer) {
// Do something with buffer
});
An instance of the Worksheet class contains all information specific to that worksheet
Worksheet constructor is called via Workbook class and accepts a name and configuration object
var xl = require('excel4node');
var wb = new xl.Workbook();
var options = {
margins: {
left: 1.5,
right: 1.5,
},
};
var ws = wb.addWorksheet('sheetname', options);
Full Worksheet options. All options are optional.
{
'margins': { // Accepts a Double in Inches
'bottom': Double,
'footer': Double,
'header': Double,
'left': Double,
'right': Double,
'top': Double
},
'printOptions': {
'centerHorizontal': Boolean,
'centerVertical': Boolean,
'printGridLines': Boolean,
'printHeadings': Boolean
},
'headerFooter': { // Set Header and Footer strings and options. See note below
'evenFooter': String,
'evenHeader': String,
'firstFooter': String,
'firstHeader': String,
'oddFooter': String,
'oddHeader': String,
'alignWithMargins': Boolean,
'differentFirst': Boolean,
'differentOddEven': Boolean,
'scaleWithDoc': Boolean
},
'pageSetup': {
'blackAndWhite': Boolean,
'cellComments': xl.CellComment, // one of 'none', 'asDisplayed', 'atEnd'
'copies': Integer,
'draft': Boolean,
'errors': xl.PrintError, // One of 'displayed', 'blank', 'dash', 'NA'
'firstPageNumber': Integer,
'fitToHeight': Integer, // Number of vertical pages to fit to
'fitToWidth': Integer, // Number of horizontal pages to fit to
'horizontalDpi': Integer,
'orientation': xl.Orientation, // One of 'default', 'portrait', 'landscape'
'pageOrder': xl.PageOrder, // One of 'downThenOver', 'overThenDown'
'paperHeight': xl.PositiveUniversalMeasure, // Value must a positive Float immediately followed by unit of measure from list mm, cm, in, pt, pc, pi. i.e. '10.5cm'
'paperSize': xl.PaperSize, // see lib/types/paperSize.js for all types and descriptions of types. setting paperSize overrides paperHeight and paperWidth settings
'paperWidth': xl.PositiveUniversalMeasure,
'scale': Integer,
'useFirstPageNumber': Boolean,
'usePrinterDefaults': Boolean,
'verticalDpi': Integer
},
'sheetView': {
'pane': { // Note. Calling .freeze() on a row or column will adjust these values
'activePane': xl.Pane, // one of 'bottomLeft', 'bottomRight', 'topLeft', 'topRight'
'state': xl.PaneState, // one of 'split', 'frozen', 'frozenSplit'
'topLeftCell': Cell Reference, // i.e. 'A1'
'xSplit': Float, // Horizontal position of the split, in 1/20th of a point; 0 (zero) if none. If the pane is frozen, this value indicates the number of columns visible in the top pane.
'ySplit': Float // Vertical position of the split, in 1/20th of a point; 0 (zero) if none. If the pane is frozen, this value indicates the number of rows visible in the left pane.
},
'rightToLeft': Boolean, // Flag indicating whether the sheet is in 'right to left' display mode. When in this mode, Column A is on the far right, Column B ;is one column left of Column A, and so on. Also, information in cells is displayed in the Right to Left format.
'showGridLines': Boolean, // Flag indicating whether the sheet should have gridlines enabled or disabled during view
'zoomScale': Integer, // Defaults to 100
'zoomScaleNormal': Integer, // Defaults to 100
'zoomScalePageLayoutView': Integer // Defaults to 100
},
'sheetFormat': {
'baseColWidth': Integer, // Defaults to 10. Specifies the number of characters of the maximum digit width of the normal style's font. This value does not include margin padding or extra padding for gridlines. It is only the number of characters.,
'defaultColWidth': Integer,
'defaultRowHeight': Integer,
'thickBottom': Boolean, // 'True' if rows have a thick bottom border by default.
'thickTop': Boolean // 'True' if rows have a thick top border by default.
},
'sheetProtection': { // same as "Protect Sheet" in Review tab of Excel
'autoFilter': Boolean, // True means that that user will be unable to modify this setting
'deleteColumns': Boolean,
'deleteRows': Boolean,
'formatCells': Boolean,
'formatColumns': Boolean,
'formatRows': Boolean,
'insertColumns': Boolean,
'insertHyperlinks': Boolean,
'insertRows': Boolean,
'objects': Boolean,
'password': String,
'pivotTables': Boolean,
'scenarios': Boolean,
'selectLockedCells': Boolean,
'selectUnlockedCells': Boolean,
'sheet': Boolean,
'sort': Boolean
},
'outline': {
'summaryBelow': Boolean, // Flag indicating whether summary rows appear below detail in an outline, when applying an outline/grouping.
'summaryRight': Boolean // Flag indicating whether summary columns appear to the right of detail in an outline, when applying an outline/grouping.
},
'disableRowSpansOptimization': Boolean // Flag indicating whether to remove the "spans" attribute on row definitions. Including spans in an optimization for Excel file readers but is not necessary,
'hidden': Boolean // Flag indicating whether to not hide the worksheet within the workbook.
}
Note: headerFooter strings accept Dynamic Formatting Strings. i.e. '&L&A&C&BCompany, Inc. Confidential&B&RPage &P of &N'
ws.addDataValidation();
Accepts a validation options object with these available options. All options are optional with exception of sqref.
{
sqref: String, // Required. Specifies range of cells to apply validate. i.e. "A1:A100"
allowBlank: Boolean, // Allows cells to be empty
errorStyle: String, // One of 'stop', 'warning', 'information'. You must specify an error string for this to take effect
error: String, // Message to show on error
errorTitle: String, // Title of message shown on error
showErrorMessage: Boolean, // Defaults to true if error or errorTitle is set
imeMode: String, // Restricts input to a specific set of characters. One of 'noControl', 'off', 'on', 'disabled', 'hiragana', 'fullKatakana', 'halfKatakana', 'fullAlpha', 'halfAlpha', 'fullHangul', 'halfHangul'
operator: String, // Must be one of 'between', 'notBetween', 'equal', 'notEqual', 'lessThan', 'lessThanOrEqual', 'greaterThan', 'greaterThanOrEqual'
prompt: String, // Message text of input prompt
promptTitle: String, // Title of input prompt
showInputMessage: Boolean, // Defaults to true if prompt or promptTitle is set
showDropDown: Boolean, // A boolean value indicating whether to display a dropdown combo box for a list type data validation. Defaults to true for type:list
type: String, // One of 'none', 'whole', 'decimal', 'list', 'date', 'time', 'textLength', 'custom'
formulas: Array // Minimum count 1, maximum count 2.
}
ws.addDataValidation({
type: 'list',
allowBlank: true,
prompt: 'Choose from dropdown',
error: 'Invalid choice was chosen',
showDropDown: true,
sqref: 'X2:X10',
formulas: ['value1,value2'],
});
ws.addDataValidation({
type: 'list',
allowBlank: 1,
sqref: 'B2:B10',
formulas: ['=sheet2!$A$1:$A$2'],
});
ws.addDataValidation({
type: 'whole',
operator: 'between',
allowBlank: 1,
sqref: 'A1:A10',
formulas: [0, 100],
});
Conditional formatting adds custom formats in response to cell reference state. A subset of conditional formatting features is currently supported by excel4node.
Formatting rules apply at the worksheet level.
The following example will highlight all cells between A1 and A10 that contain the string "ok" with bold, green text:
var wb = new xl.Workbook();
var ws = wb.addWorksheet('Sheet 1');
var myStyle = wb.createStyle({
font: {
bold: true,
color: '00FF00',
},
});
ws.addConditionalFormattingRule('A1:A10', {
// apply ws formatting ref 'A1:A10'
type: 'expression', // the conditional formatting type
priority: 1, // rule priority order (required)
formula: 'NOT(ISERROR(SEARCH("ok", A1)))', // formula that returns nonzero or 0
style: myStyle, // a style object containing styles to apply
});
The only conditional formatting type that is currently supported is expression.
When the formula returns zero, conditional formatting is NOT displayed. When the formula returns a nonzero value, conditional formatting is displayed.
Worksheet page breaks can be added at rows and columns
ws.addPageBreak(type, position) where type is row or column and position is the last row/column before the page break.
// Add page break after row 5
const wb = new xl.Workbook();
const ws = wb.addWorksheet('Sheet 1');
ws.cell(5, 1).string('Last row on this page');
ws.addPageBreak('row', 5);
Worksheet print areas can be set
ws.setPrintArea(startRow, startCol, endRow, endCol) where parameters are numbers corresponding to print area
// Sets print area to include all cells between A1 and C5 including C5
const wb = new xl.Workbook();
const ws = wb.addWorksheet('Sheet 1');
ws.cell(5, 3).string('Included in print area');
ws.cell(6, 3).string('Outside of print area, not included in printing');
ws.setPrintArea(1, 1, 5, 3);
Set custom widths and heights of columns/rows
ws.column(3).setWidth(50);
ws.row(1).setHeight(20);
Set rows and/or columns to create a frozen pane with an optionall scrollTo
ws.column(2).freeze(4); // Freezes the first two columns and scrolls the right view to column D
ws.row(4).freeze(); // Freezes the top four rows
Add Filters to a row If not options are given to the filter function, a filter will be added to all columns that contain data. Optionally, if you wish to restrict your filter to a specific range, you can specify start and end rows and columns for that range. The filter row should be included in this range.
ws.row(1).filter();
ws2.row(1).filter({
firstRow: 1,
firstColumn: 1,
lastRow: 20,
lastColumn: 5,
});
Hide a row or column
ws.row(5).hide();
ws.column(10).hide();
Create groupings of rows or columns and optionally state to collapse the grouping
ws.row(2).group(1, true);
ws.row(3).group(1, true);
ws.row(5).group(1);
ws.row(6).group(1);
ws.column(4).group(1, true);
ws.column(5).group(1, true);
Multiple groupings can be nested as demonstrated in this gist
The cell method accesses a single cell or range of cells to manipulate
cell method takes two required parameters and 3 optional parameters
.string() accepts a String or Array. Sending array allows for multiple font formattings within the same cell.
.number(number) accepts a number
.formula(formula) accepts an Excel formula
.date(date) accepts either a date or a date string
.link(url, [displayStr, tooltip]) accepts a URL and optionally a displayStr and hover tooltip
.bool(value) accepts a boolean (true or false)
.style(object) accepts the same object as when creating a new style. When applied to a cell that already has style formatting, the original formatting will be kept and updated with the changes sent to the style function.
.comment(comment, options) Add a comment to the particular cell
// ws.cell(startRow, startColumn, [[endRow, endColumn], isMerged]);
ws.cell(1, 1).string('My simple string');
ws.cell(1, 2).number(5);
ws.cell(1, 3).formula('B1 * 10');
ws.cell(1, 4).date(new Date());
ws.cell(1, 5).link('http://iamnater.com');
ws.cell(1, 6).bool(true);
ws.cell(2, 1, 2, 6, true).string('One big merged cell');
ws.cell(3, 1, 3, 6).number(1); // All 6 cells set to number 1
var complexString = [
'Workbook default font String\n',
{
bold: true,
underline: true,
italics: true,
color: 'FF0000',
size: 18,
name: 'Courier',
value: 'Hello',
},
' World!',
{
color: '000000',
underline: false,
name: 'Arial',
vertAlign: 'subscript',
},
' All',
' these',
' strings',
' are',
' black subsript,',
{
color: '0000FF',
value: '\nbut',
vertAlign: 'baseline',
},
' now are blue',
];
ws.cell(4, 1).string(complexString);
ws.cell(5, 1)
.string('another simple string')
.style({font: {name: 'Helvetica'}});
Style objects can be applied to Cells
Any combination of style values can be set
Creating a preset style is much more efficient than applying styles to individual cells
/*
Style Options Object:
{
alignment: { // §18.8.1
horizontal: ['center', 'centerContinuous', 'distributed', 'fill', 'general', 'justify', 'left', 'right'],
indent: integer, // Number of spaces to indent = indent value * 3
justifyLastLine: boolean,
readingOrder: ['contextDependent', 'leftToRight', 'rightToLeft'],
relativeIndent: integer, // number of additional spaces to indent
shrinkToFit: boolean,
textRotation: integer, // number of degrees to rotate text counter-clockwise
vertical: ['bottom', 'center', 'distributed', 'justify', 'top'],
wrapText: boolean
},
font: { // §18.8.22
bold: boolean,
charset: integer,
color: string,
condense: boolean,
extend: boolean,
family: string,
italics: boolean,
name: string,
outline: boolean,
scheme: string, // §18.18.33 ST_FontScheme (Font scheme Styles)
shadow: boolean,
strike: boolean,
size: integer,
underline: boolean,
vertAlign: string // §22.9.2.17 ST_VerticalAlignRun (Vertical Positioning Location)
},
border: { // §18.8.4 border (Border)
left: {
style: string, //§18.18.3 ST_BorderStyle (Border Line Styles) ['none', 'thin', 'medium', 'dashed', 'dotted', 'thick', 'double', 'hair', 'mediumDashed', 'dashDot', 'mediumDashDot', 'dashDotDot', 'mediumDashDotDot', 'slantDashDot']
color: string // HTML style hex value
},
right: {
style: string,
color: string
},
top: {
style: string,
color: string
},
bottom: {
style: string,
color: string
},
diagonal: {
style: string,
color: string
},
diagonalDown: boolean,
diagonalUp: boolean,
outline: boolean
},
fill: { // §18.8.20 fill (Fill)
type: string, // Currently only 'pattern' is implemented. Non-implemented option is 'gradient'
patternType: string, //§18.18.55 ST_PatternType (Pattern Type)
bgColor: string // HTML style hex value. defaults to black
fgColor: string // HTML style hex value. defaults to black.
},
numberFormat: integer or string // §18.8.30 numFmt (Number Format)
});
*/
var wb = new xl.Workbook();
var ws = wb.addWorksheet('Sheet 1');
var myStyle = wb.createStyle({
font: {
bold: true,
underline: true,
},
alignment: {
wrapText: true,
horizontal: 'center',
},
});
ws.cell(1, 1)
.string('my \n multiline\n string')
.style(myStyle);
ws.cell(2, 1).string('row 2 string');
ws.cell(3, 1).string('row 3 string');
ws.cell(2, 1, 3, 1).style(myStyle);
ws.cell(3, 1).style({font: {underline: false}});
ws.cell(4, 1)
.date(new Date())
.style({numberFormat: 'yyyy-mm-dd'});
// Since dates are stored as numbers in Excel, use the numberFormat option of the styles to set the date format as well.
Comments can be added to cells with some options
var wb = new xl.Workbook();
var ws = wb.addWorksheet('Sheet 1');
ws.cell(1, 1).comment('My Basic Comment');
ws.cell(2, 1).string('Cell A2').comment('My custom comment', {
fillColor: '#ABABAB', // default #FFFFE1
height: '100pt', // default 69pt
width: '160pt', // default 104pt
marginLeft: '200pt', // default is calculated from column
marginTop: '120pt', // default is calculated from row
visibility: 'visible', // default hidden
zIndex: '2', // default 1
})
Adds and image to the worksheet.
currently on 'picture' type is supported
positioning has 3 types, 'absoluteAnchor', 'oneCellAnchor', 'twoCellAnchor'
absoluteAnchor takes two position elements in either EMUs or measurements in cm, mm, or in
x:0, y:0 is top left corner of worksheet
oneCellAnchor and twoCellAnchor types will take positional objects:
{
'col': 1, \\ left side of image will be placed on left edge of this column
'colOff': '.5mm', \\ offset from left edge of column as EMU or measurment in cm, mm or in
'row': 1, \\top of image will be place on the top edge of this row
'rowOff': '.1in' or string \\ offset from top edge or row as EMU or measurement in cm, mm or in
}
position type of oneCellAnchor will take a single "from" position
position type of twoCellAnchor will take a "from" and "to" position
specifying a twoCellAnchor will automatically adjust the image to fit within the bounds of the two anchors.
ws.addImage({
path: './screenshot2.jpeg',
type: 'picture',
position: {
type: 'absoluteAnchor',
x: '1in',
y: '2in',
},
});
ws.addImage({
path: './screenshot1.jpg',
type: 'picture',
position: {
type: 'oneCellAnchor',
from: {
col: 1,
colOff: '0.5in',
row: 1,
rowOff: 0,
},
},
});
ws.addImage({
path: './screenshot1.png',
type: 'picture',
position: {
type: 'twoCellAnchor',
from: {
col: 1,
colOff: 0,
row: 10,
rowOff: 0,
},
to: {
col: 4,
colOff: 0,
row: 13,
rowOff: 0,
},
},
});
You can also pass buffer with loaded to memory image:
ws.addImage({
image: fs.readFileSync(path.resolve(__dirname, '../sampleFiles/logo.png')),
name: 'logo', // name is not required param
type: 'picture',
position: {
type: 'absoluteAnchor',
x: '1in',
y: '2in',
},
});