在Angular中使用SheetJS导入导出excel表格
导入本地excel表格
首先在终端使用npm命令安装SheetJS插件。SheetJS是个常用的xlsx交互库
npm install xlsx -s
而后,在angular前端的HTML页面上创建一个input元素和一个按钮,用来执行导入操作。这个按钮要跟后台的importExcel($event)函数绑定,这样当点击时触发这个函数,可以执行一系列后续操作
<input
style="display: none"
type="file"
(change)="importExcel($event)"
accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
#fileInput/>
<button nz-button (click)="fileInput.click()">导入数据</button>
在后台的component部分,首先在开头从xlsx库引入一系列需要的组件。为方便跟页面数据绑定,再新建一个全局变量excelData用来存储序列化的excel数据,一个全局变量excelHeadData用来存储表头数据,并和前端绑定
import { read, utils, WorkBook, WorkSheet, writeFile } from 'xlsx';
然后写好importExcel函数
importExcel(evt: any) {
/* 初始化相关参数 */
const target: DataTransfer = <DataTransfer>evt.target;
if (target.files.length !== 1) throw new Error('不支持多文件上传');
const reader: FileReader = new FileReader();
reader.onload = (e: any) => {
/* 我这里因为还打算加一个处理文件名的函数,所以添加了这步 */
let name = target.files[0].name;
this.fileName = name.substring(0, name.lastIndexOf('.'));
/* 读入工作簿 */
const bstr: string = e.target.result;
const wb: WorkBook = read(bstr, { type: 'binary' });
/* 抓取第一个(序号为0)表 */
const wsname: string = wb.SheetNames[0];
const ws: WorkSheet = wb.Sheets[wsname];
/* 保存表格数据标签与数据内容*/
let tmpColumnLabelList = utils.sheet_to_json(ws, {
header: 1,
})[0] as string[];
this.excelHeadData=tmpColumnLabelList;
this.excelData = utils.sheet_to_json(ws, { header: 0 });
evt.target.value = ''; // 清空
};
/* 读入数据 */
reader.readAsBinaryString(target.files[0]);
}
在前端准备好数据展示的表格组件,我这里因为比较熟悉,用了Zorro的Table组件
<!--数据区域-->
<div nz-row nzJustify="center" style="margin-top: 15px; margin-bottom: 10px">
<div nz-col nzSpan="22">
<nz-table #basicTable [nzData]="excelData">
<thead>
<tr>
<ng-container *ngFor="let label of excelHeadData">
<th>{{ label }}</th>
</ng-container>
</tr>
</thead>
<tbody>
<tr *ngFor="let valueData of basicTable.data">
<ng-container *ngFor="let value of excelHeadData">
<td>
<span [innerHtml]="valueData[value]"></span>
</td>
</ng-container>
</tr>
</tbody>
</nz-table>
</div>
</div>
如上,当我们点击按钮导入表格后,就可以通过前端的表格组件载入excel数据了。
这里有一点值得注意:表格在遍历数据时,是通过访问表头值(excelHeadData)的形式实现的。因此如果我们有时候不需要一次性载入太多列,又不想引用更重量级的表格组件甚至在线办公套件,其实在析出表头数据时就可以做取舍,只取那些有用的列,或者再设计几个函数,添加一个把所有列都附上CheckBox让用户选择显隐的功能。
导出网页上的表格数据到本地
与导入同理。不过前端得再写一个按钮调用后端的outputExcel函数。如上所述,我在自己的程序里搞了点自选动作,对表格列进行了取舍,所以这里不选择直接导出excelData,而是通过一个pick函数从excelData中遴选自己所需的表格列,然后再导出
/* 一个便捷的pick函数,方便遴选所需列 */
pick(obj: { [x: string]: any }, keys: any[]) {
return keys
.map((k) => (k in obj ? { [k]: obj[k] } : {}))
.reduce((res, o) => Object.assign(res, o), {});
}
/* 导出至本地excel */
outputExcel() {
const outputArr: any[] = [];
this.excelData.forEach((element: any) => {
let tmpStruct = this.pick(element, this.columnLabelList);
outputArr.push(tmpStruct);
});
const ws: WorkSheet = utils.json_to_sheet(outputArr, {
header: this.columnLabelList,
});
const wb: WorkBook = utils.book_new();
utils.book_append_sheet(wb, ws, 'Sheet1');
writeFile(wb, this.fileName + '保留列.xlsx');
}