【工具框架分享】在本地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

北京
浏览 935
1
2
分享
2 +1
4
1 +1
全部评论 4
 
不定时出现ScriptRetryLater
· 广东省
回复
我还没注意过这问题,需要官方看下,补充文档解释各种错误编号意思。 我猜有种可能可能是单个文档里单次只能执行一个脚本,你有没可能跑并发了,还没等上一次程序运行完?但是我这篇文章给的框架默认也没并发机制呀~
· 福建省
回复
 
近来发现本地wps表格可以使用vba编程,请问如何调用webhook进行与在线表格进行交互沟通啊?
· 广东省
回复
wils

创作者俱乐部成员

vba可以通过winhttp等com对象发http请求
· 广东省
回复