LibreOffice Calc Python UDF 的基本包装器
Basic Wrapper for LibreOffice Calc Python UDF
如何使用非整数电子表格范围形成对 运行 LibreOffice Calc Python 用户定义函数的 Basic 包装器调用?
我不清楚如何为 values
和 excel_date
数组正确声明函数,这两个数组都是实数数组,在我理解的基本术语中键入 Variant。
我关注了Calling a python function from within LibreCalc and ranges can be passed as integer arguments without defining them but these are real values. Both arrays are single-dimension so the multi-dimensional array issues do not apply as discussed in How can I call a Python macro in a cell formula in OpenOffice.Org Calc?
基本代码为:
Function xnpv_helper(rate as Double, values() as Variant, excel_date() as Variant) as Double
Dim scriptPro As Object, myScript As Object
scriptPro = ThisComponent.getScriptProvider()
myScript = scriptPro.getScript("vnd.sun.star.script:MyPythonLibrary/Develop/math.py$xnpv_helper?language=Python&location=user")
xnpv_helper = myScript.invoke(Array(rate, values, excel_date), Array(), Array() )
end function
电子表格数据:
Date Amount Rate xnpv
31/12/19 100 -0.1
31/12/20 -110
xnpv_helper
在底部。实际 python 脚本基于 https://github.com/tarioch/xirr from financial python library that has xirr and xnpv function?
# Demo will run in python REPL - uncomment last line
import scipy.optimize
DAYS_PER_YEAR = 365.0
def xnpv(valuesPerDate, rate):
'''Calculate the irregular net present value.
>>> from datetime import date
>>> valuesPerDate = {date(2019, 12, 31): -100, date(2020, 12, 31): 110}
>>> xnpv(valuesPerDate, -0.10)
22.257507852701295
'''
if rate == -1.0:
return float('inf')
t0 = min(valuesPerDate.keys())
if rate <= -1.0:
return sum([-abs(vi) / (-1.0 - rate)**((ti - t0).days / DAYS_PER_YEAR) for ti, vi in valuesPerDate.items()])
return sum([vi / (1.0 + rate)**((ti - t0).days / DAYS_PER_YEAR) for ti, vi in valuesPerDate.items()])
from datetime import date
def excel2date(excel_date):
return date.fromordinal(date(1900, 1, 1).toordinal() + int(excel_date) - 2)
def xnpv_helper(rate, values, excel_date):
dates = [excel2date(i) for i in excel_date]
valuesPerDate = dict(zip(dates, values))
return xnpv(valuesPerDate, rate)
# valuesPerDate = {date(2019, 12, 31): -100, date(2020, 12, 31): 110}
# xnpv_helper(-0.10, [-100, 110], [43830.0, 44196.0])
感谢 @arturaz for explaining the Basic array comes to python as a tuple and needs converting to a list (best match for an array in python). Further details are given in his answer at 建立在问题和其他答案的基础上。
APSO python 控制台显示:
- 什么从 Basic 解析为 python
- 需要什么
- 需要带日期格式的数据
APSO python console [LibreOffice]
3.8.10 (default, Aug 10 2021, 19:39:20) [MSC v.1928 64 bit (AMD64)]
>>>
1: ((43830.0,), (44196.0,)) ((100.0,), (-110.0,)) -0.1
2: [43830.0, 44196.0] [-100, 110] -0.1
3: {datetime.date(2019, 12, 31): -100, datetime.date(2020, 12, 31): 110} -0.1
这两个数组在 python 辅助函数中使用之前被重新格式化:
def xnpv_helper(rate, values, excel_date):
excel_date0 = [a for b in excel_date for a in b]
values0 = [a for b in values for a in b]
dates = [excel2date(i) for i in excel_date0]
valuesPerDate = dict(zip(dates, values0))
return xnpv(valuesPerDate, rate)
如何使用非整数电子表格范围形成对 运行 LibreOffice Calc Python 用户定义函数的 Basic 包装器调用?
我不清楚如何为 values
和 excel_date
数组正确声明函数,这两个数组都是实数数组,在我理解的基本术语中键入 Variant。
我关注了Calling a python function from within LibreCalc and ranges can be passed as integer arguments without defining them but these are real values. Both arrays are single-dimension so the multi-dimensional array issues do not apply as discussed in How can I call a Python macro in a cell formula in OpenOffice.Org Calc?
基本代码为:
Function xnpv_helper(rate as Double, values() as Variant, excel_date() as Variant) as Double
Dim scriptPro As Object, myScript As Object
scriptPro = ThisComponent.getScriptProvider()
myScript = scriptPro.getScript("vnd.sun.star.script:MyPythonLibrary/Develop/math.py$xnpv_helper?language=Python&location=user")
xnpv_helper = myScript.invoke(Array(rate, values, excel_date), Array(), Array() )
end function
电子表格数据:
Date Amount Rate xnpv
31/12/19 100 -0.1
31/12/20 -110
xnpv_helper
在底部。实际 python 脚本基于 https://github.com/tarioch/xirr from financial python library that has xirr and xnpv function?
# Demo will run in python REPL - uncomment last line
import scipy.optimize
DAYS_PER_YEAR = 365.0
def xnpv(valuesPerDate, rate):
'''Calculate the irregular net present value.
>>> from datetime import date
>>> valuesPerDate = {date(2019, 12, 31): -100, date(2020, 12, 31): 110}
>>> xnpv(valuesPerDate, -0.10)
22.257507852701295
'''
if rate == -1.0:
return float('inf')
t0 = min(valuesPerDate.keys())
if rate <= -1.0:
return sum([-abs(vi) / (-1.0 - rate)**((ti - t0).days / DAYS_PER_YEAR) for ti, vi in valuesPerDate.items()])
return sum([vi / (1.0 + rate)**((ti - t0).days / DAYS_PER_YEAR) for ti, vi in valuesPerDate.items()])
from datetime import date
def excel2date(excel_date):
return date.fromordinal(date(1900, 1, 1).toordinal() + int(excel_date) - 2)
def xnpv_helper(rate, values, excel_date):
dates = [excel2date(i) for i in excel_date]
valuesPerDate = dict(zip(dates, values))
return xnpv(valuesPerDate, rate)
# valuesPerDate = {date(2019, 12, 31): -100, date(2020, 12, 31): 110}
# xnpv_helper(-0.10, [-100, 110], [43830.0, 44196.0])
感谢 @arturaz for explaining the Basic array comes to python as a tuple and needs converting to a list (best match for an array in python). Further details are given in his answer at 建立在问题和其他答案的基础上。
APSO python 控制台显示:
- 什么从 Basic 解析为 python
- 需要什么
- 需要带日期格式的数据
APSO python console [LibreOffice]
3.8.10 (default, Aug 10 2021, 19:39:20) [MSC v.1928 64 bit (AMD64)]
>>>
1: ((43830.0,), (44196.0,)) ((100.0,), (-110.0,)) -0.1
2: [43830.0, 44196.0] [-100, 110] -0.1
3: {datetime.date(2019, 12, 31): -100, datetime.date(2020, 12, 31): 110} -0.1
这两个数组在 python 辅助函数中使用之前被重新格式化:
def xnpv_helper(rate, values, excel_date):
excel_date0 = [a for b in excel_date for a in b]
values0 = [a for b in values for a in b]
dates = [excel2date(i) for i in excel_date0]
valuesPerDate = dict(zip(dates, values0))
return xnpv(valuesPerDate, rate)