我正在为 Libre Office calc 编写第一个 Python 脚本。
按照各种指南,我安装了 APSO 并成功创建了一个调用 python 脚本的基本包装器。
这是它的签名:
Function python(functionName As String, ParamArray params) As Variant
functionName
是要调用的 python 方法的名称。params
是要传递的参数。functionName
的不同而有所不同,因此 params
数组没有预定义的大小和元素类型)
除非参数是单元格范围,否则这种方法效果很好。在这种情况下,单元格范围作为元组传递给 python,缺少有关行和列引用的信息。
为什么基本将单元格范围转换为元组而不是 CellRange 对象?
有没有办法检测
params
元素的类型,以便我可以以不同的方式管理单元格范围? (我尝试使用 TypeName(params(0))
但它似乎只适用于“字符串”等基本类型,如果参数是单元格范围,它会返回 Variant()
更多细节,因为我的问题不够清楚
这是我用 basic 编写的完整包装:
REM ***** BASIC *****
option compatible
Function python(functionName As String, ParamArray params) As Variant
Dim scriptPro As Object, myScript As Object
scriptPro = ThisComponent.getScriptProvider()
scriptPath = "vnd.sun.star.script:development.py$" & functionName & "?language=Python&location=user"
On Error GoTo ErrorHandler
myScript = scriptPro.getScript(scriptPath)
Dim outResult As Variant
outResult = myScript.invoke(params, Array(), Array())
python = outResult(0)
Exit Function
ErrorHandler:
python = CVErr(xlErrName)
End Function
我从计算公式栏中执行包装器,例如:
=python("custom_concatenate", "Hello ", "world")
或
=python("sum_all", A1:A10)
到此为止一切正常。
现在,假设我想创建一个方法,该方法接受一个范围并返回其第一行号和最后一行号的总和。
例如
=python("sum_row_numbers", B13:C24)
这是python方法的签名:
def sum_row_numbers(range):
range
参数只是元组的元组,此时对行和列的任何引用都是未知的。
如何确保包装器将有关范围的所有信息(包括单元格引用)传递给 python 方法?
要获取电子表格公式中使用的行号和列号,我们可以从
getFormula()
中提取它们。包括具有公式的单元格的地址。
import re
def sum_row_numbers(*params):
sCellAddress = params[-1]
oDoc = XSCRIPTCONTEXT.getDocument()
oSheet = oDoc.getCurrentController().getActiveSheet()
oCell = oSheet.getCellRangeByName(sCellAddress)
sFormula = oCell.getFormula()
match = re.search(r'[A-Z]+(\d+):[A-Z]+(\d+)', sFormula)
if match:
rownum, colnum = map(int, match.groups())
return rownum + colnum
return 0
例如,在单元格 A1 中输入以下公式并向下填充。
=PYTHON("sum_row_numbers"; B13:C24; CELL("address"))
结果:
37 39 41 43 45 47 49 51 53 55 57 59