ExcelJS-免费开源纯JS操作Excel文件读取、修改、导出
当前位置:点晴教程→知识管理交流
→『 技术文档交流 』
ExcelJS读取,操作并写入电子表格数据和样式到 XLSX 和 JSON 文件。 一个 Excel 电子表格文件逆向工程项目。 安装npm install exceljs 新的功能!
贡献欢迎贡献!这可以帮助我了解大家需要一些什么功能,或者哪些 bugs 造成了极大的麻烦。 我只有一个请求;如果您提交对错误修复的请求(PR),请添加一个能够解决问题的单元测试或集成测试(在 spec 文件夹中)。 即使只是测试失败的请求(PR)也可以 - 我可以分析测试的过程并以此修复代码。 注意:请尽可能避免在请求(PR)中修改软件包版本。 版本一般在发布时会进行更新,任何版本更改很可能导致合并冲突。 明确地说,添加到该库的所有贡献都将包含在该库的 MIT 许可证中。 目录导入const ExcelJS = require('exceljs'); ES5 导入要使用 ES5 编译代码,请使用 dist/es5 路径。 const ExcelJS = require('exceljs/dist/es5'); **注意:**ES5 版本对许多 polyfill 都具有隐式依赖,而 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.prototype; } 浏览器端ExcelJS 在 dist/ 文件夹内发布了两个支持浏览器的包: 一个是隐式依赖 <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'); 使用 示例: // 创建带有红色标签颜色的工作表 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}]}); 删除工作表使用工作表的 示例: // 创建工作表 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; 支持的属性
工作表尺寸一些新的尺寸属性已添加到工作表中...
页面设置所有可能影响工作表打印的属性都保存在工作表上的 // 使用 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'; // 在每个打印页面上重复特定的行 worksheet.pageSetup.printTitlesRow = '1:3'; // 在每个打印页面上重复特定列 worksheet.pageSetup.printTitlesColumn = 'A:C'; 支持的页面设置配置项
示例纸张尺寸
页眉和页脚这是添加页眉和页脚的方法。 添加的内容主要是文本,例如时间,简介,文件信息等,您可以设置文本的样式。 此外,您可以为首页和偶数页设置不同的文本。 注意:目前不支持图片。 // 创建一个带有页眉和页脚的工作表 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 设置
脚本命令
工作表视图现在,工作表支持视图列表,这些视图控制Excel如何显示工作表:
每个视图还支持各种属性:
冻结视图冻结视图支持以下额外属性:
worksheet.views = [ {state: 'frozen', xSplit: 2, ySplit: 3, topLeftCell: 'G10', activeCell: 'A1'} ]; 拆分视图拆分视图支持以下额外属性:
worksheet.views = [ {state: 'split', xSplit: 2000, ySplit: 3000, topLeftCell: 'G10', activeCell: 'A1'} ]; 自动筛选器可以对工作表应用自动筛选器。 worksheet.autoFilter = 'A1:C1'; 尽管范围字符串是 // 将自动筛选器设置为从 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 Rows// 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');
处理单个单元格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); insert RowsinsertRow(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');
Splice// 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');
重复行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);
定义名称单个单元格(或多个单元格组)可以为它们分配名称。名称可用于公式和数据验证(可能还有更多)。 // 为单元格分配(或获取)名称(将覆盖该单元具有的其他任何名称) 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']); 数据验证单元格可以定义哪些值有效或无效,并提示用户以帮助指导它们。 验证类型可以是以下之一:
对于
// 指定有效值的列表(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' }; 单元格批注属性下表定义了单元格注释已支持的属性。
单元格批注页边距确定单元格批注的页面距设置模式,自动或者自定义模式。 ws.getCell('B1').note.margins = { insetmode: 'custom', inset: [0.25, 0.25, 0.35, 0.35] } 已支持的页边距属性
注意:只有当 单元格批注保护可以使用保护属性来修改单元级别保护。 ws.getCell('B1').note.protection = { locked: 'False', lockText: 'False', }; 已支持的保护属性
单元格批注对象位置属性单元格注释还可以具有属性 'editAs',该属性将控制注释如何锚定到单元格。 它可以具有以下值之一: ws.getCell('B1').note.editAs = 'twoCells'
表格表允许表格内数据的表内操作。 要将表添加到工作表,请定义表模型并调用 // 将表格添加到工作表 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], ], }); 注意:将表格添加到工作表将通过放置表格的标题和行数据来修改工作表。 结果就是表格覆盖的工作表上的所有数据(包括标题和所有的)都将被覆盖。 表格属性下表定义了表格支持的属性。
表格样式属性下表定义了表格中支持的属性样式属性。
表格列属性下表定义了每个表格列中支持的属性。
统计函数下表列出了由列定义的
表格样式主题有效的主题名称遵循以下模式:
Shades(阴影),Number(数字)可以是以下之一:
对于无主题,请使用值 注意:exceljs 尚不支持自定义表格主题。 修改表格表格支持一组操作函数,这些操作函数允许添加或删除数据以及更改某些属性。由于这些操作中的许多操作可能会对工作表产生副作用,因此更改必须在完成后立即提交。 表中的所有索引值均基于零,因此第一行号和第一列号为 添加或删除标题和统计 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 }; 将样式应用于行或列时,它将应用于该行或列中所有当前存在的单元格。另外,创建的任何新单元格都将从其所属的行和列继承其初始样式。 如果单元格的行和列都定义了特定的样式(例如,字体),则该单元格所在行样式比列样式具有更高优先级。但是,如果行和列定义了不同的样式(例如 注意:以上所有属性( 数字格式// 将值显示为“ 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号字体! // 从文件或流中读取工作簿后,共享相似字体的单元格可能引用相同的字体对象
对齐// 将单元格对齐方式设置为左上,中间居中,右下 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' }; 有效的对齐属性值
边框// 在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'}} ] }; 填充模式
有效模式类型
渐变填充
注意事项 使用上面的接口,可能会创建使用XLSX编辑器程序无法实现的渐变填充效果。例如,Excel 仅支持0、45、90 和 135 的角度梯度。类似地,stops 的顺序也可能受到 UI 的限制,其中位置 [0,1] 或[0,0.5,1] 是唯一的选择。请谨慎处理此填充,以确保目标 XLSX 查看器支持该填充。 富文本现在,单个单元格支持RTF文本或单元格格式化。富文本值可以控制文本值内任意数量的子字符串的字体属性。有关支持哪些字体属性的详细信息,请参见字体。 ws.getCell('A1').value = { 'richText': [ {'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'} ] }; expect(ws.getCell('A1').text).to.equal('This is a colorful text with in-cell format'); expect(ws.getCell('A1').type).to.equal(Excel.ValueType.RichText); 单元格保护可以使用保护属性来修改单元级别保护。 ws.getCell('A1').protection = { locked: false, hidden: true, }; 支持的保护属性
条件格式化条件格式化允许工作表根据单元格值或任意公式显示特定的样式,图标等。 条件格式设置规则是在工作表级别添加的,通常会覆盖一系列单元格。 可以将多个规则应用于给定的单元格范围,并且每个规则都将应用自己的样式。 如果多个规则影响给定的单元格,则规则优先级值将确定如果竞争样式冲突,则哪个规则胜出。优先级值较低的规则获胜。如果没有为给定规则指定优先级值,ExcelJS 将按升序分配它们。 注意:目前,仅支持条件格式设置规则的子集。具体来说,只有格式规则不需要 <extLst> 元素内的 XML 呈现。这意味着不支持数据集和三个特定的图标集(3Triangles,3Stars,5Boxes)。 // 根据行和列为偶数或奇数向 A1:E7 添加一个棋盘图案 worksheet.addConditionalFormatting({ ref: 'A1:E7', rules: [ { type: 'expression', formulae: ['MOD(ROW()+COLUMN(),2)=0'], style: {fill: {type: 'pattern', pattern: 'solid', bgColor: {argb: 'FF00FF00'}}}, } ] }) 支持的条件格式设置规则类型
表达式
Cell Is
Cell Is 运算符
Top 10
高于平均值
色阶
图标集
数据条
包含文字
包含文本运算符
时间段
时间段
大纲级别Excel 支持大纲;行或列可以根据用户希望查看的详细程度展开或折叠。 大纲级别可以在列设置中定义: worksheet.columns = [ { header: 'Id', key: 'id', width: 10 }, { header: 'Name', key: 'name', width: 32 }, { header: 'D.O.B.', key: 'DOB', width: 10, outlineLevel: 1 } ]; 或直接在行或列上 worksheet.getColumn(3).outlineLevel = 1; worksheet.getRow(3).outlineLevel = 1; 工作表大纲级别可以在工作表上设置 // 设置列大纲级别 worksheet.properties.outlineLevelCol = 1; // 设置行大纲级别 worksheet.properties.outlineLevelRow = 1; 注意:调整行或列上的大纲级别或工作表上的大纲级别将产生副作用,即还修改受属性更改影响的所有行或列的折叠属性。 例如。: worksheet.properties.outlineLevelCol = 1; worksheet.getColumn(3).outlineLevel = 1; expect(worksheet.getColumn(3).collapsed).to.be.true; worksheet.properties.outlineLevelCol = 2; expect(worksheet.getColumn(3).collapsed).to.be.false; 大纲属性可以在工作表上设置 worksheet.properties.outlineProperties = { summaryBelow: false, summaryRight: false, }; 图片将图像添加到工作表是一个分为两个步骤的过程。首先,通过 注意:从此版本开始,不支持调整或变换图像。 将图片添加到工作簿
// 通过文件名将图像添加到工作簿 const imageId1 = workbook.addImage({ filename: 'path/to/image.jpg', extension: 'jpeg', }); // 通过 buffer 将图像添加到工作簿 const imageId2 = workbook.addImage({ buffer: fs.readFileSync('path/to.image.png'), extension: 'png', }); // 通过 base64 将图像添加到工作簿 const myBase64Image = "data:image/png;base64,iVBORw0KG..."; const imageId2 = workbook.addImage({ base64: myBase64Image, extension: 'png', }); 将图片添加到工作表背景使用 // 设置背景 worksheet.addBackgroundImage(imageId1); 在一定范围内添加图片使用 // 在 B2:D6 上插入图片 worksheet.addImage(imageId2, 'B2:D6'); 使用结构而不是范围字符串,可以部分覆盖单元格。 请注意,为此使用的坐标系基于零,因此 A1 的左上角将为 // 在 B2:D6 的一部分上插入图像 worksheet.addImage(imageId2, { tl: { col: 1.5, row: 1.5 }, br: { col: 3.5, row: 5.5 } }); 单元格区域还可以具有属性
ws.addImage(imageId, { tl: { col: 0.1125, row: 0.4 }, br: { col: 2.101046875, row: 3.4 }, editAs: 'oneCell' }); 将图片添加到单元格您可以将图像添加到单元格,然后以 96dpi 定义其宽度和高度(以像素为单位)。 worksheet.addImage(imageId2, { tl: { col: 0, row: 0 }, ext: { width: 500, height: 200 } }); 添加带有超链接的图片您可以将带有超链接的图像添加到单元格,并在图像范围内定义超链接。 worksheet.addImage(imageId2, { tl: { col: 0, row: 0 }, ext: { width: 500, height: 200 }, hyperlinks: { hyperlink: 'http://www.somewhere.com', tooltip: 'http://www.somewhere.com' } }); 工作表保护可以通过添加密码来保护工作表免受修改。 await worksheet.protect('the-password', options); 工作表保护也可以删除: worksheet.unprotect(); 有关如何修改单个单元格保护的详细信息请查看 单元格保护。 注意: 当 工作表保护选项
文件 I/OXLSX读 XLSX// 从文件读取 const workbook = new Excel.Workbook(); await workbook.xlsx.readFile(filename); // ... 使用 workbook // 从流读取 const workbook = new Excel.Workbook(); await workbook.xlsx.read(stream); // ... 使用 workbook // 从 buffer 加载 const workbook = new Excel.Workbook(); await workbook.xlsx.load(data); // ... 使用 workbook 写 XLSX// 写入文件 const workbook = createAndFillWorkbook(); await workbook.xlsx.writeFile(filename); // 写入流 await workbook.xlsx.write(stream); // 写入 buffer const buffer = await workbook.xlsx.writeBuffer(); CSV读 CSV读取 CSV 文件时支持的选项。
// 从文件读取 const workbook = new Excel.Workbook(); const worksheet = await workbook.csv.readFile(filename); // ... 使用 workbook 或 worksheet // 从流中读取 const workbook = new Excel.Workbook(); const worksheet = await workbook.csv.read(stream); // ... 使用 workbook 或 worksheet // 从带有欧洲日期的文件中读取 const workbook = new Excel.Workbook(); const options = { dateFormats: ['DD/MM/YYYY'] }; const worksheet = await workbook.csv.readFile(filename, options); // ... 使用 workbook 或 worksheet // 从具有自定义值解析的文件中读取 const workbook = new Excel.Workbook(); const options = { map(value, index) { switch(index) { case 0: // 第1列是字符串 return value; case 1: // 第2列是日期 return new Date(value); case 2: // 第3列是公式值的JSON return JSON.parse(value); default: // 其余的是数字 return parseFloat(value); } }, // https://c2fo.io/fast-csv/docs/parsing/options parserOptions: { delimiter: '\t', quote: false, }, }; const worksheet = await workbook.csv.readFile(filename, options); // ... 使用 workbook 或 worksheet CSV 解析器使用 fast-csv 读取CSV文件。传递给上述写入函数的选项中的 使用 npm 模块 dayjs 解析日期。如果未提供
请参阅 dayjs CustomParseFormat 插件,以获取有关如何构造 写 CSV写入 CSV 文件时支持的选项。
// 写入文件 const workbook = createAndFillWorkbook(); await workbook.csv.writeFile(filename); // 写入流 // 请注意,您需要提供 sheetName 或 sheetId 以正确导入到 csv await workbook.csv.write(stream, { sheetName: 'Page name' }); // 使用欧洲日期时间写入文件 const workbook = new Excel.Workbook(); const options = { dateFormat: 'DD/MM/YYYY HH:mm:ss', dateUTC: true, // 呈现日期时使用 utc }; await workbook.csv.writeFile(filename, options); // 使用自定义值格式写入文件 const workbook = new Excel.Workbook(); const options = { map(value, index) { switch(index) { case 0: // 第1列是字符串 return value; case 1: // 第2列是日期 return dayjs(value).format('YYYY-MM-DD'); case 2: // 第3列是一个公式,只写结果 return value.result; default: // 其余的是数字 return value; } }, // https://c2fo.io/fast-csv/docs/formatting/options formatterOptions: { delimiter: '\t', quote: false, }, }; await workbook.csv.writeFile(filename, options); // 写入新 buffer const buffer = await workbook.csv.writeBuffer(); CSV 解析器使用 fast-csv 编写 CSV 文件。传递给上述写入函数的选项中的 日期使用 npm 模块 dayjs 格式化。如果未提供 流式 I/O上面记录的文件 I/O 需要在内存中建立整个工作簿,然后才能写入文件。虽然方便,但是由于所需的内存量,它可能会限制文档的大小。 流写入器(或读取器)在生成工作簿或工作表数据时对其进行处理,然后将其转换为文件形式。通常,这在内存上效率要高得多,因为最终的内存占用量,甚至中间的内存占用量都比文档版本要紧凑得多,尤其是当您考虑到行和单元格对象一旦提交就被销毁时,尤其如此。 流式工作簿和工作表的接口几乎与文档版本相同,但实际存在一些细微差别:
请注意,可以在不提交任何行的情况下构建整个工作簿。提交工作簿后,所有添加的工作表(包括所有未提交的行)将自动提交。但是,在这种情况下,与文档版本相比收效甚微。 流式 XLSX流式 XLSX 写入器流式 XLSX 写入器在 构造函数采用带有以下字段的可选
如果在选项中未指定 // 使用样式和共享字符串构造流式 XLSX 工作簿编写器 const options = { filename: './streamed-workbook.xlsx', useStyles: true, useSharedStrings: true }; const workbook = new Excel.stream.xlsx.WorkbookWriter(options); 通常,流式 XLSX 写入器的接口与上述文档工作簿(和工作表)相同,实际上行,单元格和样式对象是相同的。 但是有一些区别... 构造 如上所示,WorkbookWriter 通常将要求在构造函数中指定输出流或文件。 提交数据 当工作表行准备就绪时,应将其提交,以便可以释放行对象和内容。通常,这将在添加每一行时完成... worksheet.addRow({ id: i, name: theName, etc: someOtherDetail }).commit(); WorksheetWriter 在添加行时不提交行的原因是允许单元格跨行合并: worksheet.mergeCells('A1:B2'); worksheet.getCell('A1').value = 'I am merged'; worksheet.getCell('C1').value = 'I am not'; worksheet.getCell('C2').value = 'Neither am I'; worksheet.getRow(2).commit(); // now rows 1 and two are committed. 每个工作表完成后,还必须提交: // 完成添加数据。 提交工作表 worksheet.commit(); 要完成 XLSX 文档,必须提交工作簿。 如果未提交工作簿中的任何工作表,则将在工作簿提交中自动提交它们。 // 完成 workbook. await workbook.commit(); // ... 流已被写入 流式 XLSX 阅读器流式 XLSX 工作簿阅读器可以在ExcelJS.stream.xlsx命名空间中找到。 构造函数包含必需的输入参数和可选的options参数:
const workbook = new ExcelJS.stream.xlsx.WorkbookReader('./file.xlsx'); for await (const worksheetReader of workbookReader) { for await (const row of worksheetReader) { // ... } } 请注意,由于性能原因, 迭代遍历所有事件工作簿上的事件是 'worksheet'、'shared-strings' 和 'hyperlinks'。 工作表上的事件是 'row' 和 'hyperlinks'. const options = { sharedStrings: 'emit', hyperlinks: 'emit', worksheets: 'emit', }; const workbook = new ExcelJS.stream.xlsx.WorkbookReader('./file.xlsx', options); for await (const {eventType, value} of workbook.parse()) { switch (eventType) { case 'shared-strings': // 值是共享字符串 case 'worksheet': // 值是worksheetReader case 'hyperlinks': // 值是hyperlinksReader } } 可读流我们强烈建议使用异步迭代,但我们也公开了流接口以实现向后兼容性。 const options = { sharedStrings: 'emit', hyperlinks: 'emit', worksheets: 'emit', }; const workbookReader = new ExcelJS.stream.xlsx.WorkbookReader('./file.xlsx', options); workbookReader.read(); workbookReader.on('worksheet', worksheet => { worksheet.on('row', row => { }); }); workbookReader.on('shared-strings', sharedString => { // ... }); workbookReader.on('hyperlinks', hyperlinksReader => { // ... }); workbookReader.on('end', () => { // ... }); workbookReader.on('error', (err) => { // ... }); 浏览器该库的一部分已被隔离,并经过测试可在浏览器环境中使用。 由于工作簿读写器的流式传输性质,因此未包括这些内容。只能使用基于文档的工作簿(有关详细信息,请参见 创建工作簿)。 例如,在浏览器中使用 ExcelJS 的代码可查看 github 中的 spec / browser 文件夹。 预捆绑以下文件已预先捆绑在一起,并包含在 dist 文件夹中。
值类型支持以下值类型。 Null 值Enum: 空值表示没有值,通常在写入文件时将不存储(合并的单元格除外)。可用于从单元格中删除该值。例如: worksheet.getCell('A1').value = null; 合并单元格Enum: 合并单元格是其值绑定到另一个“主”单元格的单元格。分配给合并单元将导致修改单元格。 数字值Enum: 一个数字值。 例如: worksheet.getCell('A1').value = 5; worksheet.getCell('A2').value = 3.14159; 字符串值Enum: 一个简单的文本字符串。 例如: worksheet.getCell('A1').value = 'Hello, World!'; 日期值Enum: 日期值,由 Javascript Date 类型表示。 例如: worksheet.getCell('A1').value = new Date(2017, 2, 15); 超链接值Enum: 具有文本和链接值的 URL。 例如: // 链接到网络 worksheet.getCell('A1').value = { text: 'www.mylink.com', hyperlink: 'http://www.mylink.com', tooltip: 'www.mylink.com' }; // 内部链接 worksheet.getCell('A1').value = { text: 'Sheet2', hyperlink: '#\'Sheet2\'!A1' }; 公式值Enum: 一个 Excel 公式,用于即时计算值。请注意,虽然单元格类型将为“公式”,但该单元格可能具有一个有效类型值,该值将从结果值中得出。 请注意,ExcelJS 无法处理公式以生成结果,必须提供该公式。 例如: worksheet.getCell('A3').value = { formula: 'A1+A2', result: 7 }; 单元格还支持便捷的获取器,以访问公式和结果: worksheet.getCell('A3').formula === 'A1+A2'; worksheet.getCell('A3').result === 7; 共享公式共享的公式通过减少工作表 xml 中文本的重复来增强 xlsx 文档的压缩。范围中左上角的单元格是指定的母版,它将保留该范围内的所有其他单元格都将引用的公式。然后,其他“从属”单元格可以引用此主单元格,而不必再次重新定义整个公式。请注意,主公式将以常用的 Excel 方式转换为从属单元格,以便对其他单元格的引用将根据从属单元相对于主单元的偏移量向右下移。例如:如果主单元格A2具有引用A1的公式,则如果单元格B2共享A2的公式,则它将引用B1。 可以将主公式与该范围内的从属单元格一起分配给该单元格 worksheet.getCell('A2').value = { formula: 'A1', result: 10, shareType: 'shared', ref: 'A2:B3' }; 可以使用新的值形式将共享公式分配给单元格: worksheet.getCell('B2').value = { sharedFormula: 'A2', result: 10 }; 这指定单元格B2是将从A2中的公式派生的公式,其结果为10。 公式便捷获取器会将A2中的公式转换为B2中应具有的公式: expect(worksheet.getCell('B2').formula).to.equal('B1'); 可以使用 // 将 A1 设置为起始编号 worksheet.getCell('A1').value = 1; // 从 A1 开始以递增计数将 A2 填充到 A10 worksheet.fillFormula('A2:A10', 'A1+1', [2,3,4,5,6,7,8,9,10]);
// 从A1开始以递增计数将 A2 填充到 A100 worksheet.fillFormula('A2:A100', 'A1+1', (row, col) => row); 公式类型要区分真正的和转换后的公式单元格,请使用 FormulaType getter: worksheet.getCell('A3').formulaType === Enums.FormulaType.Master; worksheet.getCell('B3').formulaType === Enums.FormulaType.Shared; 公式类型具有以下值:
数组公式在 Excel 中表示共享公式的一种新方法是数组公式。以这种形式,主单元格是唯一包含与公式有关的任何信息的单元格。它包含 shareType 'array' 以及适用于其的单元格范围以及将要复制的公式。其余单元格是具有常规值的常规单元格。 注意:数组公式不会以共享公式的方式转换。因此,如果主单元A2引用A1,则从单元B2也将引用A1。 例如: // 将数组公式分配给 A2:B3 worksheet.getCell('A2').value = { formula: 'A1', result: 10, shareType: 'array', ref: 'A2:B3' }; // 可能没有必要填写工作表中的其余值
// 用数组公式 "A1" 填充 A2:B3 worksheet.fillFormula('A2:B3', 'A1', [1,1,1,1], 'array'); 富文本值Enum: 样式丰富的文本。 例如: worksheet.getCell('A1').value = { richText: [ { text: 'This is '}, {font: {italic: true}, text: 'italic'}, ] }; 布尔值Enum: 例如: worksheet.getCell('A1').value = true; worksheet.getCell('A2').value = false; 错误值Enum: 例如: worksheet.getCell('A1').value = { error: '#N/A' }; worksheet.getCell('A2').value = { error: '#VALUE!' }; 当前有效的错误文本值为:
接口变化我们会尽一切努力创建一个良好的,一致的接口,该接口不会在版本之间不兼容,但令人遗憾的是,为了实现更大的利益,有时需要进行一些更改。 0.1.0Worksheet.eachRow在 Worksheet.getRow此函数已从返回稀疏的单元格数组更改为返回 仍可通过 0.1.1cell.model
0.2.44从 Bluebird 切换到 Node 原生 Promise 的函数返回的 Promise 如果依赖 Bluebird 的额外功能,则可能会破坏调用代码。 为了减少这种情况的出现,在0.3.0中添加了以下两个更改:
配置ExcelJS现在支持对 Promise 库的依赖项注入。您可以通过在模块中包含以下代码来还原 Bluebird Promise。 ExcelJS.config.setValue('promise', require('bluebird')); 请注意:我已经使用 bluebird 专门测试了 ExcelJS(直到最近,这是它使用的库)。根据我所做的测试,它不适用于 Q。 注意事项Dist 文件夹在发布此模块之前,先对源代码进行编译和其他处理,然后再将它们放置在 dist/ 文件夹中。该自述文件标识两个文件-浏览器捆绑和压缩版本。除了在 package.json 中指定为 已知的问题使用 Puppeteer 进行测试该 lib 中包含的测试套件包括一个在无头浏览器中执行的小脚本,以验证捆绑的软件包。 在撰写本文时,其表现出该测试在 Windows Linux 子系统中不能很好地进行。 因此,可以通过存在名为 .disable-test-browser 的文件来禁用浏览器测试。 sudo apt-get install libfontconfig 拼接与合并如果任何 发布历史
该文章在 2023/3/27 15:29:52 编辑过 |
关键字查询
相关文章
正在查询... |