ExcelJS
安裝
npm install exceljs
新的功能!
- Merged fix: styles rendering in case when “numFmt” is present in conditional formatting rules (resolves #1814) #1815.
Many thanks to @andreykrupskii for this contribution! - Merged inlineStr cell type support #1575 #1576.
Many thanks to @drdmitry for this contribution! - Merged Fix parsing of boolean attributes #1849.
Many thanks to @bno1 for this contribution! - Merged add optional custom auto-filter to table #1670.
Many thanks to @thambley for this contribution! - Merged Deep copy inherited style #1850.
Many thanks to @ikzhr for this contribution! - Merged Upgrade actions/cache and actions/setup-node #1846.
Many thanks to @cclauss for this contribution! - Merged Check object keys in isEqual #1831.
Many thanks to @bno1 for this contribution! - Merged Add v17 to testing workflow #1856.
Many thanks to @Siemienik for this contribution! - Merged Upgrade jszip to its latest version to date. This version does not have any vulnerability found by Snyk so far #1895.
Many thanks to @ValerioSevilla for this contribution! - Merged Update README.md #1677.
Many thanks to @xjrcode for this contribution! - Merged (docs): set prototype of RegExp correctly. #1700.
Many thanks to @joeldenning for this contribution! - Merged Added timeouts to github actions #1733.
Many thanks to @alexbjorlig for this contribution! - Merged fix issue 1676 #1701.
Many thanks to @skypesky for this contribution! - Merged ExcelJS/ExcelJS#2237 : Update CI Tests, Drop support for Node v8 #2242.
Many thanks to @Siemienik for this contribution! - Merged Fix types for getWorksheet() #2223.
Many thanks to @hfhchan-plb for this contribution! - Merged add characters cannot be used for worksheet name #2126.
Many thanks to @tkm-kj for this contribution! - Merged Fix issue #1753 Reject promise when workbook reader is writing to temporary file stream and error occurs #1756.
Many thanks to @pauliusg for this contribution! - Merged README.md to have correct link for Streaming XLSX #2186.
Many thanks to @wulfsolter for this contribution! - Merged Added a polyfill of promise.finally to support lower versions of Firefox. #1982.
Many thanks to @DemoJj for this contribution! - Merged Fix read this.worksheet before assign it #1934.
Many thanks to @ZyqGitHub1 for this contribution! - Merged chore: upgrade jszip to ^3.10.1 #2211.
Many thanks to @jarrod-cocoon for this contribution! - Merged fixed spelling error in README.md file #2208.
Many thanks to @HugoP27 for this contribution! - Merged fix: Fix xlsx.writeFile() not catching error when error occurs #2244.
Many thanks to @zurmokeeper for this contribution! - Merged Improve worksheets’ naming validation logic. #2257.
Many thanks to @Siemienik for this contribution! - Merged fix issue 2125 - spliceRows remove last row #2140.
Many thanks to @babu-ch for this contribution! - Merged fix: fix the loss of column attributes due to incorrect column order #2222.
Many thanks to @cpaiyueyue for this contribution! - Merged Fix: Sheet Properties Types #2327.
Many thanks to @albeniraouf for this contribution! - Merged Use node 18 LTS for tsc, and benchmark. Add node 20. to test matrix. … #2354.
Many thanks to @Siemienik for this contribution! - Merged Add missing tooltip attribute to CellHyperlinkValue index.d.ts #2350.
Many thanks to @NiklasPor for this contribution! - Merged Increase resilience to generating large workbooks #2320.
Many thanks to @hfhchan-plb for this contribution! - Merged repair all ‘c2fo.io’ links (‘c2fo.github.io’) #2324.
Many thanks to @justintunev7 for this contribution! - Merged fix: fix type definitions about last column, formula values and protection #2309.
Many thanks to @gltjk for this contribution! - Merged fix: add spinCount field for WorksheetProtection type #2284.
Many thanks to @damingerdai for this contribution! - Merged Add type definition for WorksheetModel.merges #2281.
Many thanks to @ytjmt for this contribution!
貢獻
歡迎貢獻!這可以幫助我了解大家需要一些什么功能,或者哪些 bugs 造成了極大的麻煩。
我只有一個請求;如果您提交對錯誤修復的請求(PR),請添加一個能夠解決問題的單元測試或集成測試(在 spec 文件夾中)。
即使只是測試失敗的請求(PR)也可以 - 我可以分析測試的過程并以此修復代碼。
注意:請盡可能避免在請求(PR)中修改軟件包版本。
版本一般在發布時會進行更新,任何版本更改很可能導致合并沖突。
明確地說,添加到該庫的所有貢獻都將包含在該庫的 MIT 許可證中。
目錄
- 導入
- 接口
- 創建工作簿
- 設置工作簿屬性
- 工作簿視圖
- 添加工作表
- 刪除工作表
- 訪問工作表
- 工作表狀態
- 工作表屬性
- 頁面設置
- 頁眉和頁腳
- 工作表視圖
- 凍結視圖
- 拆分視圖
- 自動篩選器
- 列
- 行
- Add Rows
- 處理單個單元格
- 合并單元格
- Insert Rows
- Splice
- 重復行
- 定義名稱
- 數據驗證
- 單元格注釋
- 表格
- 樣式
- 數字格式
- 字體
- 對齊
- 邊框
- 填充
- 富文本
- 條件格式化
- 大綱級別
- 圖片
- 工作表保護
- 文件 I/O
- XLSX
- 讀 XLSX
- 寫 XLSX
- CSV
- 讀 CSV
- 寫 CSV
- 流式 I/O
- 流式 XLSX
- XLSX
- 瀏覽器
- 值類型
- Null 值
- 合并單元格
- 數字值
- 字符串值
- 日期值
- 超鏈接值
- 公式值
- 共享公式
- 公式類型
- 數組公式
- 富文本值
- 布爾值
- 錯誤值
- 配置
- 已知的問題
- 發布歷史
導入?
const ExcelJS = require('exceljs');
ES5 導入?
要使用 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.prototype;
}
瀏覽器端?
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';// 在每個打印頁面上重復特定的行
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 |
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 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');
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);
Insert Rows?
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’ |
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');
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 值。 |
表格樣式主題?
有效的主題名稱遵循以下模式:
- “TableStyle[Shade][Number]”
Shades(陰影),Number(數字)可以是以下之一:
- Light, 1-21
- Medium, 1-28
- Dark, 1-11
對于無主題,請使用值 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();
樣式?
單元格,行和列均支持一組豐富的樣式和格式,這些樣式和格式會影響單元格的顯示方式。
通過分配以下屬性來設置樣式:
- numFmt
- font
- alignment
- border
- fill
// 為單元格分配樣式
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'}}
};
有效邊框樣式
- thin
- dotted
- dashDot
- hair
- dashDotDot
- slantDashDot
- mediumDashed
- mediumDashDotDot
- mediumDashDot
- medium
- double
- thick
填充?
// 用紅色深色垂直條紋填充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 | 指定圖案背景色。默認為白色。 |
有效模式類型
- none
- solid
- darkGray
- mediumGray
- lightGray
- gray125
- gray0625
- darkHorizontal
- darkVertical
- darkDown
- darkUp
- darkGrid
- darkTrellis
- lightHorizontal
- lightVertical
- lightDown
- lightUp
- lightGrid
- lightTrellis
漸變填充?
屬性 | 是否需要 | 描述 |
---|---|---|
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文本或單元格格式化。富文本值可以控制文本值內任意數量的子字符串的字體屬性。有關支持哪些字體屬性的詳細信息,請參見字體。
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,
};
支持的保護屬性
屬性 | 默認值 | 描述 |
---|---|---|
locked | true | 指定在工作表受保護的情況下是否將單元格鎖定。 |
hidden | false | 指定如果工作表受保護,則單元格的公式是否可見。 |
條件格式化?
條件格式化允許工作表根據單元格值或任意公式顯示特定的樣式,圖標等。
條件格式設置規則是在工作表級別添加的,通常會覆蓋一系列單元格。
可以將多個規則應用于給定的單元格范圍,并且每個規則都將應用自己的樣式。
如果多個規則影響給定的單元格,則規則優先級值將確定如果競爭樣式沖突,則哪個規則勝出。優先級值較低的規則獲勝。如果沒有為給定規則指定優先級值,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'}}},}]
})
支持的條件格式設置規則類型
類型 | 描述 |
---|---|
expression | 任何自定義功能均可用于激活規則。 |
cellIs | 使用指定的運算符將單元格值與提供的公式進行比較 |
top10 | 將格式化應用于值在頂部(或底部)范圍內的單元格 |
aboveAverage | 將格式化應用于值高于(或低于)平均值的單元格 |
colorScale | 根據其值在范圍內的位置將彩色背景應用于單元格 |
iconSet | 根據值將一系列圖標之一添加到單元格 |
containsText | 根據單元格是否為特定文本來應用格式 |
timePeriod | 根據單元格日期時間值是否在指定范圍內應用格式 |
表達式?
屬性 | 可選 | 默認值 | 描述 |
---|---|---|---|
type | 'expression' | ||
priority | Y | <auto> | 確定樣式的優先順序 |
formulae | 1個包含真/假值的公式字符串數組。要引用單元格值,請使用左上角的單元格地址 | ||
style | 公式返回 true 時要應用的樣式結構 |
Cell Is?
屬性 | 可選 | 默認值 | 描述 |
---|---|---|---|
type | 'cellIs' | ||
priority | Y | <auto> | 確定樣式的優先順序 |
operator | 如何將單元格值與公式結果進行比較 | ||
formulae | 1個公式字符串數組,返回要與每個單元格進行比較的值 | ||
style | 如果比較返回 true ,則應用樣式結構 |
Cell Is 運算符
運算 | 描述 |
---|---|
equal | 如果單元格值等于公式值,則應用格式 |
greaterThan | 如果單元格值大于公式值,則應用格式 |
lessThan | 如果單元格值小于公式值,則應用格式 |
between | 如果單元格值在兩個公式值之間(包括兩個值),則應用格式 |
Top 10?
屬性 | 可選 | 默認值 | 描述 |
---|---|---|---|
type | 'top10' | ||
priority | Y | <auto> | 確定樣式的優先順序 |
rank | Y | 10 | 指定格式中包含多少個頂部(或底部)值 |
percent | Y | false | 如果為 true,則等級字段為百分比,而不是絕對值 |
bottom | Y | false | 如果為 true,則包含最低值而不是最高值 |
style | 如果比較返回 true,則應用樣式結構 |
高于平均值?
屬性 | 可選 | 默認值 | 描述 |
---|---|---|---|
type | 'aboveAverage' | ||
priority | Y | <auto> | 確定樣式的優先順序 |
aboveAverage | Y | false | 如果為 true,則等級字段為百分比,而不是絕對值 |
style | 如果比較返回 true,則應用樣式結構 |
色階?
屬性 | 可選 | 默認值 | 描述 |
---|---|---|---|
type | 'colorScale' | ||
priority | Y | <auto> | 確定樣式的優先順序 |
cfvo | 2到5個條件格式化值對象的數組,指定值范圍內的航路點 | ||
color | 在給定的航路點使用的相應顏色數組 | ||
style | 如果比較返回 true,則應用樣式結構 |
圖標集?
屬性 | 可選 | 默認值 | 描述 |
---|---|---|---|
type | 'iconSet' | ||
priority | Y | <auto> | 確定樣式的優先順序 |
iconSet | Y | 3TrafficLights | 設置使用的圖標名稱 |
showValue | true | 指定應用范圍內的單元格是顯示圖標和單元格值,還是僅顯示圖標 | |
reverse | false | 指定是否以保留順序顯示 iconSet 中指定的圖標集中的圖標。 如果 custom 等于 true ,則必須忽略此值 | |
custom | false | 指定是否使用自定義圖標集 | |
cfvo | 2到5個條件格式化值對象的數組,指定值范圍內的航路點 | ||
style | 如果比較返回 true,則應用樣式結構 |
數據條?
字段 | 可選 | 默認值 | 描述 |
---|---|---|---|
type | 'dataBar' | ||
priority | Y | <auto> | 確定樣式的優先順序 |
minLength | 0 | 指定此條件格式范圍內最短數據條的長度 | |
maxLength | 100 | 指定此條件格式范圍內最長數據條的長度 | |
showValue | true | 指定條件格式范圍內的單元格是否同時顯示數據條和數值或數據條 | |
gradient | true | 指定數據條是否具有漸變填充 | |
border | true | 指定數據條是否有邊框 | |
negativeBarColorSameAsPositive | true | 指定數據條是否具有與正條顏色不同的負條顏色 | |
negativeBarBorderColorSameAsPositive | true | 指定數據條的負邊框顏色是否不同于正邊框顏色 | |
axisPosition | ‘auto’ | 指定數據條的軸位置 | |
direction | ‘leftToRight’ | 指定數據條的方向 | |
cfvo | 2 到 5 個條件格式化值對象的數組,指定值范圍內的航路點 | ||
style | 如果比較返回 true,則應用樣式結構 |
包含文字?
屬性 | 可選 | 默認值 | 描述 |
---|---|---|---|
type | 'containsText' | ||
priority | Y | <auto> | 確定樣式的優先順序 |
operator | 文本比較類型 | ||
text | 要搜索的文本 | ||
style | 如果比較返回 true,則應用樣式結構 |
包含文本運算符
運算符 | 描述 |
---|---|
containsText | 如果單元格值包含在 text 字段中指定的值,則應用格式 |
containsBlanks | 如果單元格值包含空格,則應用格式 |
notContainsBlanks | 如果單元格值不包含空格,則應用格式 |
containsErrors | 如果單元格值包含錯誤,則應用格式 |
notContainsErrors | 如果單元格值不包含錯誤,則應用格式 |
時間段?
屬性 | 可選 | 默認值 | 描述 |
---|---|---|---|
type | 'timePeriod' | ||
priority | Y | <auto> | 確定樣式的優先順序 |
timePeriod | 比較單元格值的時間段 | ||
style | 如果比較返回 true,則應用樣式結構 |
時間段
時間段 | 描述 |
---|---|
lastWeek | 如果單元格值落在最后一周內,則應用格式 |
thisWeek | 如果單元格值在本周下降,則應用格式 |
nextWeek | 如果單元格值在下一周下降,則應用格式 |
yesterday | 如果單元格值等于昨天,則應用格式 |
today | 如果單元格值等于今天,則應用格式 |
tomorrow | 如果單元格值等于明天,則應用格式 |
last7Days | 如果單元格值在過去7天之內,則應用格式 |
lastMonth | 如果單元格值屬于上個月,則應用格式 |
thisMonth | 如果單元格值在本月下降,則應用格式 |
nextMonth | 如果單元格值在下個月下降,則應用格式 |
大綱級別?
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,
};
圖片?
將圖像添加到工作表是一個分為兩個步驟的過程。首先,通過 addImage()
函數將圖像添加到工作簿中,該函數還將返回 imageId
值。然后,使用 imageId
,可以將圖像作為平鋪背景或覆蓋單元格區域添加到工作表中。
注意:從此版本開始,不支持調整或變換圖像。
將圖片添加到工作簿?
Workbook.addImage
函數支持按文件名或按 Buffer
添加圖像。請注意,在兩種情況下,都必須指定擴展名。有效的擴展名包括 “jpeg”,“png”,“gif”。
// 通過文件名將圖像添加到工作簿
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',
});
將圖片添加到工作表背景?
使用 Workbook.addImage
中的圖像 ID
,可以使用 addBackgroundImage
函數設置工作表的背景
// 設置背景
worksheet.addBackgroundImage(imageId1);
在一定范圍內添加圖片?
使用 Workbook.addImage
中的圖像 ID
,可以將圖像嵌入工作表中以覆蓋一定范圍。從該范圍計算出的坐標將覆蓋從第一個單元格的左上角到第二個單元格的右下角。
// 在 B2:D6 上插入圖片
worksheet.addImage(imageId2, 'B2:D6');
使用結構而不是范圍字符串,可以部分覆蓋單元格。
請注意,為此使用的坐標系基于零,因此 A1 的左上角將為 {col:0,row:0}
。單元格的分數可以通過使用浮點數來指定,例如 A1 的中點是 {col:0.5,row:0.5}
。
// 在 B2:D6 的一部分上插入圖像
worksheet.addImage(imageId2, {tl: { col: 1.5, row: 1.5 },br: { col: 3.5, row: 5.5 }
});
單元格區域還可以具有屬性 "editAs"
,該屬性將控制將圖像錨定到單元格的方式。它可以具有以下值之一:
值 | 描述 |
---|---|
undefined | 它指定使圖像將根據單元格移動和調整其大小 |
oneCell | 這是默認值。圖像將與單元格一起移動,但大小不變動 |
absolute | 圖像將不會隨著單元格移動或調整大小 |
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();
有關如何修改單個單元格保護的詳細信息請查看 單元格保護。
注意: 當 protect()
函數返回一個 Promise 代表它是異步的,當前的實現在主線程上運行,并且在 CPU 上將使用平均大約 600 毫秒。可以通過設置 spinCount
進行調整,該值可用于使過程更快或更有彈性。
工作表保護選項?
屬性 | 默認值 | 描述 |
---|---|---|
selectLockedCells | true | 允許用戶選擇鎖定的單元格 |
selectUnlockedCells | true | 允許用戶選擇未鎖定的單元格 |
formatCells | false | 允許用戶格式化單元格 |
formatColumns | false | 允許用戶格式化列 |
formatRows | false | 允許用戶格式化行 |
insertRows | false | 允許用戶插入行 |
insertColumns | false | 允許用戶插入列 |
insertHyperlinks | false | 允許用戶插入超鏈接 |
deleteRows | false | 允許用戶刪除行 |
deleteColumns | false | 允許用戶刪除列 |
sort | false | 允許用戶對數據進行排序 |
autoFilter | false | 允許用戶過濾表中的數據 |
pivotTables | false | 允許用戶使用數據透視表 |
spinCount | 100000 | 保護或取消保護時執行的哈希迭代次數 |
文件 I/O?
XLSX?
讀 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 文件時支持的選項。
屬性 | 是否需要 | 類型 | 描述 |
---|---|---|---|
dateFormats | N | Array | 指定 dayjs 的日期編碼格式。 |
map | N | Function | 自定義Array.prototype.map() 回調函數,用于處理數據。 |
sheetName | N | String | 指定工作表名稱。 |
parserOptions | N | Object | parseOptions 選項 @fast-csv/format 模塊以寫入 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列是公式值的JSONreturn JSON.parse(value);default:// 其余的是數字return parseFloat(value);}},// https://c2fo.github.io/fast-csv/docs/parsing/optionsparserOptions: {delimiter: '\t',quote: false,},
};
const worksheet = await workbook.csv.readFile(filename, options);
// ... 使用 workbook 或 worksheet
CSV 解析器使用 fast-csv 讀取CSV文件。傳遞給上述寫入函數的選項中的 formatterOptions
將傳遞給 @fast-csv/format 模塊以寫入 csv 數據。 有關詳細信息,請參閱 fast-csv README.md。
使用 npm 模塊 dayjs 解析日期。如果未提供 dateFormats
數組,則使用以下 dateFormats:
- ‘YYYY-MM-DD[T]HH:mm:ss’
- ‘MM-DD-YYYY’
- ‘YYYY-MM-DD’
請參閱 dayjs CustomParseFormat 插件,以獲取有關如何構造 dateFormat
的詳細信息。
寫 CSV?
寫入 CSV 文件時支持的選項。
屬性 | 是否需要 | 類型 | 描述 |
---|---|---|---|
dateFormat | N | String | 指定 dayjs 的日期編碼格式。 |
dateUTC | N | Boolean | 指定 ExcelJS 是否使用dayjs.utc() 轉換時區以解析日期。 |
encoding | N | String | 指定文件編碼格式。 |
includeEmptyRows | N | Boolean | 指定是否可以寫入空行。 |
map | N | Function | 自定義Array.prototype.map() 回調函數,用于處理行值。 |
sheetName | N | String | 指定工作表名稱。 |
sheetId | N | Number | 指定工作表 ID。 |
formatterOptions | N | Object | formatterOptions 選項 @fast-csv/format 模塊寫入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.github.io/fast-csv/docs/formatting/optionsformatterOptions: {delimiter: '\t',quote: false,},
};
await workbook.csv.writeFile(filename, options);// 寫入新 buffer
const buffer = await workbook.csv.writeBuffer();
CSV 解析器使用 fast-csv 編寫 CSV 文件。傳遞給上述寫入函數的選項中的 formatterOptions
將傳遞給 @fast-csv/format 模塊以寫入 csv 數據。有關詳細信息,請參閱 fast-csv README.md。
日期使用 npm 模塊 dayjs 格式化。如果未提供 dateFormat
,則使用 dayjs.ISO_8601
。編寫 CSV 時,您可以提供布爾值 dateUTC
為 true
,以使 ExcelJS 解析日期,而無需使用 dayjs.utc()
自動轉換時區。
流式 I/O?
上面記錄的文件 I/O 需要在內存中建立整個工作簿,然后才能寫入文件。雖然方便,但是由于所需的內存量,它可能會限制文檔的大小。
流寫入器(或讀取器)在生成工作簿或工作表數據時對其進行處理,然后將其轉換為文件形式。通常,這在內存上效率要高得多,因為最終的內存占用量,甚至中間的內存占用量都比文檔版本要緊湊得多,尤其是當您考慮到行和單元格對象一旦提交就被銷毀時,尤其如此。
流式工作簿和工作表的接口幾乎與文檔版本相同,但實際存在一些細微差別:
- 將工作表添加到工作簿后,將無法將其刪除。
- 提交行后,將無法再訪問該行,因為該行將從工作表中刪除。
- 不支持
unMergeCells()
。
請注意,可以在不提交任何行的情況下構建整個工作簿。提交工作簿后,所有添加的工作表(包括所有未提交的行)將自動提交。但是,在這種情況下,與文檔版本相比收效甚微。
流式 XLSX?
流式 XLSX 寫入器?
流式 XLSX 寫入器在 ExcelJS.stream.xlsx
命名空間中可用。
構造函數采用帶有以下字段的可選 options
對象:
字段 | 描述 |
---|---|
stream | 指定要寫入 XLSX 工作簿的可寫流。 |
filename | 如果未指定流,則此字段指定要寫入 XLSX 工作簿的文件的路徑。 |
useSharedStrings | 指定是否在工作簿中使用共享字符串。默認為 false |
useStyles | 指定是否將樣式信息添加到工作簿。樣式會增加一些性能開銷。默認為 false |
zip | ExcelJS 內部傳遞給 Archiver 的 Zip選項。默認值為 undefined |
如果在選項中未指定 stream
或 filename
,則工作簿編寫器將創建一個 StreamBuf 對象,該對象將 XLSX 工作簿的內容存儲在內存中。可以通過屬性 workbook.stream
訪問此 StreamBuf 對象,該對象可用于通過 stream.read()
直接訪問字節,或將內容通過管道傳輸到另一個流。
// 使用樣式和共享字符串構造流式 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參數:
Argument | Description |
---|---|
input (必需的) | 指定從中讀取XLSX工作簿的文件或可讀流的名稱 |
options (可選的) | 指定如何處理讀取解析期間發生的事件類型 |
options.entries | 指定是否去觸發事件('emit' )或者不發出事件('ignore' ),默認值是'emit' |
options.sharedStrings | 指定是否去緩存('cache' )共享字符串,將其插入到相應的單元格值中,或者是否去觸發('emit' )或忽略('ignore' )它們,在這兩種情況下,單元格值都將是對共享字符串索引的引用。默認值是'cache' |
options.hyperlinks | 指定是否去緩存超鏈接('cache' ),將其插入到相應的單元格值中,是否去觸發('emit' )或忽略('ignore' )它們。默認值是'cache' |
options.styles | 指定是否去緩存樣式('cache' ),將其插入到相應的行或單元格值中,或是否忽略('忽略' )它們。默認值是'cache' |
options.worksheets | 指定是否去觸發('emit' )或忽略('ignore' )工作表。默認值是'emit' |
const workbook = new ExcelJS.stream.xlsx.WorkbookReader('./file.xlsx');
for await (const worksheetReader of workbookReader) {for await (const row of worksheetReader) {// ...}
}
請注意,由于性能原因,worksheetReader
返回一個行數組,而不是單獨返回每一行: https://github.com/nodejs/node/issues/31979
迭代遍歷所有事件?
工作簿上的事件是 ‘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':// 值是worksheetReadercase '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 文件夾中。
- exceljs.js
- exceljs.min.js
值類型?
支持以下值類型。
Null 值?
Enum: Excel.ValueType.Null
空值表示沒有值,通常在寫入文件時將不存儲(合并的單元格除外)。可用于從單元格中刪除該值。例如:
worksheet.getCell('A1').value = null;
合并單元格?
Enum: Excel.ValueType.Merge
合并單元格是其值綁定到另一個“主”單元格的單元格。分配給合并單元將導致修改單元格。
數字值?
Enum: Excel.ValueType.Number
一個數字值。
例如:
worksheet.getCell('A1').value = 5;
worksheet.getCell('A2').value = 3.14159;
字符串值?
Enum: Excel.ValueType.String
一個簡單的文本字符串。
例如:
worksheet.getCell('A1').value = 'Hello, World!';
日期值?
Enum: Excel.ValueType.Date
日期值,由 JavaScript Date 類型表示。
例如:
worksheet.getCell('A1').value = new Date(2017, 2, 15);
超鏈接值?
Enum: Excel.ValueType.Hyperlink
具有文本和鏈接值的 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.ValueType.Formula
一個 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');
可以使用 fillFormula
方法將共享的公式分配到工作表中:
// 將 A1 設置為起始編號
worksheet.getCell('A1').value = 1;// 從 A1 開始以遞增計數將 A2 填充到 A10
worksheet.fillFormula('A2:A10', 'A1+1', [2,3,4,5,6,7,8,9,10]);
fillFormula
也可以使用回調函數來計算每個單元格的值
// 從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;
公式類型具有以下值:
名稱 | 值 |
---|---|
Enums.FormulaType.None | 0 |
Enums.FormulaType.Master | 1 |
Enums.FormulaType.Shared | 2 |
數組公式?
在 Excel 中表示共享公式的一種新方法是數組公式。以這種形式,主單元格是唯一包含與公式有關的任何信息的單元格。它包含 shareType ‘array’ 以及適用于其的單元格范圍以及將要復制的公式。其余單元格是具有常規值的常規單元格。
注意:數組公式不會以共享公式的方式轉換。因此,如果主單元A2引用A1,則從單元B2也將引用A1。
例如:
// 將數組公式分配給 A2:B3
worksheet.getCell('A2').value = {formula: 'A1',result: 10,shareType: 'array',ref: 'A2:B3'
};// 可能沒有必要填寫工作表中的其余值
fillFormula
方法也可以用于填充數組公式
// 用數組公式 "A1" 填充 A2:B3
worksheet.fillFormula('A2:B3', 'A1', [1,1,1,1], 'array');
富文本值?
Enum: Excel.ValueType.RichText
樣式豐富的文本。
例如:
worksheet.getCell('A1').value = {richText: [{ text: 'This is '},{font: {italic: true}, text: 'italic'},]
};
布爾值?
Enum: Excel.ValueType.Boolean
例如:
worksheet.getCell('A1').value = true;
worksheet.getCell('A2').value = false;
錯誤值?
Enum: Excel.ValueType.Error
例如:
worksheet.getCell('A1').value = { error: '#N/A' };
worksheet.getCell('A2').value = { error: '#VALUE!' };
當前有效的錯誤文本值為:
名稱 | 值 |
---|---|
Excel.ErrorValue.NotApplicable | #N/A |
Excel.ErrorValue.Ref | #REF! |
Excel.ErrorValue.Name | #NAME? |
Excel.ErrorValue.DivZero | #DIV/0! |
Excel.ErrorValue.Null | #NULL! |
Excel.ErrorValue.Value | #VALUE! |
Excel.ErrorValue.Num | #NUM! |
接口變化?
我們會盡一切努力創建一個良好的,一致的接口,該接口不會在版本之間不兼容,但令人遺憾的是,為了實現更大的利益,有時需要進行一些更改。
0.1.0?
Worksheet.eachRow?
在 Worksheet.eachRow
的回調函數中的參數已被交換和更改;它是 function(rowNumber,rowValues)
,現在是 function(row,rowNumber)
,使它的外觀更像 underscore(_.each
)方法,并且行對象優先于行號。
Worksheet.getRow?
此函數已從返回稀疏的單元格數組更改為返回 Row
對象。這樣可以訪問行屬性,并有助于管理行樣式等。
仍可通過 Worksheet.getRow(rowNumber).values;
獲得稀疏的單元格值的數組。
0.1.1?
cell.model?
cell.styles
重命名為 cell.style
0.2.44?
從 Bluebird 切換到 Node 原生 Promise 的函數返回的 Promise 如果依賴 Bluebird 的額外功能,則可能會破壞調用代碼。
為了減少這種情況的出現,在0.3.0中添加了以下兩個更改:
- 默認情況下使用功能更全且仍與瀏覽器兼容的 promise lib。 該庫支持 Bluebird 的許多功能,但占用空間少得多。
- 注入其他 Promise 實現的選項。有關更多詳細信息,請參見配置部分。
配置?
ExcelJS現在支持對 Promise 庫的依賴項注入。您可以通過在模塊中包含以下代碼來還原 Bluebird Promise。
ExcelJS.config.setValue('promise', require('bluebird'));
請注意:我已經使用 bluebird 專門測試了 ExcelJS(直到最近,這是它使用的庫)。根據我所做的測試,它不適用于 Q。
注意事項?
Dist 文件夾?
在發布此模塊之前,先對源代碼進行編譯和其他處理,然后再將它們放置在 dist/ 文件夾中。該自述文件標識兩個文件-瀏覽器捆綁和壓縮版本。除了在 package.json 中指定為 "main"
的文件外,不能保證 dist/ 文件夾的其他內容。
已知的問題?
使用 Puppeteer 進行測試?
該 lib 中包含的測試套件包括一個在無頭瀏覽器中執行的小腳本,以驗證捆綁的軟件包。 在撰寫本文時,其表現出該測試在 Windows Linux 子系統中不能很好地進行。
因此,可以通過存在名為 .disable-test-browser 的文件來禁用瀏覽器測試。
sudo apt-get install libfontconfig
拼接與合并?
如果任何 splice
操作影響合并的單元格,則合并組將無法正確移動
發布歷史?
Version | Changes |
---|---|
0.0.9 |
|
0.1.0 |
|
0.1.1 |
|
0.1.2 |
|
0.1.3 |
|
0.1.5 |
|
0.1.6 |
|
0.1.8 |
|
0.1.9 |
|
0.1.10 |
|
0.1.11 |
|
0.2.0 |
|
0.2.2 |
|
0.2.3 |
|
0.2.4 |
|
0.2.6 |
|
0.2.7 |
|
0.2.8 |
|
0.2.9 |
|
0.2.10 |
|
0.2.11 |
|
0.2.12 |
|
0.2.13 |
|
0.2.14 |
|
0.2.15 |
|
0.2.16 |
|
0.2.17 |
|
0.2.18 |
|
0.2.19 |
|
0.2.20 |
|
0.2.21 |
|
0.2.22 |
|
0.2.23 |
|
0.2.24 |
|
0.2.25 |
|
0.2.26 |
|
0.2.27 |
|
0.2.28 |
|
0.2.29 |
|
0.2.30 |
|
0.2.31 |
|
0.2.32 |
|
0.2.33 |
|
0.2.34 |
|
0.2.35 |
|
0.2.36 |
|
0.2.37 |
|
0.2.38 |
|
0.2.39 |
|
0.2.42 |
|
0.2.43 |
|
0.2.44 |
|
0.2.45 |
|
0.2.46 |
|
0.3.0 |
|
0.3.1 |
|
0.4.0 |
|
0.4.1 |
|
0.4.2 |
|
0.4.3 |
|
0.4.4 |
|
0.4.6 |
|
0.4.9 |
|
0.4.10 |
|
0.4.11 |
|
0.4.12 |
|
0.4.13 |
|
0.4.14 |
|
0.5.0 |
|
0.5.1 |
|
0.6.0 |
|
0.6.1 |
|
0.6.2 |
|
0.7.0 |
|
0.7.1 |
|
0.8.0 |
|
0.8.1 |
|
0.8.2 |
|
0.8.3 |
|
0.8.4 |
|
0.8.5 |
|
0.9.0 |
|
0.9.1 |
|
1.0.0 |
|
1.0.1 |
|
1.0.2 |
|
1.1.0 |
|
1.1.1 |
|
1.1.2 |
|
1.1.3 |
|
1.2.0 |
|
1.2.1 |
|
1.3.0 |
|
1.4.2 |
|
1.4.3 |
|
1.4.5 |
|
1.4.6 |
|
1.4.7 |
|
1.4.8 |
|
1.4.9 |
|
1.4.10 |
|
1.4.12 |
|
1.4.13 |
|
1.5.0 |
|
1.5.1 |
|
1.6.0 |
|
1.6.1 |
|
1.6.2 |
|
1.6.3 |
|
1.7.0 |
|
1.8.0 |
|
1.9.0 |
|
1.9.1 |
|
1.10.0 |
|
1.11.0 |
|
1.12.0 |
|
1.12.1 |
|
1.12.2 |
|
1.13.0 |
|
1.14.0 |
|
1.15.0 |
|
2.0.1 | Major Version ChangeIntroducing async/await to ExcelJS! The new async and await features of JavaScript can help a lot to make code more readable and maintainable. To avoid confusion, particularly with returned promises from async functions, we have had to remove the Promise class configuration option and from v2 onwards ExcelJS will use native Promises. Since this is potentially a breaking change we’re bumping the major version for this release. Changes
|
3.0.0 | Another Major Version ChangeJavascript has changed a lot over the years, and so have the modules and technologies surrounding it. To this end, this major version of ExcelJS changes the structure of the publish artefacts: Main Export is now the Original Javascript SourcePrior to this release, the transpiled ES5 code was exported as the package main. From now on, the package main comes directly from the lib/ folder. This means a number of dependencies have been removed, including the polyfills. ES5 and Browserify are Still IncludedIn order to support those that still require ES5 ready code (e.g. as dependencies in web apps) the source code will still be transpiled and available in dist/es5. The ES5 code is also browserified and available as dist/exceljs.js or dist/exceljs.min.js See the section Importing for details |
3.1.0 |
|
3.2.0 |
|
3.3.0 |
|
3.3.1 |
|
3.4.0 |
|
3.5.0 |
|
3.6.0 |
|
3.6.1 |
|
3.7.0 |
|
3.8.0 |
|
3.8.1 |
|
3.8.2 |
|
3.9.0 |
|
3.10.0 |
|
4.0.1 |
|
4.1.0 |
|
4.1.1 |
|
4.2.0 |
|
4.2.1 |
|
4.3.0 |
|
-í???€€-???e?€€-???? ??