UNPKG

exceljs

Version:

Excel Workbook Manager - Read and Write xlsx and csv Files.

1,722 lines (1,347 loc) 173 kB
# ExcelJS [![Build status](https://github.com/exceljs/exceljs/workflows/ExcelJS/badge.svg)](https://github.com/exceljs/exceljs/actions?query=workflow%3AExcelJS) [![Code Quality: Javascript](https://img.shields.io/lgtm/grade/javascript/g/exceljs/exceljs.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/exceljs/exceljs/context:javascript) [![Total Alerts](https://img.shields.io/lgtm/alerts/g/exceljs/exceljs.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/exceljs/exceljs/alerts) 读取,操作并写入电子表格数据和样式到 XLSX 和 JSON 文件。 一个 Excel 电子表格文件逆向工程项目。 # 安装 ```shell npm install exceljs ``` # 新的功能! <ul> <li> 重大版本更改-主要的ExcelJS接口已从基于流的API迁移到异步迭代器,从而使代码更简洁。 虽然技术上是一个突破性的变化,但大多数API都没有变化,详细信息请参见<a href="https://github.com/exceljs/exceljs/blob/master/UPGRADE-4.0.md">UPGRADE-4.0.md</a>。 </li> <li> 此升级来自以下合并: <ul> <li><a href="https://github.com/exceljs/exceljs/pull/1135">[MAJOR VERSION] Async iterators #1135</a></li> <li><a href="https://github.com/exceljs/exceljs/pull/1142">[MAJOR VERSION] Move node v8 support to ES5 imports #1142</a></li> </ul> 团队做了很多工作-特别是 <a href="https://github.com/alubbe">Andreas Lubbe</a> and <a href="https://github.com/Siemienik">Siemienik Paweł</a>. </li> </ul> # 贡献 欢迎贡献!这可以帮助我了解大家需要一些什么功能,或者哪些 bugs 造成了极大的麻烦。 我只有一个请求;如果您提交对错误修复的请求(PR),请添加一个能够解决问题的单元测试或集成测试(在 *spec* 文件夹中)。 即使只是测试失败的请求(PR)也可以 - 我可以分析测试的过程并以此修复代码。 注意:请尽可能避免在请求(PR)中修改软件包版本。 版本一般在发布时会进行更新,任何版本更改很可能导致合并冲突。 明确地说,添加到该库的所有贡献都将包含在该库的 MIT 许可证中。 # 目录 <ul> <li><a href="#导入">导入</a></li> <li> <a href="#接口">接口</a> <ul> <li><a href="#创建工作簿">创建工作簿</a></li> <li><a href="#设置工作簿属性">设置工作簿属性</a></li> <li><a href="#工作簿视图">工作簿视图</a></li> <li><a href="#添加工作表">添加工作表</a></li> <li><a href="#删除工作表">删除工作表</a></li> <li><a href="#访问工作表">访问工作表</a></li> <li><a href="#工作表状态">工作表状态</a></li> <li><a href="#工作表属性">工作表属性</a></li> <li><a href="#页面设置">页面设置</a></li> <li><a href="#页眉和页脚">页眉和页脚</a></li> <li> <a href="#工作表视图">工作表视图</a> <ul> <li><a href="#冻结视图">冻结视图</a></li> <li><a href="#拆分视图">拆分视图</a></li> </ul> </li> <li><a href="#自动筛选器">自动筛选器</a></li> <li><a href="#列">列</a></li> <li><a href="#行">行</a> <ul> <li><a href="#add-rows">Add Rows</a></li> <li><a href="#处理单个单元格">处理单个单元格</a></li> <li><a href="#合并单元格">合并单元格</a></li> <li><a href="#insert-rows">Insert Rows</a></li> <li><a href="#splice">Splice</a></li> <li><a href="#重复行">重复行</a></li> </ul> </li> <li><a href="#定义名称">定义名称</a></li> <li><a href="#数据验证">数据验证</a></li> <li><a href="#单元格注释">单元格注释</a></li> <li><a href="#表格">表格</a></li> <li><a href="#样式">样式</a> <ul> <li><a href="#数字格式">数字格式</a></li> <li><a href="#字体">字体</a></li> <li><a href="#对齐">对齐</a></li> <li><a href="#边框">边框</a></li> <li><a href="#填充">填充</a></li> <li><a href="#富文本">富文本</a></li> </ul> </li> <li><a href="#条件格式化">条件格式化</a></li> <li><a href="#大纲级别">大纲级别</a></li> <li><a href="#图片">图片</a></li> <li><a href="#工作表保护">工作表保护</a></li> <li><a href="#文件-io">文件 I/O</a> <ul> <li><a href="#xlsx">XLSX</a> <ul> <li><a href="#读-xlsx">读 XLSX</a></li> <li><a href="#写-xlsx">写 XLSX</a></li> </ul> </li> <li><a href="#csv">CSV</a> <ul> <li><a href="#读-csv">读 CSV</a></li> <li><a href="#写-csv">写 CSV</a></li> </ul> </li> <li><a href="#流式-io">流式 I/O</a> <ul> <li><a href="#流式-xlsx">流式 XLSX</a></li> </ul> </li> </ul> </li> </ul> </li> <li><a href="#浏览器">浏览器</a></li> <li> <a href="#值类型">值类型</a> <ul> <li><a href="#null-值">Null 值</a></li> <li><a href="#合并单元格">合并单元格</a></li> <li><a href="#数字值">数字值</a></li> <li><a href="#字符串值">字符串值</a></li> <li><a href="#日期值">日期值</a></li> <li><a href="#超链接值">超链接值</a></li> <li> <a href="#公式值">公式值</a> <ul> <li><a href="#共享公式">共享公式</a></li> <li><a href="#公式类型">公式类型</a></li> <li><a href="#数组公式">数组公式</a></li> </ul> </li> <li><a href="#富文本值">富文本值</a></li> <li><a href="#布尔值">布尔值</a></li> <li><a href="#错误值">错误值</a></li> </ul> </li> <li><a href="#配置">配置</a></li> <li><a href="#已知的问题">已知的问题</a></li> <li><a href="#发布历史">发布历史</a></li> </ul> # 导入[⬆](#目录)<!-- Link generated with jump2header --> ```javascript const ExcelJS = require('exceljs'); ``` ## ES5 导入[⬆](#目录)<!-- Link generated with jump2header --> 要使用 ES5 编译代码,请使用 *dist/es5* 路径。 ```javascript const ExcelJS = require('exceljs/dist/es5'); ``` **注意:**ES5 版本对许多 polyfill 都具有隐式依赖,而 exceljs 不再明确添加。 您需要在依赖项中添加 `core-js` 和 `regenerator-runtime`,并在导入 `exceljs` 之前在代码中包含以下引用: ```javascript // 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 模式。 例如, ```js 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; } ``` ## 浏览器端[⬆](#目录)<!-- Link generated with jump2header --> ExcelJS 在 *dist/* 文件夹内发布了两个支持浏览器的包: 一个是隐式依赖 `core-js` polyfills 的... ```html <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.26.0/polyfill.js"></script> <script src="exceljs.js"></script> ``` 另一个则没有... ```html <script src="--your-project's-pollyfills-here--"></script> <script src="exceljs.bare.js"></script> ``` # 接口[⬆](#目录)<!-- Link generated with jump2header --> ## 创建工作簿[⬆](#目录)<!-- Link generated with jump2header --> ```javascript const workbook = new Excel.Workbook(); ``` ## 设置工作簿属性[⬆](#目录)<!-- Link generated with jump2header --> ```javascript workbook.creator = 'Me'; workbook.lastModifiedBy = 'Her'; workbook.created = new Date(1985, 8, 30); workbook.modified = new Date(); workbook.lastPrinted = new Date(2016, 9, 27); ``` ```javascript // 将工作簿日期设置为 1904 年日期系统 workbook.properties.date1904 = true; ``` ## 设置计算属性[⬆](#目录)<!-- Link generated with jump2header --> ```javascript // 在加载时强制工作簿计算属性 workbook.calcProperties.fullCalcOnLoad = true; ``` ## 工作簿视图[⬆](#目录)<!-- Link generated with jump2header --> 工作簿视图控制在查看工作簿时 Excel 将打开多少个单独的窗口。 ```javascript workbook.views = [ { x: 0, y: 0, width: 10000, height: 20000, firstSheet: 0, activeTab: 1, visibility: 'visible' } ] ``` ## 添加工作表[⬆](#目录)<!-- Link generated with jump2header --> ```javascript const sheet = workbook.addWorksheet('My Sheet'); ``` 使用 `addWorksheet` 函数的第二个参数来指定工作表的选项。 示例: ```javascript // 创建带有红色标签颜色的工作表 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}]}); ``` ## 删除工作表[⬆](#目录)<!-- Link generated with jump2header --> 使用工作表的 `id` 从工作簿中删除工作表。 示例: ```javascript // 创建工作表 const sheet = workbook.addWorksheet('My Sheet'); // 使用工作表 id 删除工作表 workbook.removeWorksheet(sheet.id) ``` ## 访问工作表[⬆](#目录)<!-- Link generated with jump2header --> ```javascript // 遍历所有工作表 // 注意: workbook.worksheets.forEach 仍然是可以正常运行的, 但是以下的方式更好 workbook.eachSheet(function(worksheet, sheetId) { // ... }); // 按 name 提取工作表 const worksheet = workbook.getWorksheet('My Sheet'); // 按 id 提取工作表 const worksheet = workbook.getWorksheet(1); ``` ## 工作表状态[⬆](#目录)<!-- Link generated with jump2header --> ```javascript // 使工作表可见 worksheet.state = 'visible'; // 隐藏工作表 worksheet.state = 'hidden'; // 从“隐藏/取消隐藏”对话框中隐藏工作表 worksheet.state = 'veryHidden'; ``` ## 工作表属性[⬆](#目录)<!-- Link generated with jump2header --> 工作表支持属性存储,以允许控制工作表的某些功能。 ```javascript // 创建具有属性的新工作表 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 | ### 工作表尺寸[⬆](#目录)<!-- Link generated with jump2header --> 一些新的尺寸属性已添加到工作表中... | 属性名 | 描述 | | ----------------- | ------------------------------------------------------------ | | rowCount | 文档的总行数。 等于具有值的最后一行的行号。 | | actualRowCount | 具有值的行数的计数。 如果中间文档行为空,则该行将不包括在计数中。 | | columnCount | 文档的总列数。 等于所有行的最大单元数。 | | actualColumnCount | 具有值的列数的计数。 | ## 页面设置[⬆](#目录)<!-- Link generated with jump2header --> 所有可能影响工作表打印的属性都保存在工作表上的 `pageSetup` 对象中。 ```javascript // 使用 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'; ``` **支持的页面设置配置项** | 属性名 | 默认值 | 描述 | | --------------------- | ------------- | ----------- | | 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 | | 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 | ## 页眉和页脚[⬆](#目录)<!-- Link generated with jump2header --> 这是添加页眉和页脚的方法。 添加的内容主要是文本,例如时间,简介,文件信息等,您可以设置文本的样式。 此外,您可以为首页和偶数页设置不同的文本。 注意:目前不支持图片。 ```javascript // 创建一个带有页眉和页脚的工作表 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 | ## 工作表视图[⬆](#目录)<!-- Link generated with jump2header --> 现在,工作表支持视图列表,这些视图控制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` 视图不兼容 | ### 冻结视图[⬆](#目录)<!-- Link generated with jump2header --> 冻结视图支持以下额外属性: | 属性名 | 默认值 | 描述 | | ----------------- | --------- | ----------- | | xSplit | 0 | 冻结多少列。要仅冻结行,请将其设置为 `0` 或 `undefined` | | ySplit | 0 | 冻结多少行。要仅冻结列,请将其设置为 `0` 或 `undefined` | | topLeftCell | special | 哪个单元格将在右下窗格中的左上角。注意:不能是冻结单元格。默认为第一个未冻结的单元格 | ```javascript worksheet.views = [ {state: 'frozen', xSplit: 2, ySplit: 3, topLeftCell: 'G10', activeCell: 'A1'} ]; ``` ### 拆分视图[⬆](#目录)<!-- Link generated with jump2header --> 拆分视图支持以下额外属性: | 属性名 | 默认值 | 描述 | | ----------------- | --------- | ----------- | | xSplit | 0 | 从左侧多少个点起,以放置拆分器。要垂直拆分,请将其设置为 `0` 或 `undefined` | | ySplit | 0 | 从顶部多少个点起,放置拆分器。要水平拆分,请将其设置为 `0` 或 `undefined` | | topLeftCell | `undefined` | 哪个单元格将在右下窗格中的左上角。 | | activePane | `undefined` | 哪个窗格将处于活动状态-`topLeft`,`topRight`,`bottomLeft` 和 `bottomRight` 中的一个 | ```javascript worksheet.views = [ {state: 'split', xSplit: 2000, ySplit: 3000, topLeftCell: 'G10', activeCell: 'A1'} ]; ``` ## 自动筛选器[⬆](#目录)<!-- Link generated with jump2header --> 可以对工作表应用自动筛选器。 ```javascript worksheet.autoFilter = 'A1:C1'; ``` 尽管范围字符串是 `autoFilter` 的标准形式,但工作表还将支持以下值: ```javascript // 将自动筛选器设置为从 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 } } ``` ## 列[⬆](#目录)<!-- Link generated with jump2header --> ```javascript // 添加列标题并定义列键和宽度 // 注意:这些列结构仅是构建工作簿的方便之处,除了列宽之外,它们不会完全保留。 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); ``` ## 行[⬆](#目录)<!-- Link generated with jump2header --> ```javascript // 获取一个行对象。如果尚不存在,则将返回一个新的空对象 const row = worksheet.getRow(5); // 获取工作表中的最后一个可编辑行(如果没有,则为 `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[⬆](#contents)<!-- Link generated with jump2header --> ```javascript // 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 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()} ]; worksheet.addRows(rows); // Add an array of rows with inherited style // These new rows will have same styles as last row worksheet.addRows(rows, 'i'); ``` | Parameter | Description | Default Value | | -------------- | ----------------- | -------- | | value/s | The new row/s values | | | styleOption | 'i' for inherit from row above, 'n' for none | *'n'* | ## 处理单个单元格[⬆](#目录)<!-- Link generated with jump2header --> ```javascript 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>'; ``` ## 合并单元格[⬆](#目录)<!-- Link generated with jump2header --> ```javascript // 合并一系列单元格 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 Rows[⬆](#目录)<!-- Link generated with jump2header --> ```javascript insertRow(pos, value, styleOption = 'n') insertRows(pos, values, styleOption = '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(); worksheet.insertRow(1, rowValues); // Insert a row, with inherited style // This new row will have same style as row on top of it worksheet.insertRow(1, rowValues, 'i'); // Insert a row, keeping original style // This new row will have same style as it was previously 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()} ]; 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 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 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 | | | styleOption | 'i' for inherit from row above, 'o' for original style, 'n' for none | *'n'* | ## Splice[⬆](#contents)<!-- Link generated with jump2header --> ```javascript // 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 | | ## 重复行[⬆](#目录)<!-- Link generated with jump2header --> ```javascript 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` | ## 定义名称[⬆](#目录)<!-- Link generated with jump2header --> 单个单元格(或多个单元格组)可以为它们分配名称。名称可用于公式和数据验证(可能还有更多)。 ```javascript // 为单元格分配(或获取)名称(将覆盖该单元具有的其他任何名称) 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']); ``` ## 数据验证[⬆](#目录)<!-- Link generated with jump2header --> 单元格可以定义哪些值有效或无效,并提示用户以帮助指导它们。 验证类型可以是以下之一: | 类型 | 描述 | | ---------- | ----------- | | list | 定义一组离散的有效值。Excel 将在下拉菜单中提供这些内容,以便于输入 | | whole | 该值必须是整数 | | decimal | 该值必须是十进制数 | | textLength | 该值可以是文本,但长度是受控的 | | custom | 自定义公式控制有效值 | 对于 `list` 或 `custom` 以外的其他类型,以下运算符会影响验证: | 运算符 | 描述 | | -------------------- | ----------- | | between | 值必须介于公式结果之间 | | notBetween | 值不能介于公式结果之间 | | equal | 值必须等于公式结果 | | notEqual | 值不能等于公式结果 | | greaterThan | 值必须大于公式结果 | | lessThan | 值必须小于公式结果 | | greaterThanOrEqual | 值必须大于或等于公式结果 | | lessThanOrEqual | 值必须小于或等于公式结果 | ```javascript // 指定有效值的列表(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)] }; ``` ## 单元格注释[⬆](#目录)<!-- Link generated with jump2header --> 将旧样式的注释添加到单元格 ```javascript // 纯文字笔记 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' }; ``` ### 单元格批注属性[⬆](#目录)<!-- Link generated with jump2header --> 下表定义了单元格注释已支持的属性。 | Field | Required | Default Value | Description | | -------- | -------- | ------------- | ----------- | | texts | Y | | 评论文字 | | margins | N | {} | 确定自动或自定义设置单元格注释的边距值 | | protection | N | {} | 可以使用保护属性来指定对象和对象文本的锁定状态 | | editAs | N | 'absolute' | 可以使用'editAs'属性来指定注释如何锚定到单元格 | ### 单元格批注页边距[⬆](#目录)<!-- Link generated with jump2header --> 确定单元格批注的页面距设置模式,自动或者自定义模式。 ```javascript ws.getCell('B1').note.margins = { insetmode: 'custom', inset: [0.25, 0.25, 0.35, 0.35] } ``` ### 已支持的页边距属性[⬆](#目录)<!-- Link generated with jump2header --> | Property | Required | Default Value | Description | | -------- | -------- | ------------- | ----------- | | insetmode | N | 'auto' | 确定是否自动设置注释边距,并且值是'auto' 或者 'custom' | | inset | N | [0.13, 0.13, 0.25, 0.25] | 批注页边距的值,单位是厘米, 方向是左-上-右-下 | 注意:只有当 ```insetmode```的值设置为'custom'时,```inset```的设置才生效。 ### 单元格批注保护[⬆](#目录)<!-- Link generated with jump2header --> 可以使用保护属性来修改单元级别保护。 ```javascript ws.getCell('B1').note.protection = { locked: 'False', lockText: 'False', }; ``` ### 已支持的保护属性[⬆](#目录)<!-- Link generated with jump2header --> | Property | Required | Default Value | Description | | -------- | -------- | ------------- | ----------- | | locked | N | 'True' | 此元素指定在保护工作表时对象已锁定 | | lockText | N | 'True' | 该元素指定对象的文本已锁定 | ### 单元格批注对象位置属性[⬆](#目录)<!-- Link generated with jump2header --> 单元格注释还可以具有属性 'editAs',该属性将控制注释如何锚定到单元格。 它可以具有以下值之一: ```javascript ws.getCell('B1').note.editAs = 'twoCells' ``` | Value | Description | | --------- | ----------- | | twoCells | 它指定注释的大小、位置随单元格而变 | | oneCells | 它指定注释的大小固定,位置随单元格而变 | | absolute | 这是默认值,它指定注释的大小、位置均固定 | ## 表格[⬆](#目录)<!-- Link generated with jump2header --> 表允许表格内数据的表内操作。 要将表添加到工作表,请定义表模型并调用 `addTable`: ```javascript // 将表格添加到工作表 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], ], }); ``` 注意:将表格添加到工作表将通过放置表格的标题和行数据来修改工作表。 结果就是表格覆盖的工作表上的所有数据(包括标题和所有的)都将被覆盖。 ### 表格属性[⬆](#目录)<!-- Link generated with jump2header --> 下表定义了表格支持的属性。 | 表属性 | 描述 | 是否需要 | 默认值 | | -------------- | ----------------- | -------- | ------------- | | name | 表格名称 | Y | | | displayName | 表格的显示名称 | N | `name` | | ref | 表格的左上方单元格 | Y | | | headerRow | 在表格顶部显示标题 | N | true | | totalsRow | 在表格底部显示总计 | N | `false` | | style | 额外的样式属性 | N | {} | | columns | 列定义 | Y | | | rows | 数据行 | Y | | ### 表格样式属性[⬆](#目录)<!-- Link generated with jump2header --> 下表定义了表格中支持的属性样式属性。 | 样式属性 | 描述 | 是否需要 | 默认值 | | ------------------ | ----------------- | -------- | ------------- | | theme | 桌子的颜色主题 | N | `'TableStyleMedium2'` | | showFirstColumn | 突出显示第一列(粗体) | N | `false` | | showLastColumn | 突出显示最后一列(粗体) | N | `false` | | showRowStripes | 用交替的背景色显示行 | N | `false` | | showColumnStripes | 用交替的背景色显示列 | N | `false` | ### 表格列属性[⬆](#目录)<!-- Link generated with jump2header --> 下表定义了每个表格列中支持的属性。 | 列属性 | 描述 | 是否需要 | 默认值 | | ------------------ | ----------------- | -------- | ------------- | | name | 列名,也用在标题中 | Y | | | filterButton | 切换标题中的过滤器控件 | N | false | | totalsRowLabel | 用于描述统计行的标签(第一列) | N | `'Total'` | | totalsRowFunction | 统计函数名称 | N | `'none'` | | totalsRowFormula | 自定义函数的可选公式 | N | | ### 统计函数[⬆](#目录)<!-- Link generated with jump2header --> 下表列出了由列定义的 `totalsRowFunction` 属性的有效值。如果使用 `'custom'` 以外的任何值,则无需包括关联的公式,因为该公式将被表格插入。 | 统计函数 | 描述 | | ------------------ | ----------------- | | none | 此列没有统计函数 | | average | 计算列的平均值 | | countNums | 统计数字条目数 | | count | 条目数 | | max | 此列中的最大值 | | min | 此列中的最小值 | | stdDev | 该列的标准偏差 | | var | 此列的方差 | | sum | 此列的条目总数 | | custom | 自定义公式。 需要关联的 `totalsRowFormula` 值。 | ### 表格样式主题[⬆](#目录)<!-- Link generated with jump2header --> 有效的主题名称遵循以下模式: * "TableStyle[Shade][Number]" Shades(阴影),Number(数字)可以是以下之一: * Light, 1-21 * Medium, 1-28 * Dark, 1-11 对于无主题,请使用值 `null`。 注意:exceljs 尚不支持自定义表格主题。 ### 修改表格[⬆](#目录)<!-- Link generated with jump2header --> 表格支持一组操作函数,这些操作函数允许添加或删除数据以及更改某些属性。由于这些操作中的许多操作可能会对工作表产生副作用,因此更改必须在完成后立即提交。 表中的所有索引值均基于零,因此第一行号和第一列号为 `0`。 **添加或删除标题和统计** ```javascript const table = ws.getTable('MyTable'); // 打开标题行 table.headerRow = true; // 关闭统计行 table.totalsRow = false; // 将表更改提交到工作表中 table.commit(); ``` **重定位表** ```javascript const table = ws.getTable('MyTable'); // 表格左上移至 D4 table.ref = 'D4'; // 将表更改提交到工作表中 table.commit(); ``` **添加和删除行** ```javascript 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(); ``` **添加和删除列** ```javascript 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(); ``` **更改列属性** ```javascript 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(); ``` ## 样式[⬆](#目录)<!-- Link generated with jump2header --> 单元格,行和列均支持一组丰富的样式和格式,这些样式和格式会影响单元格的显示方式。 通过分配以下属性来设置样式: * <a href="#数字格式">numFmt</a> * <a href="#字体">font</a> * <a href="#对齐">alignment</a> * <a href="#边框">border</a> * <a href="#填充">fill</a> ```javascript // 为单元格分配样式 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对象的数量来优先考虑性能。如果希望样式对象是独立的,则需要先对其进行克隆,然后再分配它们。同样,默认情况下,如果电子表格实体共享相似的样式,则从文件(或流)中读取文档时,它们也将引用相同的样式对象。 ### 数字格式[⬆](#目录)<!-- Link generated with jump2header --> ```javascript // 将值显示为“ 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%'; ``` ### 字体 ```javascript // 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 | 字体 <u>下划线</u> 样式 | true, false, 'none', 'single', 'double', 'singleAccounting', 'doubleAccounting' | | strike | 字体 <strike>删除线</strike> | true, false | | outline | 字体轮廓 | true, false | | vertAlign | 垂直对齐 | 'superscript', 'subscript' ### 对齐[⬆](#目录)<!-- Link generated with jump2header --> ```javascript // 将单元格对齐方式设置为左上,中间居中,右下 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 | | | | | | | ### 边框[⬆](#目录)<!-- Link generated with jump2header --> ```javascript // 在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'}} }; ``` **有效边框样式** * thin * dotted * dashDot * hair * dashDotDot * slantDashDot * mediumDashed * mediumDashDotDot * mediumDashDot * medium * double * thick ### 填充[⬆](#目录)<!-- Link generated with jump2header --> ```javascript // 用红色深色垂直条纹填充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'}} ] }; ``` #### 填充模式[⬆](#目录)<!-- Link generated with jump2header --> | 属性 | 是否需要 | 描述 | | -------- | -------- | ----------- | | type | Y | 值: `'pattern'`<br/>指定此填充使用模式 | | pattern | Y | 指定模式类型 (查看下面 <a href="#有效模式类型">有效模式类型</a> ) | | fgColor | N | 指定图案前景色。默认为黑色。 | | bgColor | N | 指定图案背景色。默认为白色。 | **有效模式类型** * none * solid * darkGray * mediumGray * lightGray * gray125 * gray0625 * darkHorizontal * darkVertical * darkDown * darkUp * darkGrid * darkTrellis * lightHorizontal * lightVertical * lightDown * lightUp * lightGrid * lightTrellis #### 渐变填充[⬆](#目录)<!-- Link generated with jump2header --> | 属性 | 是否需要 | 描述 | | -------- | -------- | ----------- | | type | Y | 值: `'gradient'`<br/>指定此填充使用渐变 | | 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 查看器支持该填充。 ### 富文本[⬆](#目录)<!-- Link generated with jump2header --> 现在,单个单元格支持RTF文本或单元格格式化。富文本值可以控制文本值内任意数量的子字符串的字体属性。有关支持哪些字体属性的详细信息,请参见<a href="font">字体</a>。 ```javascript 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); ``` ### 单元格保护[⬆](#目录)<!-- Link generated with jump2header --> 可以使用保护属性来修改单元级别保护。 ```javascript ws.getCell('A1').protection = { locked: false, hidden: true, }; ``` **支持的保护属性** | 属性 | 默认值 | 描述 | | -------- | ------- | ----------- | | locked | `true` | 指定在工作表受保护的情况下是否将单元格锁定。 | | hidden | `false` | 指定如果工作表受保护,则单元格的公式是否可见。 | ## 条件格式化[⬆](#目录)<!-- Link generated with jump2header --> 条件格式化允许工作表根据单元格值或任意公式显示特定的样式,图标等。 条件格式设置规则是在工作表级别添加的,通常会覆盖一系列单元格。 可以将多个规则应用于给定的单元格范围,并且每个规则都将应用自己的样式。 如果多个规则影响给定的单元格,则规则优先级值将确定如果竞争样式冲突,则哪个规则胜出。优先级值较低的规则获胜。如果没有为给定规则指定优先级值,ExcelJS 将按升序分配它们。 注意:目前,仅支持条件格式设置规则的子集。具体来说,只有格式规则不需要 &lt;extLst&gt 元素内的 XML 呈现。这意味着不支持数据集和三个特定的图标集(3Triangles,3Stars,5Boxes)。 ```javascript // 根据行和列为偶数或奇数向 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'}}}, } ] }) ``` **支持的条件格式设置规则类型** | 类型 | 描述 | | ------------ | ----------- | | expression | 任何自定义功能均可用于激活规则。 | | cellIs | 使用指定的运算符将单元格值与提供的公式进行比较 | | top10 | 将格式化应用于值在顶部(或底部)范围内的单元格 | | aboveAverage | 将格式化应用于值高于(或低于)平均值的单元格 | | colorScale | 根据其值在范围内的位置将彩色背景应用于单元格 | | iconSet | 根据值将一系列图标之一添加到单元格 | | containsText | 根据单元格是否为特定文本来应用格式 | | timePeriod | 根据单元格日期时间值是否在指定范围内应用格式 | ### 表达式[⬆](#目录)<!-- Link generated with jump2header --> | 属性 | 可选 | 默认值 | 描述 | | -------- | -------- | ------- | ----------- | | type | | | `'expression'` | | priority | Y | &lt;auto&gt; | 确定样式的优先顺序 | | formulae | | | 1个包含真/假值的公式字符串数组。要引用单元格值,请使用左上角的单元格地址 | | style | | | 公式返回 `true` 时要应用的样式结构 | ### Cell Is[⬆](#目录)<!-- Link generated with jump2header --> | 属性 | 可选 | 默认值 | 描述 | | -------- | -------- | ------- | ----------- | | type | | | `'cellIs'` | | priority | Y | &lt;auto&gt; | 确定样式的优先顺序 | | operator | | | 如何将单元格值与公式结果进行比较 | | formulae | | | 1个公式字符串数组,返回要与每个单元格进行比较的值 | | style | |