xlwings:如何检测是否从VBA模块调用了python函数?

时间:2019-06-21 23:47:38

标签: python excel vba xlwings

情况

xlwings 软件包提供了一种方便的方法来call python functions from an excel VBA module xlwings 文档提供了以下基本示例:

  

将以下代码写入VBA模块。

Sub HelloWorld()
    RunPython ("import hello; hello.world()")
End Sub
     

这将在hello.py中调用以下代码:

# hello.py
import numpy as np
import xlwings as xw

def world():
    wb = xw.Book.caller()
    wb.sheets[0].range('A1').value = 'Hello World!'

尝试直接运行python函数world()(而不是从excel VBA调用)会显示以下错误消息:

  

异常:不能直接调用Book.caller()。通过呼叫   Excel或先通过Book.set_mock_caller()设置模拟调用者。

问题

我想修改world()函数,使其在直接运行时引发自定义异常。为了实现这一点,我首先需要以编程方式确定world()函数是直接运行还是从excel VBA调用(至少我是这样认为的)。我该怎么办?

1 个答案:

答案 0 :(得分:1)

您可以捕获异常,然后提出自己的例外:

def world():
    try:
        wb = xw.Book.caller()
    except Exception:
        raise CustomException(custom_message)
    wb.sheets[0].range('A1').value = 'Hello World!'

您担心Exception太笼统,这是正确的。但这是xlwings的错,而不是您的错。如果它提出了一个通用的Exception,那么您剩下的就是全部。您可以检查异常消息,以确保您没有捕获到错误的异常,但这会很脆弱。错误消息通常是无证的,不被视为公开的,稳定的API。

或者,您可以解决问题所在的地方xlwings' source code,并使其按照我的意愿做正确的事情:提出更具体的异常。

class NotFromExcelError(Exception):
    pass

caller的末尾:

raise NotFromExcelError('Book.caller() must not be called directly. Call through Excel '
                        'or set a mock caller first with Book.set_mock_caller().')

我希望这样的拉取请求会被接受,因为像现在这样提出一个裸露的Exception看起来确实是错误的。