【工具框架分享】在本地py环境获取在线表格数据进行处理
1 引言
1、之前我发过一个帖子:关于现有js和py能力边界的一些思考,以及我期望的"梦中情表"的编程工具是怎样的,讨论过jsa(指在线表格的AirScript语言,统称jsa)不擅长做数据分析,所以我们有时候就要用到py。
2、官方是有提供一个py的环境来操作表格的:
可以实现一些获取数据、修改数据保存回表格的功能。
3、但官方提供的py环境毕竟有些限制,有时候我们会需要在本地进行开发,就可以用到一些官方不支持的py三方库,或者要用到本地的一些文件数据、开发环境。甚至部署py后端服务,来支持跟jsa进行一些精细的交互联动。
这些话题我以后有空会逐步完善我的代码框架后,分享我遇到的一些具体问题,和思考到的解决方案。
4、这次主要先来讨论,在自己的py环境如何调用jsa(简称py-jsa),从而能与在线表格进行联动。
最基本的联动就是获取在线表格数据,这个通了,后续的如何修改表格,非数据类的特殊操作,乃至在jsa中调用py(jsa-py)道理都是类似的。
2 思路框架
1、py-jsa,主要就是用了官方提供的脚本令牌功能:https://airsheet.wps.cn/docs/apitoken/intro.html。
2、按照官方提供的示例思路,一般情况下,我们需要每个功能写一段脚本,复制一个id来调用。如果我们要用的功能很多,有的人会觉得操作很繁琐麻烦,维护不太方便。
3、所以我的想法,是在jsa做一个统一的大脚本,把各种需要的功能都作为一个函数写进去。py调用的时候,只要传递需要调用的函数名,和函数传参值,就能实现一套通用的py-jsa交互框架了。
其实这个本质效果,就是相当于在jsa搭建一个后端服务。
这是我实现的完整js脚本代码:https://github.com/XLPRUtils/pyxllib/blob/master/pyxllib/text/airscript.js,先看最后一段代码:
4、核心原理解释
可以在这段脚本里加上自己写的各种扩展、自定义函数功能,比如:
function add(a, b) { return a+b }
然后在第750行枚举所有直接调用的接口函数:
const funcsMap = {packTableDataFields, add}
这里利用了js的语法糖,实现了一个从函数字符串名可以映射取到函数本身的一个字典。
脚本令牌可以通过Context.argv传递参数值过来。
我这里框架默认使用funcName标记函数名,args存储参数列表。
完整实现:
// 1 这里填上要支持的函数接口清单
const funcsMap = {packTableDataFields}
// 2 支持三种触发方式,及优先级:py-jsa调用 > 选中单元格指定函数名 > 选中单元格所在第1列是触发函数名
let funcName = Context.argv.funcName || Selection.Cells(1, 1).Value2 || ''
if (!funcsMap[funcName]) funcName = ActiveSheet.Cells(Selection.Row, 1)
// 3 如果找得到函数则运行
if (funcsMap[funcName]) return funcsMap[funcName](...Context.argv.args)
// 4 也可以注释掉3,下面写自己手动调试要运行的代码
仅脚本令牌的考虑,这里实现其实不用这么复杂,我是有其他功能的兼容考虑,以后会解释。
从脚本令牌功能而言,这里简化后的逻辑如下:
const funcsMap = {packTableDataFields, add}
let funcName = Context.argv.funcName
if (funcsMap[funcName]) return funcsMap[funcName](...Context.argv.args)
这样的逻辑,就实现了一个js脚本,支持多个函数功能调用。
5、这个js脚本文件非常大,其实你们不需要的话可以全部删掉,只要取最后那段funcsMap触发调用的代码段即可。
那个脚本其实是我封装整理的一套jsa工具箱,包括了我之前分享的这部分功能:【AirScript工具代码分享】结构化解析表格数据区域
6、我这次就基于上次那套代码,介绍一个新的功能函数:packTableDataFields,这个是可以把在线表格数据打包成json,然后传递给py使用的。
7、在py可以写个客户端类,简化操作过程:https://github.com/XLPRUtils/pyxllib/blob/master/pyxllib/ext/wpsapi.py。
3 使用示例
现在在py就能这样取到在线表格的各种数据了:
import os
from pyxllib.ext.wpsapi import WpsOnlineBook
# 0 脚本令牌
os.environ['WPS_SCRIPT_TOKEN'] = 'my_token'
# 1 输入文件id,脚本id
wb = WpsOnlineBook('cly1BNKcBNo0', 'V2-5zlMqhErThAE4XiHchEc6g')
# 2 运行脚本的基础接口,可以拿到jsa里的原始输出结果
data = wb.run_script2('packTableDataFields', '顾客', ['编号', '名称', '料理喜爱'], [4, 10])
print(data)
# {'名称': ['莉格露', '橙', '露米娅', '稗田阿求', '茨木华扇', '上白泽慧音', '博丽灵梦'], '料理喜爱': ['猎奇,甜,生,肉', '水产,流行·喜爱,烧烤,甜,肉,重油', '招牌,流行·喜爱,猎奇,生,肉,饱腹', '和风,文化底蕴,汤羹,流行·喜爱,清淡,甜,高级', '下酒,和风,家常,文化底蕴', '中华,和风,家常,文化底蕴,流行·喜爱,清淡,素', '不可思议,实惠,流行·喜爱,甜,饱腹,高级'], '编号': [1, 2, 3, 4, 5, 6, 7]}
# 3 更高级,进一步封装的专门取表格数据的接口,默认返回df格式
df = wb.get_sheet_data('食材', ['编号', '名称', '标签', '价格'], [4, 10])
print(df)
# 价格 名称 标签 编号
# 0 8 鳟鱼 水产,鲜 1
# 1 14 八目鳗 招牌,水产,鲜 2
# 2 24 三文鱼 水产,高级,鲜 3
# 3 30 金枪鱼 水产,高级,鲜 4
# 4 34 极上金枪鱼 传说,水产,海味,高级,鲜 5
# 5 42 河豚 水产,海味,鲜 6
# 6 30 虾 水产,鲜 7
创作者俱乐部成员