这是我参与更文挑战的第2天,活动详情查看: 更文挑战 !
👽概论
小程序解析Excel表格文件并非不可能的任务,搭配SheetJs可以轻松完成任务,但在此过程中也有一些值得注意与分享的地方,下面就和大家一起来探讨一下。
此次实践演示以UNIAPP开发环境为例。
👽SheetJs介绍
SheetJs是一款框架无关的excel操作库,其可以再web环境下或者node环境下完成excel文件读写、新建、导出等诸多功能,此次实践的核心工具就是它啦。
👽模块引入
👻导入工具文件
在github的SheetJS中找到dist目录下的构建文件,官方提供了很多版本可供选择:
xlsx.full.min.js:包含全部特性及功能的版本;
xlsx.core.min.js:仅具备核心功能的版本;
因为此次项目仅涉及到了excel文件的解析,且小程序包体积又有大小要求,所以选择了xlsx.mini.min.js精简版本。
将xlsx.mini.min.js文件下载后放入项目的utils文件夹中备用。
👻获取Excel文件
因为小程序本身只支持上传图像等媒体文件,所以我们选择从服务器请求获取Excel文件。
<script>
import XLSX from '../../utils/xlsx.mini.min.js';//导入SheetJS
export default {
data() {
return {
fileLocation:'https://xxx.xxx.com/tagetFile.xlsx',//文件地址
fileData:null//存放解析后的数据
}
},
created() {
this.getFileData();
},
methods: {
getFileData() {
uni.request({
url: this.fileLocation,
data: {
v: parseInt(Math.random() * 1000000000),//此处作防止服务器缓存用
},
method: 'GET',
responseType: 'arraybuffer',//定义响应类型
success:res=> {
console.log(res.data)//此处即为获取到的二进制数据
/*-----
此处作如下几点解释:
1. 解析后的原始数据我们一般不去改动它,为优化性能将其冻结;
2. { type: 'array' }:定义解析后的数据格式为Array;
3. 我们只关心其中的Sheets工作簿,故直接获取到它。
-----*/
this.fileData = Object.freeze(
XLSX.read(new Uint8Array(res.data), { type: 'array' }).Sheets
)
console.log('文件获取失败', this.fileData);
},
fail:res=> {
console.log('文件获取失败', res);
},
});
},
}
}
👻组织单元格数据
经过上一步操作处理后,我们成功获取到了excel表格中的数据,但同时我们也能清晰的发现,这些数据都是以单元格为单位零散地在一个数组中,这些数据往往需要进一步处理后才能使用。
<script>
···
export default {
···
data(){
return {
cookedSheetAData:null//用于存储处理后的SheetA数据
}
},
methods:{
/* 原始表格数据处理函数
param:{
sheetName,//表名
columnSortMap,//列与字段名之间的映射结构
target,//待填充的目标
}
*/
processData(param) {
let tableData = this.fileData[param.sheetName];
let uselessKeys = Object.keys(tableData).filter(key => key[0] == '!'); //筛选非数据属性
uselessKeys.forEach(key => delete tableData[key]); //删除非数据属性
let usefulKeys = Object.keys(tableData);
let titleRow = [1, 2]; //标题行行号
let dataLength = usefulKeys.filter(key => key[0] == 'A').length - titleRow.length; //定义内容区数组长度
let emptyItem = {};
Object.values(param.columnSortMap).forEach(value => {
emptyItem[value] = null;
});
this[param.target] = JSON.parse(JSON.stringify(Array(dataLength).fill(emptyItem))); //制作模板数据
usefulKeys.forEach(key => {
//解析单元格坐标:如将A3解析为'A'和'3'
//因为此表数据列数较少,对于AZ31这种坐标的情况,此处不做介绍。大家自行开动脑筋
let columSort = key.match(/[A-Z]/g).join(''); //'A'
let columIndex = key.match(/\d/g).join(''); //'3'
if (!titleRow.includes(+columIndex)) {
//将解析后的值赋如data中
this[param.target][columIndex - titleRow.length - 1][param.columnSortMap[columSort]] =
param.columnSortMap[columSort] == 'loanDate' ? tableData[key].w : tableData[key].v;
}
});
Object.freeze(this[param.target]);//依旧做冻结处理
},
//调用处理函数,处理相应工作簿
processSheetA() {
let target = 'cookedSheetAData';//data中用于存放对应数据的字段
let sheetName = '一级渠道放款列表';//工作簿名
let columnSortMap = {
A: 'region',
B: 'rank',
C: 'name',
D: 'channelQuality2nd',
E: 'loanAmount',
F: 'finishedCount',
G: 'unfinishedCount',
H: 'refusedCount',
I: 'passingRate',
J: 'loanDate',
K: 'incrementRate',
};//列坐标与实体字段之间的映射结构(即A列下的数据对应cookedSheetAData数组中的region字段)
this.processData({ target, sheetName, columnSortMap });
},
}
}
接下来的工作就是调用相应方法对数据处理,再在页面上展示啦。大功告成!
👽结语
对于Excel解析来说,代码开发阶段固然很重要,但更为重要的其实是Excel内容结构的定义。一份合理明晰的excel表格可以为开发工作省下不少事情,诸君切记!!🙊🙊🙊