npm install exceljs
欢迎贡献!这可以帮助我了解大家需要一些什么功能,或者哪些 bugs 造成了极大的麻烦。
我只有一个请求;如果您提交对错误修复的请求(PR),请添加一个能够解决问题的单元测试或集成测试(在 spec 文件夹中)。
即使只是测试失败的请求(PR)也可以 - 我可以分析测试的过程并以此修复代码。
注意:请尽可能避免在请求(PR)中修改软件包版本。
版本一般在发布时会进行更新,任何版本更改很可能导致合并冲突。
明确地说,添加到该库的所有贡献都将包含在该库的 MIT 许可证中。
const ExcelJS = require('exceljs');
要使用 ES5 编译代码,请使用 dist/es5 路径。
const ExcelJS = require('exceljs/dist/es5');
**注意:**ES5 版本对许多 polyfill 都具有隐式依赖,而 exceljs 不再明确添加。
您需要在依赖项中添加 core-js
和 regenerator-runtime
,并在导入 exceljs
之前在代码中包含以下引用:
// exceljs 所需的 polyfills
require('core-js/modules/es.promise');
require('core-js/modules/es.string.includes');
require('core-js/modules/es.object.assign');
require('core-js/modules/es.object.keys');
require('core-js/modules/es.symbol');
require('core-js/modules/es.symbol.async-iterator');
require('regenerator-runtime/runtime');
const ExcelJS = require(‘exceljs/dist/es5’);
对于 IE 11,您还需要一个 polyfill 以支持 unicode regex 模式。 例如,
const rewritePattern = require('regexpu-core');
const {generateRegexpuOptions} = require('@babel/helper-create-regexp-features-plugin/lib/util');
const {RegExp} = global;
try {
new RegExp('a', 'u');
} catch (err) {
global.RegExp = function(pattern, flags) {
if (flags && flags.includes('u')) {
return new RegExp(rewritePattern(pattern, flags, generateRegexpuOptions({flags, pattern})));
}
return new RegExp(pattern, flags);
};
global.RegExp.prototype = RegExp;
}
ExcelJS 在 dist/ 文件夹内发布了两个支持浏览器的包:
一个是隐式依赖 core-js
polyfills 的…
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.26.0/polyfill.js"></script>
<script src="exceljs.js"></script>
另一个则没有…
<script src="--your-project's-pollyfills-here--"></script>
<script src="exceljs.bare.js"></script>
const workbook = new ExcelJS.Workbook();
workbook.creator = 'Me';
workbook.lastModifiedBy = 'Her';
workbook.created = new Date(1985, 8, 30);
workbook.modified = new Date();
workbook.lastPrinted = new Date(2016, 9, 27);
// 将工作簿日期设置为 1904 年日期系统
workbook.properties.date1904 = true;
// 在加载时强制工作簿计算属性
workbook.calcProperties.fullCalcOnLoad = true;
工作簿视图控制在查看工作簿时 Excel 将打开多少个单独的窗口。
workbook.views = [
{
x: 0, y: 0, width: 10000, height: 20000,
firstSheet: 0, activeTab: 1, visibility: 'visible'
}
]
const sheet = workbook.addWorksheet('My Sheet');
使用 addWorksheet
函数的第二个参数来指定工作表的选项。
示例:
// 创建带有红色标签颜色的工作表
const sheet = workbook.addWorksheet('My Sheet', {properties:{tabColor:{argb:'FFC0000'}}});
// 创建一个隐藏了网格线的工作表
const sheet = workbook.addWorksheet('My Sheet', {views: [{showGridLines: false}]});
// 创建一个第一行和列冻结的工作表
const sheet = workbook.addWorksheet('My Sheet', {views:[{xSplit: 1, ySplit:1}]});
// 使用A4设置的页面设置设置创建新工作表 - 横向
const worksheet = workbook.addWorksheet('My Sheet', {
pageSetup:{paperSize: 9, orientation:'landscape'}
});
// 创建一个具有页眉页脚的工作表
const sheet = workbook.addWorksheet('My Sheet', {
headerFooter:{firstHeader: "Hello Exceljs", firstFooter: "Hello World"}
});
// 创建一个冻结了第一行和第一列的工作表
const sheet = workbook.addWorksheet('My Sheet', {views:[{state: 'frozen', xSplit: 1, ySplit:1}]});
使用工作表的 id
从工作簿中删除工作表。
示例:
// 创建工作表
const sheet = workbook.addWorksheet('My Sheet');
// 使用工作表 id 删除工作表
workbook.removeWorksheet(sheet.id)
// 遍历所有工作表
// 注意: workbook.worksheets.forEach 仍然是可以正常运行的, 但是以下的方式更好
workbook.eachSheet(function(worksheet, sheetId) {
// ...
});
// 按 name 提取工作表
const worksheet = workbook.getWorksheet('My Sheet');
// 按 id 提取工作表
const worksheet = workbook.getWorksheet(1);
// 使工作表可见
worksheet.state = 'visible';
// 隐藏工作表
worksheet.state = 'hidden';
// 从“隐藏/取消隐藏”对话框中隐藏工作表
worksheet.state = 'veryHidden';
工作表支持属性存储,以允许控制工作表的某些功能。
// 创建具有属性的新工作表
const worksheet = workbook.addWorksheet('sheet', {properties:{tabColor:{argb:'FF00FF00'}}});
// 创建一个具有属性的可写的新工作表
const worksheetWriter = workbookWriter.addWorksheet('sheet', {properties:{outlineLevelCol:1}});
// 之后调整属性(工作表读写器不支持该操作)
worksheet.properties.outlineLevelCol = 2;
worksheet.properties.defaultRowHeight = 15;
支持的属性
属性名 | 默认值 | 描述 |
---|---|---|
tabColor | undefined | 标签的颜色 |
outlineLevelCol | 0 | 工作表列大纲级别 |
outlineLevelRow | 0 | 工作表行大纲级别 |
defaultRowHeight | 15 | 默认行高 |
defaultColWidth | (optional) | 默认列宽 |
dyDescent | 55 | TBD |
一些新的尺寸属性已添加到工作表中…
属性名 | 描述 |
---|---|
rowCount | 文档的总行数。 等于具有值的最后一行的行号。 |
actualRowCount | 具有值的行数的计数。 如果中间文档行为空,则该行将不包括在计数中。 |
columnCount | 文档的总列数。 等于所有行的最大单元数。 |
actualColumnCount | 具有值的列数的计数。 |
所有可能影响工作表打印的属性都保存在工作表上的 pageSetup
对象中。
// 使用 A4 横向的页面设置创建新工作表
const worksheet = workbook.addWorksheet('sheet', {
pageSetup:{paperSize: 9, orientation:'landscape'}
});
// 使用适合页面的pageSetup设置创建一个新的工作表编写器
const worksheetWriter = workbookWriter.addWorksheet('sheet', {
pageSetup:{fitToPage: true, fitToHeight: 5, fitToWidth: 7}
});
// 之后调整页面设置配置
worksheet.pageSetup.margins = {
left: 0.7, right: 0.7,
top: 0.75, bottom: 0.75,
header: 0.3, footer: 0.3
};
// 设置工作表的打印区域
worksheet.pageSetup.printArea = 'A1:G20';
// 通过使用 `&&` 分隔打印区域来设置多个打印区域
worksheet.pageSetup.printArea = 'A1:G10&&A11:G20';
// 在每个打印页面上重复特定的行
workheet.pageSetup.printTitlesRow = '1:3';
// 在每个打印页面上重复特定列
worksheet.pageSetup.printTitlesColumn = 'A:C';
支持的页面设置配置项
属性名 | 默认值 | 描述 |
---|---|---|
margins | 页面上的空白边距。 单位为英寸。 | |
orientation | 'portrait' | 页面方向 - 即较高 ('portrait' ) 或者较宽 ('landscape' ) |
horizontalDpi | 4294967295 | 水平方向上的 DPI。默认值为 -1 |
verticalDpi | 4294967295 | 垂直方向上的 DPI。默认值为 -1 |
fitToPage | 是否使用 fitToWidth 和 fitToHeight 或 scale 设置。默认基于存在于 pageSetup 对象中的设置-如果两者都存在,则 scale 优先级高(默认值为 false )。 | |
pageOrder | 'downThenOver' | 打印页面的顺序-['downThenOver', 'overThenDown'] 之一 |
blackAndWhite | false | 无色打印 |
draft | false | 打印质量较低(墨水) |
cellComments | 'None' | 在何处放置批注-['atEnd','asDisplayed','None'] 中的一个 |
errors | 'displayed' | 哪里显示错误 -['dash', 'blank', 'NA', 'displayed'] 之一 |
scale | 100 | 增加或减小打印尺寸的百分比值。 当 fitToPage 为 false 时激活 |
fitToWidth | 1 | 纸张应打印多少页宽。 当 fitToPage 为 true 时激活 |
fitToHeight | 1 | 纸张应打印多少页高。 当 fitToPage 为 true 时激活 |
paperSize | 使用哪种纸张尺寸(见下文) | |
showRowColHeaders | false | 是否显示行号和列字母 |
showGridLines | false | 是否显示网格线 |
firstPageNumber | 第一页使用哪个页码 | |
horizontalCentered | false | 是否将工作表数据水平居中 |
verticalCentered | false | 是否将工作表数据垂直居中 |
示例纸张尺寸
属性名 | 值 |
---|---|
Letter | undefined |
Legal | 5 |
Executive | 7 |
A3 | 8 |
A4 | 9 |
A5 | 11 |
B5 (JIS) | 13 |
Envelope #10 | 20 |
Envelope DL | 27 |
Envelope C5 | 28 |
Envelope B5 | 34 |
Envelope Monarch | 37 |
Double Japan Postcard Rotated | 82 |
16K 197x273 mm | 119 |
这是添加页眉和页脚的方法。
添加的内容主要是文本,例如时间,简介,文件信息等,您可以设置文本的样式。
此外,您可以为首页和偶数页设置不同的文本。
注意:目前不支持图片。
// 创建一个带有页眉和页脚的工作表
var sheet = workbook.addWorksheet('My Sheet', {
headerFooter:{firstHeader: "Hello Exceljs", firstFooter: "Hello World"}
});
// 创建一个带有页眉和页脚可写的工作表
var worksheetWriter = workbookWriter.addWorksheet('sheet', {
headerFooter:{firstHeader: "Hello Exceljs", firstFooter: "Hello World"}
});
// 代码中出现的&开头字符对应变量,相关信息可查阅下文的变量表
// 设置页脚(默认居中),结果:“第 2 页,共 16 页”
worksheet.headerFooter.oddFooter = "第 &P 页,共 &N 页";
// 将页脚(默认居中)设置为粗体,结果是:“第2页,共16页”
worksheet.headerFooter.oddFooter = "Page &P of &N";
// 将左页脚设置为 18px 并以斜体显示。 结果:“第2页,共16页”
worksheet.headerFooter.oddFooter = "&LPage &P of &N";
// 将中间标题设置为灰色Aril,结果为:“ 52 exceljs”
worksheet.headerFooter.oddHeader = "&C&KCCCCCC&\"Aril\"52 exceljs";
// 设置页脚的左,中和右文本。 结果:页脚左侧为“ Exceljs”。 页脚中心的“ demo.xlsx”。 页脚右侧的“第2页”
worksheet.headerFooter.oddFooter = "&Lexceljs&C&F&RPage &P";
// 在首页添加不同的页眉和页脚
worksheet.headerFooter.differentFirst = true;
worksheet.headerFooter.firstHeader = "Hello Exceljs";
worksheet.headerFooter.firstFooter = "Hello World"
支持的 headerFooter 设置
属性名 | 默认值 | 描述 |
---|---|---|
differentFirst | false | 将 differentFirst 的值设置为 true ,这表示第一页的页眉/页脚与其他页不同 |
differentOddEven | false | 将 differentOddEven 的值设置为 true ,表示奇数页和偶数页的页眉/页脚不同 |
oddHeader | null | 设置奇数(默认)页面的标题字符串,可以设置格式化字符串 |
oddFooter | null | 设置奇数(默认)页面的页脚字符串,可以设置格式化字符串 |
evenHeader | null | 设置偶数页的标题字符串,可以设置格式化字符串 |
evenFooter | null | 为偶数页设置页脚字符串,可以设置格式化字符串 |
firstHeader | null | 设置首页的标题字符串,可以设置格式化字符串 |
firstFooter | null | 设置首页的页脚字符串,可以设置格式化字符串 |
脚本命令
命令 | 描述 |
---|---|
&L | 将位置设定在左侧 |
&C | 将位置设置在中心 |
&R | 将位置设定在右边 |
&P | 当前页码 |
&N | 总页数 |
&D | 当前日期 |
&T | 当前时间 |
&G | 照片 |
&A | 工作表名称 |
&F | 文件名称 |
&B | 加粗文本 |
&I | 斜体文本 |
&U | 文本下划线 |
&“font name” | 字体名称,例如&“ Aril” |
&font size | 字体大小,例如12 |
&KHEXCode | 字体颜色,例如 &KCCCCCC |
现在,工作表支持视图列表,这些视图控制Excel如何显示工作表:
frozen
- 顶部和左侧的许多行和列被冻结在适当的位置。 仅右下部分会滚动split
- 该视图分为4个部分,每个部分可半独立滚动。每个视图还支持各种属性:
属性名 | 默认值 | 描述 |
---|---|---|
state | 'normal' | 控制视图状态 - 'normal' , 'frozen' 或者 'split' 之一 |
rightToLeft | false | 将工作表视图的方向设置为从右到左 |
activeCell | undefined | 当前选择的单元格 |
showRuler | true | 在页面布局中显示或隐藏标尺 |
showRowColHeaders | true | 显示或隐藏行标题和列标题(例如,顶部的 A1,B1 和左侧的1,2,3) |
showGridLines | true | 显示或隐藏网格线(针对未定义边框的单元格显示) |
zoomScale | 100 | 用于视图的缩放比例 |
zoomScaleNormal | 100 | 正常缩放视图 |
style | undefined | 演示样式- pageBreakPreview 或 pageLayout 之一。 注意:页面布局与 frozen 视图不兼容 |
冻结视图支持以下额外属性:
属性名 | 默认值 | 描述 |
---|---|---|
xSplit | 0 | 冻结多少列。要仅冻结行,请将其设置为 0 或 undefined |
ySplit | 0 | 冻结多少行。要仅冻结列,请将其设置为 0 或 undefined |
topLeftCell | special | 哪个单元格将在右下窗格中的左上角。注意:不能是冻结单元格。默认为第一个未冻结的单元格 |
worksheet.views = [
{state: 'frozen', xSplit: 2, ySplit: 3, topLeftCell: 'G10', activeCell: 'A1'}
];
拆分视图支持以下额外属性:
属性名 | 默认值 | 描述 |
---|---|---|
xSplit | 0 | 从左侧多少个点起,以放置拆分器。要垂直拆分,请将其设置为 0 或 undefined |
ySplit | 0 | 从顶部多少个点起,放置拆分器。要水平拆分,请将其设置为 0 或 undefined |
topLeftCell | undefined | 哪个单元格将在右下窗格中的左上角。 |
activePane | undefined | 哪个窗格将处于活动状态-topLeft ,topRight ,bottomLeft 和 bottomRight 中的一个 |
worksheet.views = [
{state: 'split', xSplit: 2000, ySplit: 3000, topLeftCell: 'G10', activeCell: 'A1'}
];
可以对工作表应用自动筛选器。
worksheet.autoFilter = 'A1:C1';
尽管范围字符串是 autoFilter
的标准形式,但工作表还将支持以下值:
// 将自动筛选器设置为从 A1 到 C1
worksheet.autoFilter = {
from: 'A1',
to: 'C1',
}
// 将自动筛选器设置为从第3行第1列的单元格到第5行第12列的单元格
worksheet.autoFilter = {
from: {
row: 3,
column: 1
},
to: {
row: 5,
column: 12
}
}
// 将自动筛选器设置为从D3到第7行第5列中的单元格
worksheet.autoFilter = {
from: 'D3',
to: {
row: 7,
column: 5
}
}
// 添加列标题并定义列键和宽度
// 注意:这些列结构仅是构建工作簿的方便之处,除了列宽之外,它们不会完全保留。
worksheet.columns = [
{ header: 'Id', key: 'id', width: 10 },
{ header: 'Name', key: 'name', width: 32 },
{ header: 'D.O.B.', key: 'DOB', width: 10, outlineLevel: 1 }
];
// 通过键,字母和基于1的列号访问单个列
const idCol = worksheet.getColumn('id');
const nameCol = worksheet.getColumn('B');
const dobCol = worksheet.getColumn(3);
// 设置列属性
// 注意:将覆盖 C1 单元格值
dobCol.header = 'Date of Birth';
// 注意:这将覆盖 C1:C2 单元格值
dobCol.header = ['Date of Birth', 'A.K.A. D.O.B.'];
// 从现在开始,此列将以 “dob” 而不是 “DOB” 建立索引
dobCol.key = 'dob';
dobCol.width = 15;
// 如果需要,隐藏列
dobCol.hidden = true;
// 为列设置大纲级别
worksheet.getColumn(4).outlineLevel = 0;
worksheet.getColumn(5).outlineLevel = 1;
// 列支持一个只读字段,以指示基于 `OutlineLevel` 的折叠状态
expect(worksheet.getColumn(4).collapsed).to.equal(false);
expect(worksheet.getColumn(5).collapsed).to.equal(true);
// 遍历此列中的所有当前单元格
dobCol.eachCell(function(cell, rowNumber) {
// ...
});
// 遍历此列中的所有当前单元格,包括空单元格
dobCol.eachCell({ includeEmpty: true }, function(cell, rowNumber) {
// ...
});
// 添加一列新值
worksheet.getColumn(6).values = [1,2,3,4,5];
// 添加稀疏列值
worksheet.getColumn(7).values = [,,2,3,,5,,7,,,,11];
// 剪切一列或多列(右边的列向左移动)
// 如果定义了列属性,则会相应地对其进行切割或移动
// 已知问题:如果拼接导致任何合并的单元格移动,结果可能是不可预测的
worksheet.spliceColumns(3,2);
// 删除一列,再插入两列。
// 注意:第4列及以上的列将右移1列。
// 另外:如果工作表中的行数多于列插入项中的值,则行将仍然被插入,就好像值存在一样。
const newCol3Values = [1,2,3,4,5];
const newCol4Values = ['one', 'two', 'three', 'four', 'five'];
worksheet.spliceColumns(3, 1, newCol3Values, newCol4Values);
// 获取一个行对象。如果尚不存在,则将返回一个新的空对象
const row = worksheet.getRow(5);
// Get multiple row objects. If it doesn't already exist, new empty ones will be returned
const rows = worksheet.getRows(5, 2); // start, length (>0, else undefined is returned)
// 获取工作表中的最后一个可编辑行(如果没有,则为 `undefined`)
const row = worksheet.lastRow;
// 设置特定的行高
row.height = 42.5;
// 隐藏行
row.hidden = true;
// 为行设置大纲级别
worksheet.getRow(4).outlineLevel = 0;
worksheet.getRow(5).outlineLevel = 1;
// 行支持一个只读字段,以指示基于 `OutlineLevel` 的折叠状态
expect(worksheet.getRow(4).collapsed).to.equal(false);
expect(worksheet.getRow(5).collapsed).to.equal(true);
row.getCell(1).value = 5; // A5 的值设置为5
row.getCell('name').value = 'Zeb'; // B5 的值设置为 “Zeb” - 假设第2列仍按名称键入
row.getCell('C').value = new Date(); // C5 的值设置为当前时间
// 获取行并作为稀疏数组返回
// 注意:接口更改:worksheet.getRow(4) ==> worksheet.getRow(4).values
row = worksheet.getRow(4).values;
expect(row[5]).toEqual('Kyle');
// 通过连续数组分配行值(其中数组元素 0 具有值)
row.values = [1,2,3];
expect(row.getCell(1).value).toEqual(1);
expect(row.getCell(2).value).toEqual(2);
expect(row.getCell(3).value).toEqual(3);
// 通过稀疏数组分配行值(其中数组元素 0 为 `undefined`)
const values = []
values[5] = 7;
values[10] = 'Hello, World!';
row.values = values;
expect(row.getCell(1).value).toBeNull();
expect(row.getCell(5).value).toEqual(7);
expect(row.getCell(10).value).toEqual('Hello, World!');
// 使用列键按对象分配行值
row.values = {
id: 13,
name: 'Thing 1',
dob: new Date()
};
// 在该行下方插入一个分页符
row.addPageBreak();
// 遍历工作表中具有值的所有行
worksheet.eachRow(function(row, rowNumber) {
console.log('Row ' + rowNumber + ' = ' + JSON.stringify(row.values));
});
// 遍历工作表中的所有行(包括空行)
worksheet.eachRow({ includeEmpty: true }, function(row, rowNumber) {
console.log('Row ' + rowNumber + ' = ' + JSON.stringify(row.values));
});
// 连续遍历所有非空单元格
row.eachCell(function(cell, colNumber) {
console.log('Cell ' + colNumber + ' = ' + cell.value);
});
// 遍历一行中的所有单元格(包括空单元格)
row.eachCell({ includeEmpty: true }, function(cell, colNumber) {
console.log('Cell ' + colNumber + ' = ' + cell.value);
});
// 提交给流一个完成的行
row.commit();
// 行尺寸
const rowSize = row.cellCount;
const numValues = row.actualCellCount;
// Add a couple of Rows by key-value, after the last current row, using the column keys
worksheet.addRow({id: 1, name: 'John Doe', dob: new Date(1970,1,1)});
worksheet.addRow({id: 2, name: 'Jane Doe', dob: new Date(1965,1,7)});
// Add a row by contiguous Array (assign to columns A, B & C)
worksheet.addRow([3, 'Sam', new Date()]);
// Add a row by sparse Array (assign to columns A, E & I)
const rowValues = [];
rowValues[1] = 4;
rowValues[5] = 'Kyle';
rowValues[9] = new Date();
worksheet.addRow(rowValues);
// Add a row with inherited style
// This new row will have same style as last row
// And return as row object
const newRow = worksheet.addRow(rowValues, 'i');
// Add an array of rows
const rows = [
[5,'Bob',new Date()], // row by array
{id:6, name: 'Barbara', dob: new Date()}
];
// add new rows and return them as array of row objects
const newRows = worksheet.addRows(rows);
// Add an array of rows with inherited style
// These new rows will have same styles as last row
// and return them as array of row objects
const newRowsStyled = worksheet.addRows(rows, 'i');
Parameter | Description | Default Value |
---|---|---|
value/s | The new row/s values | |
style | ‘i’ for inherit from row above, ‘i+’ to include empty cells, ‘n’ for none | ‘n’ |
const cell = worksheet.getCell('C3');
// 修改/添加单个单元格
cell.value = new Date(1968, 5, 1);
// 查询单元格的类型
expect(cell.type).toEqual(Excel.ValueType.Date);
// 使用单元格的字符串值
myInput.value = cell.text;
// 使用 html 安全的字符串进行渲染...
const html = '<div>' + cell.html + '</div>';
// 合并一系列单元格
worksheet.mergeCells('A4:B5');
// ...合并的单元格被链接起来了
worksheet.getCell('B5').value = 'Hello, World!';
expect(worksheet.getCell('B5').value).toBe(worksheet.getCell('A4').value);
expect(worksheet.getCell('B5').master).toBe(worksheet.getCell('A4'));
// ...合并的单元格共享相同的样式对象
expect(worksheet.getCell('B5').style).toBe(worksheet.getCell('A4').style);
worksheet.getCell('B5').style.font = myFonts.arial;
expect(worksheet.getCell('A4').style.font).toBe(myFonts.arial);
// 取消单元格合并将打破链接的样式
worksheet.unMergeCells('A4');
expect(worksheet.getCell('B5').style).not.toBe(worksheet.getCell('A4').style);
expect(worksheet.getCell('B5').style.font).not.toBe(myFonts.arial);
// 按左上,右下合并
worksheet.mergeCells('K10', 'M12');
// 按开始行,开始列,结束行,结束列合并(相当于 K10:M12)
worksheet.mergeCells(10,11,12,13);
insertRow(pos, value, style = 'n')
insertRows(pos, values, style = 'n')
// Insert a couple of Rows by key-value, shifting down rows every time
worksheet.insertRow(1, {id: 1, name: 'John Doe', dob: new Date(1970,1,1)});
worksheet.insertRow(1, {id: 2, name: 'Jane Doe', dob: new Date(1965,1,7)});
// Insert a row by contiguous Array (assign to columns A, B & C)
worksheet.insertRow(1, [3, 'Sam', new Date()]);
// Insert a row by sparse Array (assign to columns A, E & I)
var rowValues = [];
rowValues[1] = 4;
rowValues[5] = 'Kyle';
rowValues[9] = new Date();
// insert new row and return as row object
const insertedRow = worksheet.insertRow(1, rowValues);
// Insert a row, with inherited style
// This new row will have same style as row on top of it
// And return as row object
const insertedRowInherited = worksheet.insertRow(1, rowValues, 'i');
// Insert a row, keeping original style
// This new row will have same style as it was previously
// And return as row object
const insertedRowOriginal = worksheet.insertRow(1, rowValues, 'o');
// Insert an array of rows, in position 1, shifting down current position 1 and later rows by 2 rows
var rows = [
[5,'Bob',new Date()], // row by array
{id:6, name: 'Barbara', dob: new Date()}
];
// insert new rows and return them as array of row objects
const insertedRows = worksheet.insertRows(1, rows);
// Insert an array of rows, with inherited style
// These new rows will have same style as row on top of it
// And return them as array of row objects
const insertedRowsInherited = worksheet.insertRows(1, rows, 'i');
// Insert an array of rows, keeping original style
// These new rows will have same style as it was previously in 'pos' position
const insertedRowsOriginal = worksheet.insertRows(1, rows, 'o');
Parameter | Description | Default Value |
---|---|---|
pos | Row number where you want to insert, pushing down all rows from there | |
value/s | The new row/s values | |
style | ‘i’ for inherit from row above, , ‘i+’ to include empty cells, ‘o’ for original style, ‘o+’ to include empty cells, ‘n’ for none | ‘n’ |
// Cut one or more rows (rows below are shifted up)
// Known Issue: If a splice causes any merged cells to move, the results may be unpredictable
worksheet.spliceRows(4, 3);
// remove one row and insert two more.
// Note: rows 4 and below will be shifted down by 1 row.
const newRow3Values = [1, 2, 3, 4, 5];
const newRow4Values = ['one', 'two', 'three', 'four', 'five'];
worksheet.spliceRows(3, 1, newRow3Values, newRow4Values);
// Cut one or more cells (cells to the right are shifted left)
// Note: this operation will not affect other rows
row.splice(3, 2);
// remove one cell and insert two more (cells to the right of the cut cell will be shifted right)
row.splice(4, 1, 'new value 1', 'new value 2');
Parameter | Description | Default Value |
---|---|---|
start | Starting point to splice from | |
count | Number of rows/cells to remove | |
…inserts | New row/cell values to insert |
duplicateRow(start, amount = 1, insert = true)
const wb = new ExcelJS.Workbook();
const ws = wb.addWorksheet('duplicateTest');
ws.getCell('A1').value = 'One';
ws.getCell('A2').value = 'Two';
ws.getCell('A3').value = 'Three';
ws.getCell('A4').value = 'Four';
// 该行将重复复制第一行两次,但将替换第二行和第三行
// 如果第三个参数为 true,则它将插入2个新行,其中包含行 “One” 的值和样式
ws.duplicateRow(1,2,false);
参数 | 描述 | 默认值 |
---|---|---|
start | 要复制的行号(Excel中的第一个是1) | |
amount | 您要复制行的次数 | 1 |
insert | 如果要为重复项插入新行,则为 true ,否则为 false 将替换已有行 | true |
单个单元格(或多个单元格组)可以为它们分配名称。名称可用于公式和数据验证(可能还有更多)。
// 为单元格分配(或获取)名称(将覆盖该单元具有的其他任何名称)
worksheet.getCell('A1').name = 'PI';
expect(worksheet.getCell('A1').name).to.equal('PI');
// 为单元格分配(或获取)一组名称(单元可以具有多个名称)
worksheet.getCell('A1').names = ['thing1', 'thing2'];
expect(worksheet.getCell('A1').names).to.have.members(['thing1', 'thing2']);
// 从单元格中删除名称
worksheet.getCell('A1').removeName('thing1');
expect(worksheet.getCell('A1').names).to.have.members(['thing2']);
单元格可以定义哪些值有效或无效,并提示用户以帮助指导它们。
验证类型可以是以下之一:
类型 | 描述 |
---|---|
list | 定义一组离散的有效值。Excel 将在下拉菜单中提供这些内容,以便于输入 |
whole | 该值必须是整数 |
decimal | 该值必须是十进制数 |
textLength | 该值可以是文本,但长度是受控的 |
custom | 自定义公式控制有效值 |
对于 list
或 custom
以外的其他类型,以下运算符会影响验证:
运算符 | 描述 |
---|---|
between | 值必须介于公式结果之间 |
notBetween | 值不能介于公式结果之间 |
equal | 值必须等于公式结果 |
notEqual | 值不能等于公式结果 |
greaterThan | 值必须大于公式结果 |
lessThan | 值必须小于公式结果 |
greaterThanOrEqual | 值必须大于或等于公式结果 |
lessThanOrEqual | 值必须小于或等于公式结果 |
// 指定有效值的列表(One,Two,Three,Four)。
// Excel 将提供一个包含这些值的下拉列表。
worksheet.getCell('A1').dataValidation = {
type: 'list',
allowBlank: true,
formulae: ['"One,Two,Three,Four"']
};
// 指定范围内的有效值列表。
// Excel 将提供一个包含这些值的下拉列表。
worksheet.getCell('A1').dataValidation = {
type: 'list',
allowBlank: true,
formulae: ['$D$5:$F$5']
};
// 指定单元格必须为非5的整数。
// 向用户显示适当的错误消息(如果他们弄错了)
worksheet.getCell('A1').dataValidation = {
type: 'whole',
operator: 'notEqual',
showErrorMessage: true,
formulae: [5],
errorStyle: 'error',
errorTitle: 'Five',
error: 'The value must not be Five'
};
// 指定单元格必须为1.5到7之间的十进制数字。
// 添加“工具提示”以帮助指导用户
worksheet.getCell('A1').dataValidation = {
type: 'decimal',
operator: 'between',
allowBlank: true,
showInputMessage: true,
formulae: [1.5, 7],
promptTitle: 'Decimal',
prompt: 'The value must between 1.5 and 7'
};
// 指定单元格的文本长度必须小于15
worksheet.getCell('A1').dataValidation = {
type: 'textLength',
operator: 'lessThan',
showErrorMessage: true,
allowBlank: true,
formulae: [15]
};
// 指定单元格必须是2016年1月1日之前的日期
worksheet.getCell('A1').dataValidation = {
type: 'date',
operator: 'lessThan',
showErrorMessage: true,
allowBlank: true,
formulae: [new Date(2016,0,1)]
};
将旧样式的注释添加到单元格
// 纯文字笔记
worksheet.getCell('A1').note = 'Hello, ExcelJS!';
// 彩色格式化的笔记
ws.getCell('B1').note = {
texts: [
{'font': {'size': 12, 'color': {'theme': 0}, 'name': 'Calibri', 'family': 2, 'scheme': 'minor'}, 'text': 'This is '},
{'font': {'italic': true, 'size': 12, 'color': {'theme': 0}, 'name': 'Calibri', 'scheme': 'minor'}, 'text': 'a'},
{'font': {'size': 12, 'color': {'theme': 1}, 'name': 'Calibri', 'family': 2, 'scheme': 'minor'}, 'text': ' '},
{'font': {'size': 12, 'color': {'argb': 'FFFF6600'}, 'name': 'Calibri', 'scheme': 'minor'}, 'text': 'colorful'},
{'font': {'size': 12, 'color': {'theme': 1}, 'name': 'Calibri', 'family': 2, 'scheme': 'minor'}, 'text': ' text '},
{'font': {'size': 12, 'color': {'argb': 'FFCCFFCC'}, 'name': 'Calibri', 'scheme': 'minor'}, 'text': 'with'},
{'font': {'size': 12, 'color': {'theme': 1}, 'name': 'Calibri', 'family': 2, 'scheme': 'minor'}, 'text': ' in-cell '},
{'font': {'bold': true, 'size': 12, 'color': {'theme': 1}, 'name': 'Calibri', 'family': 2, 'scheme': 'minor'}, 'text': 'format'},
],
margins: {
insetmode: 'custom',
inset: [0.25, 0.25, 0.35, 0.35]
},
protection: {
locked: True,
lockText: False
},
editAs: 'twoCells'
};
下表定义了单元格注释已支持的属性。
Field | Required | Default Value | Description |
---|---|---|---|
texts | Y | 评论文字 | |
margins | N | {} | 确定自动或自定义设置单元格注释的边距值 |
protection | N | {} | 可以使用保护属性来指定对象和对象文本的锁定状态 |
editAs | N | ‘absolute’ | 可以使用’editAs’属性来指定注释如何锚定到单元格 |
确定单元格批注的页面距设置模式,自动或者自定义模式。
ws.getCell('B1').note.margins = {
insetmode: 'custom',
inset: [0.25, 0.25, 0.35, 0.35]
}
Property | Required | Default Value | Description |
---|---|---|---|
insetmode | N | ‘auto’ | 确定是否自动设置注释边距,并且值是’auto’ 或者 ‘custom’ |
inset | N | [0.13, 0.13, 0.25, 0.25] | 批注页边距的值,单位是厘米, 方向是左-上-右-下 |
注意:只有当 insetmode
的值设置为’custom’时,inset
的设置才生效。
可以使用保护属性来修改单元级别保护。
ws.getCell('B1').note.protection = {
locked: 'False',
lockText: 'False',
};
Property | Required | Default Value | Description |
---|---|---|---|
locked | N | ‘True’ | 此元素指定在保护工作表时对象已锁定 |
lockText | N | ‘True’ | 该元素指定对象的文本已锁定 |
单元格注释还可以具有属性 ‘editAs’,该属性将控制注释如何锚定到单元格。
它可以具有以下值之一:
ws.getCell('B1').note.editAs = 'twoCells'
Value | Description |
---|---|
twoCells | 它指定注释的大小、位置随单元格而变 |
oneCells | 它指定注释的大小固定,位置随单元格而变 |
absolute | 这是默认值,它指定注释的大小、位置均固定 |
表允许表格内数据的表内操作。
要将表添加到工作表,请定义表模型并调用 addTable
:
// 将表格添加到工作表
ws.addTable({
name: 'MyTable',
ref: 'A1',
headerRow: true,
totalsRow: true,
style: {
theme: 'TableStyleDark3',
showRowStripes: true,
},
columns: [
{name: 'Date', totalsRowLabel: 'Totals:', filterButton: true},
{name: 'Amount', totalsRowFunction: 'sum', filterButton: false},
],
rows: [
[new Date('2019-07-20'), 70.10],
[new Date('2019-07-21'), 70.60],
[new Date('2019-07-22'), 70.10],
],
});
注意:将表格添加到工作表将通过放置表格的标题和行数据来修改工作表。
结果就是表格覆盖的工作表上的所有数据(包括标题和所有的)都将被覆盖。
下表定义了表格支持的属性。
表属性 | 描述 | 是否需要 | 默认值 |
---|---|---|---|
name | 表格名称 | Y | |
displayName | 表格的显示名称 | N | name |
ref | 表格的左上方单元格 | Y | |
headerRow | 在表格顶部显示标题 | N | true |
totalsRow | 在表格底部显示总计 | N | false |
style | 额外的样式属性 | N | {} |
columns | 列定义 | Y | |
rows | 数据行 | Y |
下表定义了表格中支持的属性样式属性。
样式属性 | 描述 | 是否需要 | 默认值 |
---|---|---|---|
theme | 桌子的颜色主题 | N | 'TableStyleMedium2' |
showFirstColumn | 突出显示第一列(粗体) | N | false |
showLastColumn | 突出显示最后一列(粗体) | N | false |
showRowStripes | 用交替的背景色显示行 | N | false |
showColumnStripes | 用交替的背景色显示列 | N | false |
下表定义了每个表格列中支持的属性。
列属性 | 描述 | 是否需要 | 默认值 |
---|---|---|---|
name | 列名,也用在标题中 | Y | |
filterButton | 切换标题中的过滤器控件 | N | false |
totalsRowLabel | 用于描述统计行的标签(第一列) | N | 'Total' |
totalsRowFunction | 统计函数名称 | N | 'none' |
totalsRowFormula | 自定义函数的可选公式 | N |
下表列出了由列定义的 totalsRowFunction
属性的有效值。如果使用 'custom'
以外的任何值,则无需包括关联的公式,因为该公式将被表格插入。
统计函数 | 描述 |
---|---|
none | 此列没有统计函数 |
average | 计算列的平均值 |
countNums | 统计数字条目数 |
count | 条目数 |
max | 此列中的最大值 |
min | 此列中的最小值 |
stdDev | 该列的标准偏差 |
var | 此列的方差 |
sum | 此列的条目总数 |
custom | 自定义公式。 需要关联的 totalsRowFormula 值。 |
有效的主题名称遵循以下模式:
Shades(阴影),Number(数字)可以是以下之一:
对于无主题,请使用值 null
。
注意:exceljs 尚不支持自定义表格主题。
表格支持一组操作函数,这些操作函数允许添加或删除数据以及更改某些属性。由于这些操作中的许多操作可能会对工作表产生副作用,因此更改必须在完成后立即提交。
表中的所有索引值均基于零,因此第一行号和第一列号为 0
。
添加或删除标题和统计
const table = ws.getTable('MyTable');
// 打开标题行
table.headerRow = true;
// 关闭统计行
table.totalsRow = false;
// 将表更改提交到工作表中
table.commit();
重定位表
const table = ws.getTable('MyTable');
// 表格左上移至 D4
table.ref = 'D4';
// 将表更改提交到工作表中
table.commit();
添加和删除行
const table = ws.getTable('MyTable');
// 删除前两行
table.removeRows(0, 2);
// 在索引 5 处插入新行
table.addRow([new Date('2019-08-05'), 5, 'Mid'], 5);
// 在表格底部追加新行
table.addRow([new Date('2019-08-10'), 10, 'End']);
// 将表更改提交到工作表中
table.commit();
添加和删除列
const table = ws.getTable('MyTable');
// 删除第二列
table.removeColumns(1, 1);
// 在索引 1 处插入新列(包含数据)
table.addColumn(
{name: 'Letter', totalsRowFunction: 'custom', totalsRowFormula: 'ROW()', totalsRowResult: 6, filterButton: true},
['a', 'b', 'c', 'd'],
2
);
// 将表更改提交到工作表中
table.commit();
更改列属性
const table = ws.getTable('MyTable');
// 获取第二列的列包装器
const column = table.getColumn(1);
// 设置一些属性
column.name = 'Code';
column.filterButton = true;
column.style = {font:{bold: true, name: 'Comic Sans MS'}};
column.totalsRowLabel = 'Totals';
column.totalsRowFunction = 'custom';
column.totalsRowFormula = 'ROW()';
column.totalsRowResult = 10;
// 将表更改提交到工作表中
table.commit();
单元格,行和列均支持一组丰富的样式和格式,这些样式和格式会影响单元格的显示方式。
通过分配以下属性来设置样式:
// 为单元格分配样式
ws.getCell('A1').numFmt = '0.00%';
// 将样式应用于工作表列
ws.columns = [
{ header: 'Id', key: 'id', width: 10 },
{ header: 'Name', key: 'name', width: 32, style: { font: { name: 'Arial Black' } } },
{ header: 'D.O.B.', key: 'DOB', width: 10, style: { numFmt: 'dd/mm/yyyy' } }
];
// 将第3列设置为“货币格式”
ws.getColumn(3).numFmt = '"£"#,##0.00;[Red]\-"£"#,##0.00';
// 将第2行设置为 Comic Sans。
ws.getRow(2).font = { name: 'Comic Sans MS', family: 4, size: 16, underline: 'double', bold: true };
将样式应用于行或列时,它将应用于该行或列中所有当前存在的单元格。另外,创建的任何新单元格都将从其所属的行和列继承其初始样式。
如果单元格的行和列都定义了特定的样式(例如,字体),则该单元格所在行样式比列样式具有更高优先级。但是,如果行和列定义了不同的样式(例如 column.numFmt
和 row.font
),则单元格将继承行的字体和列的 numFmt
。
注意:以上所有属性(numFmt
(字符串)除外)都是 JS 对象结构。如果将同一样式对象分配给多个电子表格实体,则每个实体将共享同一样式对象。如果样式对象后来在电子表格序列化之前被修改,则所有引用该样式对象的实体也将被修改。此行为旨在通过减少创建的JS对象的数量来优先考虑性能。如果希望样式对象是独立的,则需要先对其进行克隆,然后再分配它们。同样,默认情况下,如果电子表格实体共享相似的样式,则从文件(或流)中读取文档时,它们也将引用相同的样式对象。
// 将值显示为“ 1 3/5”
ws.getCell('A1').value = 1.6;
ws.getCell('A1').numFmt = '# ?/?';
// 显示为“ 1.60%”
ws.getCell('B1').value = 0.016;
ws.getCell('B1').numFmt = '0.00%';
// for the wannabe graphic designers out there
ws.getCell('A1').font = {
name: 'Comic Sans MS',
family: 4,
size: 16,
underline: true,
bold: true
};
// for the graduate graphic designers...
ws.getCell('A2').font = {
name: 'Arial Black',
color: { argb: 'FF00FF00' },
family: 2,
size: 14,
italic: true
};
// 垂直对齐
ws.getCell('A3').font = {
vertAlign: 'superscript'
};
// 注意:该单元格将存储对分配的字体对象的引用。
// 如果之后更改了字体对象,则单元字体也将更改。
const font = { name: 'Arial', size: 12 };
ws.getCell('A3').font = font;
font.size = 20; // 单元格 A3 现在具有20号字体!
// 从文件或流中读取工作簿后,共享相似字体的单元格可能引用相同的字体对象
字体属性 | 描述 | 示例值 |
---|---|---|
name | 字体名称。 | ‘Arial’, ‘Calibri’, etc. |
family | 备用字体家族。整数值。 | 1 - Serif, 2 - Sans Serif, 3 - Mono, Others - unknown |
scheme | 字体方案。 | ‘minor’, ‘major’, ‘none’ |
charset | 字体字符集。整数值。 | 1, 2, etc. |
size | 字体大小。整数值。 | 9, 10, 12, 16, etc. |
color | 颜色描述,一个包含 ARGB 值的对象。 | { argb: ‘FFFF0000’} |
bold | 字体 粗细 | true, false |
italic | 字体 倾斜 | true, false |
underline | 字体 下划线 样式 | true, false, ‘none’, ‘single’, ‘double’, ‘singleAccounting’, ‘doubleAccounting’ |
strike | 字体
| true, false |
outline | 字体轮廓 | true, false |
vertAlign | 垂直对齐 | ‘superscript’, ‘subscript’ |
// 将单元格对齐方式设置为左上,中间居中,右下
ws.getCell('A1').alignment = { vertical: 'top', horizontal: 'left' };
ws.getCell('B1').alignment = { vertical: 'middle', horizontal: 'center' };
ws.getCell('C1').alignment = { vertical: 'bottom', horizontal: 'right' };
// 将单元格设置为自动换行
ws.getCell('D1').alignment = { wrapText: true };
// 将单元格缩进设置为1
ws.getCell('E1').alignment = { indent: 1 };
// 将单元格文本旋转设置为向上30deg,向下45deg和垂直文本
ws.getCell('F1').alignment = { textRotation: 30 };
ws.getCell('G1').alignment = { textRotation: -45 };
ws.getCell('H1').alignment = { textRotation: 'vertical' };
有效的对齐属性值
水平的 | 垂直 | 文本换行 | 自适应 | 缩进 | 阅读顺序 | 文本旋转 |
---|---|---|---|---|---|---|
left | top | true | true | integer | rtl | 0 to 90 |
center | middle | false | false | ltr | -1 to -90 | |
right | bottom | vertical | ||||
fill | distributed | |||||
justify | justify | |||||
centerContinuous | ||||||
distributed |
// 在A1周围设置单个细边框
ws.getCell('A1').border = {
top: {style:'thin'},
left: {style:'thin'},
bottom: {style:'thin'},
right: {style:'thin'}
};
// 在A3周围设置双细绿色边框
ws.getCell('A3').border = {
top: {style:'double', color: {argb:'FF00FF00'}},
left: {style:'double', color: {argb:'FF00FF00'}},
bottom: {style:'double', color: {argb:'FF00FF00'}},
right: {style:'double', color: {argb:'FF00FF00'}}
};
// 在A5中设置厚红十字边框
ws.getCell('A5').border = {
diagonal: {up: true, down: true, style:'thick', color: {argb:'FFFF0000'}}
};
有效边框样式
// 用红色深色垂直条纹填充A1
ws.getCell('A1').fill = {
type: 'pattern',
pattern:'darkVertical',
fgColor:{argb:'FFFF0000'}
};
// 在A2中填充深黄色格子和蓝色背景
ws.getCell('A2').fill = {
type: 'pattern',
pattern:'darkTrellis',
fgColor:{argb:'FFFFFF00'},
bgColor:{argb:'FF0000FF'}
};
// 从左到右用蓝白蓝渐变填充A3
ws.getCell('A3').fill = {
type: 'gradient',
gradient: 'angle',
degree: 0,
stops: [
{position:0, color:{argb:'FF0000FF'}},
{position:0.5, color:{argb:'FFFFFFFF'}},
{position:1, color:{argb:'FF0000FF'}}
]
};
// 从中心开始用红绿色渐变填充A4
ws.getCell('A4').fill = {
type: 'gradient',
gradient: 'path',
center:{left:0.5,top:0.5},
stops: [
{position:0, color:{argb:'FFFF0000'}},
{position:1, color:{argb:'FF00FF00'}}
]
};
属性 | 是否需要 | 描述 |
---|---|---|
type | Y | 值: 'pattern' 指定此填充使用模式 |
pattern | Y | 指定模式类型 (查看下面 有效模式类型 ) |
fgColor | N | 指定图案前景色。默认为黑色。 |
bgColor | N | 指定图案背景色。默认为白色。 |
有效模式类型
属性 | 是否需要 | 描述 |
---|---|---|
type | Y | 值: 'gradient' 指定此填充使用渐变 |
gradient | Y | 指定渐变类型。['angle','path'] 之一 |
degree | angle | 对于“角度”渐变,指定渐变的方向。0 是从左到右。值从 1-359 顺时针旋转方向 |
center | path | 对于“路径”渐变。指定路径起点的相对坐标。“左”和“顶”值的范围是 0 到 1 |
stops | Y | 指定渐变颜色序列。是包含位置和颜色(从位置 0 开始到位置 1 结束)的对象的数组。中间位置可用于指定路径上的其他颜色。 |
注意事项
使用上面的接口,可能会创建使用XLSX编辑器程序无法实现的渐变填充效果。例如,Excel 仅支持0、45、90 和 135 的角度梯度。类似地,stops 的顺序也可能受到 UI 的限制,其中位置 [0,1] 或[0,0.5,1] 是唯一的选择。请谨慎处理此填充,以确保目标 XLSX 查看器支持该填充。
现在,单个单元格支持RTF文本或单元格格式化。富文本值可以控制文本值内任意数量的子字符串的字体属性。有关支持哪些字体属性的详细信息,请参见字体。