#在uniapp上解析excel表格(基于微信的云开发)

1,449 阅读6分钟

目的:由于项目的框架是uniapp,所以在开发小程序的情况下,采用了小程序的云函数来解析excel表格(撸码不易,请笔芯点个赞)。

云开发的好处

  • 开发者可以使用云开发开发微信小程序、小游戏,无需搭建服务器,即可使用云端能力。云开发为开发者提供完整的原生云端支持和微信服务支持,弱化后端和运维概念,无需搭建服务器,使用平台提供的 API 进行核心业务开发,即可实现快速上线和迭代。关于云开发的更多了解,可以去其官方文档查阅。 采用云开发解析excel的步骤
  • 1、先开通云开发平台。
  • 2、在云项目创建云函数。
  • 3、编写云函数。
  • 4、客户端中使用wx.chooseMessageFile选择表格,通过wx.cloud.uploadFile上传excel,在云函数里解析excel,并把数据添加到云数据库。

一、开通云平台

1、填写小程序appid,选择建立云开发模板,点击创建按钮。

2、创建成功后会进入这样一个界面,然后我们就可以点击云开发按钮,进入开通阶段,暂时可以选择免费版本的。

二、在云项目创建云函数

1、在cloudfunctions的目录下右键点击选择新建Node.js云函数,新建一个云函数

2、这样我们就创建好了一个excel云函数了。

3、在excel的目录下右键点击选择外部终端窗口,输入npm install node-xlsx 安装依赖。安装完成后,看到node-xlsx的版本号就算安装成功了。

三、在云项目编写云函数

首先我们先配置miniprogram目录下的app.js的环境变量,代码如下:

//app.js
App({
  onLaunch: function () {
    if (!wx.cloud) {
      console.error('请使用 2.2.3 或以上的基础库以使用云能力')
    } else {
      wx.cloud.init({
        // env 参数说明:
        //   env 参数决定接下来小程序发起的云开发调用(wx.cloud.xxx)会默认请求到哪个云环境的资源
        //   此处请填入环境 ID, 环境 ID 可打开云控制台查看
        //   如不填则使用默认环境(第一个创建的环境)
        env: 'xxxxxxxxxxxxxx',  //该环境变量可从云平台中找到
        traceUser: true,
      })
    }
    this.globalData = {}
  }
})

配置完成后编写云函数的步骤如下:

1、编写excel的index.js。贴上代码如下:

//index.js
const cloud = require('wx-server-sdk')
cloud.init({env: "xxxxxxxxxxxxxxx"}) //该env环境变量可从云平台中找到
var xlsx = require('node-xlsx'); //引用node-xlsx依赖
const db = cloud.database()  //实例化db库
exports.main = async (event, context) => {
	let {fileID} = event
	//1,通过fileID下载云存储里的excel文件
	const res = await cloud.downloadFile({fileID: fileID})
	const buffer = res.fileContent
	const all_excel_data = [] //用来存储所有的excel数据
	//2,解析excel文件里的数据
	var sheets = xlsx.parse(buffer); //获取到所有sheets,因为表格可能会有多张表
	sheets.forEach(function(sheet) {
        //这里粗暴的用了else if 来处理对应的表名的内容,并处理相应的字段
        //(这里你们可以按照你们的表格内容,自己做相应的处理)
		if (sheet['name'] == "LoRa网关") {
			for (var rowId in sheet['data']) {
				var row = sheet['data'][rowId]; 
				if (rowId > 1 && row.length) { 
					all_excel_data.push({
						addr: row[0], 
						type: row[1], 
						id: row[2], 
						name: row[3],
						sheetName:"LoRa网关"
					})
				}
			}
		}else if (sheet['name'] == "LoRa终端") {
			for (var rowId in sheet['data']) {
				var row = sheet['data'][rowId]; 
				if (rowId > 1 && row.length) { 
					all_excel_data.push({
						type: 0, 
						addr: row[0],
						id: row[1], 
						sheetName:"LoRa终端"
					})
				}
			}
		}else if (sheet['name'] == "监测设备") {
			for (var rowId in sheet['data']) {
				var row = sheet['data'][rowId]; 
				if (rowId > 1 && row.length) { 
					all_excel_data.push({
						type: 1, 
						addr: row[0],
						id: row[1], 
						sheetName:"监测设备"
					})
				}
			}
		}else if (sheet['name'] == "无线路由") {
			for (var rowId in sheet['data']) {
				var row = sheet['data'][rowId]; 
				if (rowId > 1 && row.length) { 
					all_excel_data.push({
						targetDeviceId: row[0], 
						addr1: row[1],
						addr2: row[2],
						addr3: row[3],
						addr4: row[4],
						addr5: row[5],
						addr6: row[6],
						addr7: row[7],
						addr8: row[8],
						sheetName:"无线路由"
					})
				}
			}
		}else if (sheet['name'] == "测点") {
			for (var rowId in sheet['data']) {
				var row = sheet['data'][rowId]; 
				if (rowId > 1 && row.length) { 
					all_excel_data.push({
						name: row[0], 
						id: row[1],
						dataType: row[2],
						readWriteType: row[3],
						addr: row[4],
						regAddr: row[5],
						uploadInterval: row[6],
						collectByteCount: row[7],
						gain: row[8],
						offset: row[9],
						uploadDataType: row[10],
						sheetName:"测点"
					})
				}
			}
		}else if (sheet['name'] == "条件上报") {
			for (var rowId in sheet['data']) {
				var row = sheet['data'][rowId]; 
				if (rowId > 1 && row.length) { 
					all_excel_data.push({
						id: row[0], 
						condition: row[1],
						num1: row[2],
						num2: row[3],
						sheetName:"条件上报"
					})
				}
			}
		}
	});
    // 一起添加所有数据
	var result = await db.collection('users').add({   //这里的 users 字段一定要和云平台的数据哭的集合名称保持一致
		data: all_excel_data
	}).then(res => {
		return res
	}).catch(err => {
		return err
	})
	return result
}

2、编写好excel的index.js云函数后,发现其中有个问题,就是每次拿到excel的内容丢到数据库时,如果不清空以前的数据库,数据库数据就会不断的增加或者被覆盖,所以我们又新建了一个云函数deleData,创建方法跟创建excel函数一样,但云函数deleDataindex.js代码如下:

const cloud = require('wx-server-sdk')
cloud.init({env: "xxxxxxxxxxxxxxx"}) //该env环境变量可从云平台中找到
const db = cloud.database()
exports.main = async(event, context) => {
  let {type,_id} = event
  try {
    if (type == 'all') {
      const _ = db.command
      return await db.collection('users').where({
        _id: _.exists(true) //只要_id字段存在,就删除
      }).remove()
    } else {
      return await db.collection('users').where({
        _id: _id
      }).remove()
    }
  } catch (e) {
    console.error(e)
  }
}

3、编写好所有的云函数后,可以右键点击刚好已经搞好的两个云函数deleDataexcel选择上传并部署,部署成功后,以后如果要来修改对应的index.js的业务逻辑的时候,把修改好的index.js增量上传就好。

四、在uniapp的操作

1、先初始化云开发的环境

wx.cloud.init({env: 'xxxxxxxxxxxxx'});
var db = wx.cloud.database();

1、使用wx.chooseMessageFile来选择微信对话列表中的文件,wx.chooseMessageFile上传文件,wx.cloud.callFunction调用我们前面所创建的云函数excel并成功返回解析后的数据,完整代码如下:

export default {
	data() {
		return {
			fileName: '', //文件名
		};
	},
	onLoad() {
		wx.cloud.init({
			env: 'xxxxxxxxxxxxxxx'
		});
		db = wx.cloud.database();
	},
	methods: {
		//选择excel表格
		chooseFile() {
			wx.chooseMessageFile({
				count: 1,
				type: 'file',
				success: res => {
					if (res.tempFiles[0].name.indexOf('.xlsx') == -1) {
						this.showToast('选择的文件不是excel文件,请重新选择!');
						return;
					}
					this.fileName = res.tempFiles[0].name;
					let path = res.tempFiles[0].path;
					this.uploadExcel(path);
				},
				fail: err => {
					console.log(err);
				}
			});
		},
		// 上传excel表格到云存储
		uploadExcel(path) {
			wx.cloud.uploadFile({
				cloudPath: new Date().getTime() + '.xls',
				filePath: path,
				success: async res => {
					console.log('上传成功', res.fileID);
					//先获取数据库所有的数据长度
					let getData = await db
						.collection('users')
						.where({})
						.count();
					//每隔20条去删除数据,直到清空数据库
					for (let i = 0; i < getData.total; i += 20) {
						this.getListIndexSkip(i).then(async res => {
							//清空数据库
							await wx.cloud.callFunction({
								name: 'deledata',
								data: {
									type: 'all',
									_id: res._id
								},
								success: res => {
									console.log(res);
								},
								fail: err => {
									console.log('删除失败', err);
								}
							});
						});
					};
					setTimeout(() => {
						this.parseF(res.fileID);
					}, 50)

				},
				fail: err => {
					this.showToast('解析excel失败!');
					console.log('上传失败', err);
				}
			});
		},
		//解析文件
		parseF(fileID) {
			wx.cloud.callFunction({
				name: 'excel',
				data: {
					fileID: fileID
				},
				success: async res => {
					console.log('解析并上传成功', res);
					let getData = await db
						.collection('users')
						.where({})
						.count();
					console.log("长度:" + getData.total);
					let list = [];
					for (let i = 0; i < getData.total; i += 20) {
						this.getListIndexSkip(i).then(res => {
							list = list.concat(res);
							if (list.length == getData.total) {
								console.log(list);
								//list为解析返回来的数组
								this.showToast('解析excel成功!');
							}
						});
					}
				},
				fail: err => {
					console.log('解析失败', err);
					this.showToast('解析excel失败!');
				}
			});
		},
		//单次查询函数
		getListIndexSkip(skip) {
			return new Promise((resolve, reject) => {
				let statusList = [];
				let selectPromise;
				if (skip > 0) {
					selectPromise = db
						.collection('users')
						.where({})
						.skip(skip)
						.get();
				} else {
					selectPromise = db
						.collection('users')
						.where({})
						.get();
				}
				selectPromise
					.then(res => {
						resolve(res.data);
					})
					.catch(e => {
						console.error(e);
						reject('查询失败!');
					});
			});
		},
		//弹框显示
		showToast(val) {
			uni.showToast({
				title: val,
				icon: 'none'
			});
		},
	}
};

2、以上的例子返回的结果跟云平台的数据库完全一致,效果截图如下:

返回来的数据,这里是以数组的形式来展示

延伸阅读

微信云开发

uniapp