第六期:如何通过知晓云将数据表导出为 Excel 文件
作者:知晓云 - 小程序开发快人一步
来源:知晓课堂
在日常的工作中,常常需要根据运营需求对数据进行各种格式的处理和导出。导出后,不少人偏爱将数据放入 excel在进行处理。
一般来说,处理数据导出时需要对数据进行一些运算整理。在以前,处理的方式是在一台独立的服务器上跑脚本。
而现在有了知晓云,不再需要维护服务器,直接写代码就能把相关事都都丢给云函数。 本文将介绍通过知晓云云函数来实现将数据表导出为 excel 文件的功能,并使用 webpack 和 mincloud 将代码打包上传到知晓云。
技术栈:
- 打包工具:webpack@4.22.0
- 部署工具:mincloud@1.0.4
- Excel 处理:node-xlsx@0.14.1
- 其他:知晓云 SDK
一、项目搭建
项目文件结构:
export-excel-file
├── index.js
├── package.json
├── src
│ └── index.js
├── webpack.config.js
└── yarn.lock
项目搭建与云函数代码打包示例文档基本一致。项目搭建好后,还需要安装以下依赖(两种安装方式选其一即可):
// 使用 yarn 安装
yarn add node-xlsx mincloud
// 使用 npm 安装
npm install --save node-xlsx minclou `
修改 deploy 脚本,如下:
// package.json
...
"scripts": { "build": "webpack --mode production", "predeploy": "npm run build", "deploy": "mincloud deploy export-excel-file ../" }, ...
最终我们会使用以下两个命令来部署和测试:
npm run deploy // 部署到知晓云
mincloud invoke export-excel-file // 测试已经部署到知晓云上的云函数
二、将数据表导出为 excel 文件
我们需要准备两张表:
- order: 订单表 (新建字段:name, price)
- export_task:导出任务记录表 (新建字段:file_download_link)
知晓云的云函数调用有同步和异步两种方式,同步调用的最大超时时间为 5 s,异步调用的则为 300 s。
假定 order 订单表有十万条数据,由于知晓云单次拉取数据的最大限制为 1000 条,所以需要分批获取数据,加上后续可能需要对数据进行处理,所花费的时间将会超过 5 s,因此对该云函数的调用将采用异步的方式。这时候就需要 export_task 导出任务记录表来对导出任务进行管理了。
export_task 表对导出任务进行管理的流程如下:
调用云函数时在 export_task 表中创建一条记录 A,此时记录 A 中的 file_download_link 字段值为空,同时拿到记录 A 的 id,记这个 id 为 jobId
进行 order 表数据查询,excel 文件生成,文件上传等操作,拿到文件下载链接
之后根据 jobId 来更新第一步创建的记录,保存文件下载链接到 file_download_link 字段中
更新完后就能在 export_task 表中拿到文件下载链接
通过上面的准备和分析,对导出 excel 文件操作分为以下 4 个步骤:
order 订单表数据获取
使用获取的数据在云函数环境下创建 excel 文件
将创建出的 excel 文件上传到知晓云
保存文件下载链接到 export_task 表中的 file_download_link 字段
完整代码如下:
const fs = require('fs')
const xlsx = require('node-xlsx')const EXPORT_DATA_CATEGORY_ID = '5c711e3119111409cdabe6f2' // 文件上传分类 id
const TABLE_ID = {order: 66666, // 订单表export_task: 66667, // 导出任务记录表
}const TMP_FILE_NAME = '/tmp/result.xlsx' // 本地临时文件路径,以 /tmp 开头,具体请查看:https://doc.minapp.com/support/technical-notes.html (云函数的临时文件存储)
const ROW_NAME = ['name', 'price'] // Excel 文件列名配置
const MAX_CONNECT_LIMIT = 5 // 最大同时请求数
const LIMIT = 1000 // 单次最大拉取数据数
let result = []/*** 更新导出记录中的 file_download_link 字段* @param {*} tableID * @param {*} recordId * @param {*} fileLink */
function updateExportJobIdRecord(tableID, recordId, fileLink) {let Schame = new BaaS.TableObject(tableID)let schame = Schame.getWithoutData(recordId)schame.set('file_download_link', fileLink)return schame.update()
}/*** 创建数据导出任务* 设置初始 file_download_link 为空* 待导出任务执行完毕后将文件下载地址存储到 file_download_link 字段中* @param {*} tableID */
function createExportJobIdRecord(tableID) {let Schame = new BaaS.TableObject(tableID)let schame = Schame.create()return schame.set({file_download_link: ''}).save().then(res => {return res.data.id})
}/*** 获取总数据条数* @tableId {*} tableId*/
function getTotalCount(tableId) {const Order = new BaaS.TableObject(tableId)return Order.count().then(num => {console.log('数据总条数:', num)return num}).catch(err => {console.log('获取数据总条数失败:', err)throw new Error(err)})
}/*** 分批拉取数据* @param {*} tableId * @param {*} offset * @param {*} limit */
function getDataByGroup(tableId, offset = 0, limit = LIMIT) {let Order = new BaaS.TableObject(tableId)return Order.limit(limit).offset(offset).find().then(res => {return res.data.objects}).catch(err => {console.log('获取分组数据失败:', err)throw new Error(err)})
}/*** 创建 Excel 导出文件* @param {*} sourceData 源数据*/
function genExportFile(sourceData = []) {const resultArr = []const rowArr = []// 配置列名rowArr.push(ROW_NAME)sourceData.forEach(v => {rowArr.push(ROW_NAME.map(k => v[k]))})resultArr[0] = {data: rowArr,name: 'sheet1', // Excel 工作表名}const option = {'!cols': [{wch: 10}, {wch: 20}]} // 自定义列宽度const buffer = xlsx.build(resultArr, option)return fs.writeFile(TMP_FILE_NAME, buffer, err => {if (err) {console.log('创建 Excel 导出文件失败')throw new Error(err)}})
}/*** 上传文件*/
function uploadFile() {let MyFile = new BaaS.File()return MyFile.upload(TMP_FILE_NAME, {category_id: EXPORT_DATA_CATEGORY_ID}).catch(err => {console.log('上传文件失败')throw new Error(err)})
}module.exports = async function(event, callback) {try {const date = new Date().getTime()const groupInfoArr = []const groupInfoSplitArr = []const [jobId, totalCount] = await Promise.all([createExportJobIdRecord(TABLE_ID.export_task), getTotalCount(TABLE_ID.order)])const groupSize = Math.ceil(totalCount / LIMIT) || 1for (let i = 0; i < groupSize; i++) {groupInfoArr.push({offset: i * LIMIT,limit: LIMIT,})}console.log('groupInfoArr:', groupInfoArr)const length = Math.ceil(groupInfoArr.length / MAX_CONNECT_LIMIT)for (let i = 0; i < length; i++) {groupInfoSplitArr.push(groupInfoArr.splice(0, MAX_CONNECT_LIMIT))}console.log('groupInfoSplitArr:', groupInfoSplitArr)const date0 = new Date().getTime()console.log('处理分组情况耗时:', date0 - date, 'ms')let num = 0// 分批获取数据const getSplitDataList = index => {return Promise.all(groupInfoSplitArr[index].map(v => {return getDataByGroup(TABLE_ID.order, v.offset, v.limit)})).then(res => {++numresult.push(...Array.prototype.concat(...res))if (num < groupInfoSplitArr.length) {return getSplitDataList(num)} else {return result}})}Promise.all([getSplitDataList(num)]).then(res => {const date1 = new Date().getTime()console.log('结果条数:', result.length)console.log('分组拉取数据次数:', num)console.log('拉取数据耗时:', date1 - date0, 'ms')genExportFile(result)const date2 = new Date().getTime()console.log('处理数据耗时:', date2 - date1, 'ms')uploadFile().then(res => {const fileLink = res.data.file_linkconst date3 = new Date().getTime()console.log('上传文件耗时:', date3 - date2, 'ms')console.log('总耗时:', date3 - date, 'ms')updateExportJobIdRecord(TABLE_ID.export_task, jobId, fileLink).then(() => {const date4 = new Date().getTime()console.log('保存文件下载地址耗时:', date4 - date3, 'ms')console.log('总耗时:', date4 - date, 'ms')callback(null, {message: '保存文件下载地址成功',fileLink,})}).catch(err => {callback(err)})}).catch(err => {console.log('上传文件失败:', err)throw new Error(err)})})} catch (err)
三、部署并测试
跟 npm 一样,部署前需要先登录,请参照文档配置。
使用以下命令即可将云函数部署到知晓云:
run deploy
执行结果如下:
使用以下的命令来测试:
mincloud invoke export-excel-filebr
执行结果如下:
export_task 表记录:
上传到知晓云的 excel 文件如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8xgPW2iK-1588065248145)(https://cloud-minapp-11491.cloud.ifanrusercontent.com/1h3eeGNECR14zCdk.png)]
文件内容:
四、参考文档
知晓云开发文档:https://doc.minapp.com/
node-xlsx 文档:https://www.npmjs.com/package/node-xlsx
五、源码
仓库地址:https://github.com/ifanrx/export-excel-file
相关阅读
第一期:快速实现图片爬虫
第二期:快速生成分享海报
第三期:处理微信卡券消息
第四期:自动回复客服消息
第五期:生成带参数的二维码
关注「知晓云」公众号,点击菜单栏「知晓云」-「知晓课堂」,获取更多开发教程。
第六期:如何通过知晓云将数据表导出为 Excel 文件相关推荐
- 微信小程序-知晓云等云产品导出excel
参考链接:微信小程序通过知晓云云函数导出excle(无须后台开发)_流转往复的博客-CSDN博客 我是参考这篇文章做的,可以实现导出静态的excle,如果有更多的需求可以在此基础上自行拓展. 前言 我 ...
- ipv4v6双栈技术_【第二十六期】IPv6系列应用篇——数据中心IPv4/IPv6双栈架构探讨...
背景 2017年,工业和信息化部发布了<推进互联网协议第六版(IPv6)规模部署行动计划>的通知,从国家层面推动下一代IP技术--IPv6的普及和应用.目标到2020年末,IPv6活跃用户 ...
- 第十六期:简单的介绍一下大数据中最重要的MapReduce
MapReduce是分布式运行的,由两个阶段组成:Map和Reduce,Map阶段是一个独立的程序,有很多个节点同时运行,每个节点处理一部分数据. MapReduce执行流程图 概述 MapReduc ...
- 第三期:如何通过知晓云处理微信卡券消息
作者:知晓云 - 小程序开发快人一步 来源:知晓课堂 知晓云新推出「消息推送」功能,该功能通过「消息推送」类型的触发器接收微信推送过来的消息,开发者可以对此消息实行相关操作. 此教程将带领大家体验这个 ...
- 微信小程序开发(以知晓云SDK作为后端)
本篇介绍知晓云SDK开发需要注意的地方. 目录 一.知晓云配置 二.微信开发者工具中配置知晓云插件 三.连接数据库 四.通过链接访问知晓云数据库中文件资源 4.3 在微信公众平台中配置知晓云数据库域名 ...
- 第16期高级转录组分析和R数据可视化培训(2022年1月)
福利公告:为了响应学员的学习需求,经过易生信培训团队的讨论筹备,现安排<高级转录组分析和R数据可视化>于2022年1月14-16 线上/线下课程 (线上课是通过腾讯会议实时直播线下课,实时 ...
- 【知云】第六期:数据级异地容灾如何实现?阿里云帮你打通数据的“任督二脉”...
摘要:国家要求网络借贷信息中介机构成立两年内,应当建立或使用与其业务规模相匹配的应用级灾备设施.那么如何规划容灾设施呢?本文中阿里云架构师半农将与大家分享阿里云异地容灾解决方案. 想要看视频版?请点击 ...
- 第四期:如何通过知晓云自动回复客服消息
作者:知晓云 - 小程序开发快人一步 来源:知晓课堂 在上篇推送完「卡券核销消息推送」的教程后,我们决定再多出点教程. 此次教程将再次带领大家体验「消息推送」,实现另一个「微信消息推送」的触发器,关于 ...
- 【第六期】拿不到offer全额退款 人工智能工程师培养计划招生
前 言 学院第四期课程在2019年10月结课,第一至第四期具有求职意向的同学中,目前已经有80%的同学拿到了国内外名企的AI算法岗位offer,或者国外名校的AI 硕士.全奖博士录取 offer.在大 ...
最新文章
- RHEL 5服务篇—使用Apache搭建web服务(四)部署AWStats网站分析系统
- 将选择元素绑定到Angular中的对象
- Emacs基础命令整理 - Unplugged - 博客频道 - CSDN.NET
- Scala隐式参数(隐式值)
- linux u盘新建文件夹加密,linux磁盘的加密保护以及u盘加密的方法。
- 【网络】几种常见的协议
- 函数指针以及在类成员函数中应用函数指针
- c语言贪吃蛇(简易版本含完整代码)
- HackerRank Word Order
- 如何提高FPGA的工作频率
- rfm模型python_Python pandas RFM模型应用实例详解
- Julia文件和文件夹相关基础函数01
- HAKE笔记:Learning Hierarchy-Aware Knowledge Graph Embeddings for Link Prediction
- HBase的数据模型和存储原理
- “没用”的StringBuffer,StringBuffer被StringBuilder取代的原因
- AD——PCB布线实用技巧
- 选购kvm需要注意的重要事项
- 使用Maven WAR插件实现多Web应用间的重迭运用
- 《离散数学》学习笔记
- MATLAB编写遗传算法求解vrp问题