excel 表格解析插件
# xlsx插件使用
npm i xlsx
1
# 读取excle文件并解析详细文件信息
# FileReader读取文件内容
export const readExcel = (file) => {
return new Promise((resolve) => {
const reader = new FileReader();
reader.onload = (e) => {
const fileData = reader.result;
// reader.result === e.target.result
const result = [];
parseExcelData(fileData, result);
resolve(result);
};
reader.readAsArrayBuffer(file);
});
};
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# FileReader (opens new window)的读取方法
- 【属性】readyState 表示FileReader状态的数字 {EMPTY: 0, LOADING: 1, DONE: 2}。
- 【属性】result 文件的内容。该属性仅在读取操作完成后才有效。
- 【事件】onload 在读取操作完成时触发。
- 【方法】readAsArrayBuffer() 读取指定的 Blob 或 File 对象。一旦完成,会出发onload/onloadend事件,readyState状态会变味DONE,同时 result 属性中将包含一个 ArrayBuffer 对象以表示所读取文件的数据。
- 【方法】readAsBinaryString() 和 readAsArrayBuffer 功能相同,区别是 result 属性将包含所读取文件原始二进制格式。(非标准: 该特性是非标准的,请尽量不要在生产环境中使用它!)
- 【方法】readAsDataURL() 和 readAsArrayBuffer 功能相同,区别是 result 属性将包含所读取文件的
data:
URL格式的字符串(base64编码)。 - 【方法】readAsText() 异步读取指定的 Blob 或 File 对象,根据特殊的编码格式转化为内容(字符串形式)。
# XLSX解析文件内容
import * as XLSX from "xlsx";
export const parseExcelData = (fileData, result) => {
const workbook = XLSX.read(fileData, { type: "binary" });
workbook.SheetNames.forEach((sheetName) => {
const tableAu = XLSX.utils.sheet_to_html(workbook.Sheets[sheetName]);
result.push({
sheetName,
sheet: XLSX.utils.sheet_to_formulae(workbook.Sheets[sheetName]),
json: XLSX.utils.sheet_to_json(workbook.Sheets[sheetName]),
tableAu,
});
});
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# XLSX (opens new window)
解析方法
- XLSX.read(data, read_opts) 解析数据 data
- XLSX.readFile(filename, read_opts) 解析文件名为 fileName 的文件,node环境下使用
# read_opts
1. type 文件类型
type | expected input |
---|---|
"base64" | string: Base64 encoding of the file 需要将内容转成 base-64 编码的 ASCII 字符串 |
"binary" | string: binary string (byte n is data.charCodeAt(n) ) 对应 fileReader.readAsBinaryString() |
"string" | string: JS string (characters interpreted as UTF8) |
"buffer" | nodejs Buffer 对应 fileReader.readAsArrayBuffer() |
"array" | array: array of 8-bit unsigned int (byte n is data[n] ) Uint8Array,8位无符号数组; |
"file" | string: path of file that will be read (nodejs only) 文件的路径(仅nodejs下支持); |
# 解析type: base64
1. buffer -> BinaryString -> base64
function fixdata(data) { //文件流转BinaryString
let o = "", l = 0;
const w = 10240;
for (; l < data.byteLength / w; ++l)
o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w, l * w + w)));
o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w)));
return o;
}
const fileReader = new FileReader();
fileReader.onload = (e: any) => {
const data = fileReader.result;
const workbook = XLSX.read(btoa(fixdata(data)), {type:"base64"})
// TODO: ...
};
fileReader.readAsArrayBuffer(file);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- fixdata() 将文件流 fileReader.readAsArrayBuffer() 获取搭配的文件流转为二进制字符串。
- btoa() (opens new window) 将二进制字符串转化为 base-64 编码的 ASCII 字符串。
- XLSX.read(encodedData, {type:"base64"}) 读取excel文件,获取workbook对象
2. base64文件
const fileReader = new FileReader();
fileReader.onload = (e: any) => {
const data = fileReader.result;
const workbook = XLSX.read((data as string).split(';')[1].replace('base64,',''), {type:"base64"});
// TODO: ...
};
fileReader.readAsDataURL(file);
1
2
3
4
5
6
7
2
3
4
5
6
7
# 解析 type: buffer
ini复制代码const reader = new FileReader();
fileReader.readAsArrayBuffer(file)
reader.onload = (e: any) => {
const data = reader.result;
const workbook = XLSX.read(data, { type: 'buffer' });
// TODO: ...
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 解析 type: binary
const reader = new FileReader();
fileReader.readAsBinaryString(file)
reader.onload = (e: any) => {
const data = reader.result;
const workbook = XLSX.read(data, { type: 'binary' });
// TODO: ...
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# excel数据预览
# workbook
对象
- SheetNames 存放excel中sheet名称
- Sheets 存放每个sheet中的具体内容
# sheet object 表格对象 (opens new window)
Sheets
每个对象代表一张表格,表格中除了以 !
开头的都表示单元格,以 !
开头的表示一些特殊的含义:
!ref
表示所有单元格范围!margin
表示页边距,包含left、right、top、bottom、header、footer!merges
表示合并单元格,是个数组,每个元素包含s
和e
两个对象分别表示开始和结束,s
和e
包含r
和c
两个对象分别表示行和列
# cell object 单元格对象 (opens new window)
Cell Object
每一个单元格是一个对象,包括 v
、w
、t
、f
、F
、r
、h
、c
、z
、l
、s
字段
- t:表示内容类型,
b
Boolean,e
Error,n
Number,d
Date,s
Text等 - v:表示原始值
- w:表示格式化后的内容
- f:表示公式,例如
f: "C3+4"
- h:html内容
- r:富文本内容rich text
# XLSX.utils (opens new window)
XLSX.utils
提供了直接可用的API解析
Exporting:
- XLSX.utils.sheet_to_csv 生成CSV格式
- XLSX.utils.sheet_to_txt 生成文本格式
- XLSX.utils.sheet_to_json 输出json格式
- XLSX.utils.sheet_to_html 将excel数据转化为html(table)
- XLSX.utils.sheet_to_formulae 输出公式列表(带有值回退)。
# 下载文件
XLSX.write
生成一个 sheetnew Blob
将 binary 字符串转成 blob 对象URL.createObjectURL
将 blob 对象转成 url 下载地址
// 将一个sheet转成最终的excel文件的blob对象,然后利用URL.createObjectURL下载
function sheet2blob(workbook) {
// 生成excel的配置项
var wopts: any = {
bookType: 'xlsx', // 要生成的文件类型
bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
type: 'binary'
};
var wbout = XLSX.write(workbook, wopts);
var blob = new Blob([s2ab(wbout)], {type:"application/octet-stream"});
// 字符串转ArrayBuffer
function s2ab(s: any) {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
return blob;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
参考文章 JS弹出下载对话框以及实现常见文件类型的下载 (opens new window)
/**
* 通用的打开下载对话框方法,没有测试过具体兼容性
* @param url 下载地址,也可以是一个blob对象,必选
* @param saveName 保存文件名,可选
*/
export function downloadDialog(sheetDatas, saveName = '导出.xlsx') {
let url: any = sheet2blob(sheetDatas);
if (typeof url == 'object' && url instanceof Blob) {
url = URL.createObjectURL(url); // 创建blob地址
}
var aLink = document.createElement('a');
aLink.href = url;
aLink.download = saveName; // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
var event;
if (window.MouseEvent) event = new MouseEvent('click');
else {
event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
}
aLink.dispatchEvent(event);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# workbook
对象
workbook
的格式和 XLSX.read
读取出来的对象格式一致,包含 SheetNames 和 Sheets
👇 通过XLSX.utils
提供的API生成workbook
# XLSX.utils (opens new window)
XLSX.utils
提供了直接可用的API解析
Importing:
- XLSX.utils.aoa_to_sheet 将
csv
结构的二维数组转 sheet - XLSX.utils.json_to_sheet 将
json
格式数据转 sheet - XLSX.utils.table_to_sheet 将一个
table dom
直接转成 sheet,会自动识别colspan
和rowspan
并将其转成对应的单元格合并 - XLSX.utils.sheet_add_aoa 向现有的工作表中添加一个
csv
数组 - XLSX.utils.sheet_add_json 将一个
json
对象添加到现有的工作表中
const sheetName = 'sheet1';
const aoa = [['姓名','性别','年龄','注册时间'], ['张三','男','18','9/16/21','22'], ['李四','女','22','9/16/21','26'], ['主要信息','','','其它信息']];
const csv = `姓名,性别,年龄,注册时间,\n张三,男,18,9/16/21,22\n李四,女,22,9/16/21,26\n主要信息,,,其它信息,`;
const json = [
{ '姓名': '张三', '年龄': 18, '性别': '男', '注册时间': 44455.62984811343 },
{ '姓名': '李四', '年龄': 22, '性别': '女', '注册时间': 44455.62984811343 },
{ '姓名': '主要信息', '注册时间': '其它信息' },
];
workbook.SheetNames.push(sheetName);
// workbook.Sheets[sheetName] = XLSX.utils.json_to_sheet(json);
// workbook.Sheets[sheetName] = XLSX.utils.aoa_to_sheet(aoa);
// workbook.Sheets[sheetName] = csv2sheet(csv);
workbook.Sheets[sheetName] = XLSX.utils.table_to_sheet(document.getElementsByTagName('table')[0]);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14