簡介
SheetJS是前端操作Excel以及類似的二維表的最佳選擇之一,而js-xlsx
是它的社區版本.
js-xlsx
將注意力集中到了數據轉換和導出上,所以它支持相當多種類的數據解析和導出.不僅僅侷限於支持xlsx格式.
它可以:
- 解析符合格式的數據
- 導出符合格式的數據
- 利用中間層操作數據
可以運行在:
- 瀏覽器端
- Node端
瀏覽器端特色
- 純瀏覽器端解析數據
- 純瀏覽器端導出數據
Node端特色
- 讀寫文件
- 流式讀寫
本篇文章力求精簡,主要討論一下js-xlsx
的工作流程和基本概念以及使用方式.
概念
js-xlsx
提供了一箇中間層用於操作數據,他將不同類型的文件抽象成同一個js對象,從而規避了操作不同種類數據數據之間的複雜性.
並且圍繞着這個對象提供了一系列的抽象功能,本小節主要討論這些數據對象與Excel數據之間的關係.
而瀏覽器端和Node端的區別僅僅在於怎樣導入文件和導出文件上而已,對於數據的操作,雙方的接口是一致的.
引入
js-xlsx
的引入非常簡單,瀏覽器端引入可以是最基本script
標籤的形式.
<script lang="javascript" src="dist/xlsx.full.min.js"></script>
在node端,使用npm安裝如下模塊:
npm install xlsx --save
在Node中如下引入:
const xlsx = require('xlsx');
對應關係
在這個表格中我列舉了Excel與js-xlsx
之間的關係:
Excel名詞 | js-xlsx中的抽象類型 |
---|---|
工作簿 | workBook |
工作表 | Sheets |
Excel引用樣式(單元格地址) | cellAddress |
單元格 | cell |
有了這個基本的對應關係我們就可以輕鬆的理解後續的操作,例如在我們使用Excel的過程中,獲取一個數據的流程如下:
- 打開工作簿
- 打開一個工作表
- 選中一片區域或者一個單元格
- 針對數據進行操作
- 保存(另存爲)
那麼在js-xlsx
中獲取一個單元格內容的操作如下:
// 先不要關心我們的workbook對象是從哪裏來的
var first_sheet_name = workbook.SheetNames[0]; // 獲取工作簿中的工作表名字
var address_of_cell = 'A1'; // 提供一個引用樣式(單元格下標)
var worksheet = workbook.Sheets[first_sheet_name]; // 獲取對應的工作表對象
var desired_cell = worksheet[address_of_cell]; // 獲取對應的單元格對象
var desired_value = (desired_cell ? desired_cell.v : undefined);// 獲取對應單元格中的數據
數據格式
圖片:工作簿的數據結構
一旦我們的Excel文件被解析那麼這個Excel表中的所有內容都會被解析上面的這個對象.而且這整個過程是同步完成的.
所以我們可以使用鍵的方式來直接獲取數據,在上面的例子中我們就利用鍵一層層的向下獲取數據.
上圖中常用的鍵一共有兩個:
-
SheetNames
以字符串數組的形式保存了所有的工作表的名稱 - Sheets下的內容都是工作表對象,而鍵名就是
SheetNames
中包含的名字
而Excel的數據單位由小到大有如下排序如下:
- 單元格
- 工作表
- 工作簿
單元格格式
在Excel中單元格有多種格式,而js-xlsx
會將其解析爲對應的JavaScript的格式.
常見格式如下:
鍵 | 描述 |
---|---|
v | 源數據(未經處理的數據) |
w | 格式化後的文本(如果能夠被格式化) |
t | 單元格類型(具體類型請看下方的表格) |
r | 解碼後的富文本(如果可以被解碼) |
h | 渲染成HTML格式的富文本(如果可以被解碼) |
c | 單元格註釋 |
z | 格式化成字符串的數值(如果需要的話) |
完整格式鏈接.
解析後單元格數據格式:
這個數據在Excel中保存在A1的位置上,文本類型,單元格內容爲xm
.
單元格地址
js-xlsx
使用有兩種方式來描述操作中的單元格區域.
一種是單元格地址對象(Cell address object)另外一種是地址範圍(Cell range).
地址對象格式如下:
const start = { c: 0, r: 0 };
const end = { c: 1, r: 1 };
上方地址對象對應的地址範圍如下:
const range = 'A1:B2';
我們不難發現兩者之間對應的關係:
- 地址對象描述的是一個起始座標(從0開始)到結束座標之間的範圍.
- 地址範圍就是Excel中的引用樣式.
注意:這兩個概念會在工作表讀寫中使用到.
API
js-xlsx
提供的接口非常清晰主要分爲兩類:
-
xlsx
對象本身提供的功能- 解析數據
- 導出數據
-
utils
工具類- 將數據添加到數據表對象上
- 將二維數組以及符合格式的對象或者HTML轉爲工作表對象
- 將工作簿轉爲另外一種數據格式
- 行,列,範圍之間的轉碼和解碼
- 工作簿操作
- 單元格操作
讀取數據並解析
這裏提供一個簡單的Node例子(Node10+):
const xlxs = require('xlsx');
const {readFile} = require('fs').promises;
(async function (params) {
// 獲取數據
const excelBuffer = await readFile('./books.xlsx');
// 解析數據
const result = xlxs.read(excelBuffer,{
type:'buffer',
cellHTML:false,
});
console.log('TCL: result', result);
})();
還可以使用utils.book_new()
創建一個新的工作簿對象:
const
xlsx = require('xlsx'),
{ utils } = xlsx;
const workBook= utils.book_new(); // 創建一個工作簿
然後使用跟多的工具來操作工作簿對象:
// 接着上面的例子
const ws_data = [
[ "S", "h", "e", "e", "t", "J", "S" ],
[ 1 , 2 , 3 , 4 , 5 ]
];
const workSheet = XLSX.utils.aoa_to_sheet(ws_data);// 使用二維數組創建一個工作表對象
utils.book_append_sheet(workBook,workSheet,'工作表名稱');// 向工作簿追加一個工作表
console.log(workBook);
數據填充
工作表是實際存放數據的地方,在大部分情況下我們的操作都是對於工作表對象的操作.
js-xlsx
提供了多種方式來操作數據,這裏提供最常見的幾種操作:
-
利用現有的數據結構創建工作表
- 二維數組作爲數據源
- JSON作爲數據源
-
修改工作表數據
- 二維數組作爲數據源
- JSON作爲數據源
創建工作表
const workSheet = utils.aoa_to_sheet([[1,2,3,new Date()],[1,2,,4]],{
sheetStubs:false,
cellStyles:false,
cellDates:true // 解析爲原生時間
});
console.log(workSheet);
二維數組的關係非常容易理解,數組中的每一個數組代表一行.
圖片:二維數組結果
const workSheet =
utils.json_to_sheet([
{ '列1': 1, '列2': 2, '列3': 3 },
{ '列1': 4, '列2': 5, '列3': 6 }
],{
header:['列1','列2','列3'],
skipHeader:true// 跳過上面的標題行
})
console.log(workSheet);
圖片:JSON效果
修改數據表數據
const workSheet =
utils.json_to_sheet([
{ '列1': 1, '列2': 2, '列3': 3 },
{ '列1': 4, '列2': 5, '列3': 6 }
],{
header:['列1','列2','列3'],
skipHeader:true// 跳過上面的標題行
})
utils.sheet_add_aoa(workSheet,[
[7,8,9],
['A','B','C']
],{
origin:'A1' // 從A1開始增加內容
});
console.log(workSheet);
圖片:二維數組結果
const workSheet =
utils.json_to_sheet([
{ '列1': 1, '列2': 2, '列3': 3 },
{ '列1': 4, '列2': 5, '列3': 6 }
],{
header:['列1','列2','列3'],
skipHeader:true// 跳過上面的標題行
})
utils.sheet_add_json(workSheet,[
{ '列1': 7, '列2': 8, '列3': 9 },
{ '列1': 'A', '列2': 'B', '列3': 'C' }
],{
origin:'A1',// 從A1開始增加內容
header: ['列1', '列2', '列3'],
skipHeader: true// 跳過上面的標題行
});
console.log(workSheet);
圖片:JSON效果
數據導出
數據導出分爲兩個部分:
- 利用工具類將工作簿對象轉爲其他數據結構
- 調用
write
或者writeFile
方法
轉換爲其他的數據結構
這裏就不提供詳細的用例了,可以轉換的格式如下:
輸出文件
這裏提供一個簡單的Node例子(Node10+):
const
xlsx = require('xlsx'),
{ utils } = xlsx;
const {writeFile} =require('fs').promises;
const workBook= utils.book_new();
const workSheet = utils.aoa_to_sheet([[1,2,3]],{
cellDates:true,
});
// 向工作簿中追加工作表
utils.book_append_sheet(workBook, workSheet,'helloWorld');
// 瀏覽器端和node共有的API,實際上node可以直接使用xlsx.writeFile來寫入文件,但是瀏覽器沒有該API
const result = xlsx.write(workBook, {
bookType: 'xlsx', // 輸出的文件類型
type: 'buffer', // 輸出的數據類型
compression:true // 開啓zip壓縮
});
// 寫入文件
writeFile('./hello.xlsx',result)
.catch((error)=>{
console.log(error);
});
引用
https://github.com/SheetJS/js...