为什么ExecuteExcel4Macro的返回结果总是False?

2 投票
3 回答
2443 浏览
提问于 2025-04-17 04:24

在使用 ExecuteExcel4Macro 在 Python 中运行 Excel 宏时,我总是得到一个 False 的结果,下面是我执行的代码:

import win32com.client

filename = r'E:\excel.xls'
xlApp = win32com.client.Dispatch('Excel.Application')
xlApp.visible = 1
xlBook = xlApp.Workbooks.Open(filename)

strPara = xlBook.Name + '!Macro1()'
res = xlApp.ExecuteExcel4Macro(strPara)
print res

xlBook.Close(SaveChanges=0)

而 "print res" 语句的输出是:False

我在 MSDN 上查找了 ExecuteExcel4Macro 的用法,得到了以下信息:

ExecuteExcel4Macro -- 运行一个 Microsoft Excel 4.0 宏函数,然后返回该函数的结果。返回的类型取决于函数。

然后我就困惑了:因为 Excel 中的宏总是一个 "Sub 过程",而在 VBA 中 "Sub 过程" 是没有返回结果的,那 Excel 宏怎么能返回结果呢?那么上面例子中的 False 结果又代表什么呢?

之后,我尝试在 Excel(2003)中用 VBA 而不是 Python 来使用 ExecuteExcel4Macro

Sub RunMacro()
    res = ExecuteExcel4Macro("excel.xls!Macro1()")
    MsgBox CStr(res)
End Sub
Sub Macro1()
    MsgBox "in Macro1"
End Sub

而在 MsgBox 中显示的 "res" 字符串也是一样:False

1. 为什么 ExecuteExcel4Macro 的返回结果总是 False?

2. 如果我想在 Python 中运行一个 Excel 宏并获取该宏函数的退出状态,我该怎么做?


更新于 2011.10.28:

Sub TEST()
    res = Application.Run(MacroToRun)
    MsgBox CStr(res)
End Sub

Function MacroToRun()
    MacroToRun = True
End Function

在 Excel 2003 中运行 TEST 宏后,我得到了这个:

一个对话框显示 "错误 2015" 的信息。

3 个回答

0

这是关于2020年的一些额外信息。需要注意的是:我使用的是Excel Pro Plus 2016。这个评论只是为了帮助其他人避免我经历的痛苦和浪费的时间。对一些程序员来说,这可能很明显,但我当时不知道,也在网上找不到任何关于这个问题或限制的建议。

经过很多痛苦的尝试,我发现你不能在一个函数(用户自定义函数,UDF)中运行ExecuteExcel4Macro。同时,我也发现你不能在一个函数中调用一个运行ExecuteExcel4Macro的子程序。这样做会导致函数在ExecuteExcel4Macro处结束,并在单元格中返回#Value!。我当时没有运行错误捕捉系统。这可能是上面问题的原因,但我不确定在旧版Excel中是否会有不同的结果。

背景信息:我有一个单元格,想测试用户是否改变了颜色,或者条件格式是否改变了颜色。我想知道屏幕上显示的是什么颜色。我尝试了一个函数(UDF),但在使用.displayformat时遇到了问题。在函数中无法使用.displayformat。

所以我想我可以使用Get.Cell(63,cell)。为此,我需要使用ExecuteExcel4Macro,但它在函数(UDF)中无法工作。这会导致函数崩溃,出现Error2015的错误。不过,它在宏中单独运行是可以的。

我使用了一个命名范围,公式为=GET.CELL(63,INDIRECT("rc",FALSE)),用于条件格式,这样做没有问题。

以下是我在函数(UDF)中测试的一些代码。在定义TempA后,我会跳转到Temp = ...

TempA = Application.ExecuteExcel4Macro("Sqrt(4)")

TempA = Application.ExecuteExcel4Macro("GET.CELL(42)")

TempA = "GET.CELL(63,HistorySheet!" & MyCell.Address(ReferenceStyle:=xlR1C1) & ")"

Temp = ExecuteExcel4Macro(TempA)

ExecuteExcel4Macro在函数(UDF)中的问题对一些程序员来说可能很明显,但我当时不知道,也在网上找不到任何相关的信息。希望这能帮助到未来的某个人。

0

你可以通过这个 Excel 4 宏和 ExecuteExcel4Macro 方法来调用一个 VBA 自定义函数(UDF):

retval = Application.ExecuteExcel4Macro("EVALUATE(""Book1!some_UDF()"")") 

使用 Excel 4 宏函数 EVALUATE() 的话,你就无法在 VBE 调试模式下进入名为 "some_UDF" 的自定义函数,就像你从 Excel 4 宏调用它时那样(见示例)。

我还发现,Application.Caller 在自定义函数中根本不能提到,否则 Excel 会崩溃。

示例

这是一个 Excel 4 宏表,里面有以下内容(单元格 $A$1 被命名为 "Macro1",通过名称管理器设置):

$A$1: Macro1
$A$2: =RETURN(Book1!some_UDF())

Excel 工作表中的单元格

$A$1: =Macro1()

总的来说,我怀疑这个示例之所以能正常工作,是因为 Excel 使用了它自己的 Application.Evaluate 来获取 VBA 自定义函数的结果(假设是整数 10),然后像这样运行 Excel 4 宏:

$A$1: Macro1
$A$2: =RETURN(10)

实际上,在 VBA 时代之前的 1992 年,当时只有 Excel 4.0 宏函数,=RETURN(Book1!some_UDF()) 是不可能工作的,这简直不可思议(虽然没有验证,但我看不出它怎么能工作...)

所以如果想在 VBA 中实现完全相同的行为,调用方式应该是:

retval = Application.ExecuteExcel4Macro("EVALUATE(" & Application.Run("Book_XL4M!test_10") & ")")
0

你可以定义Excel函数,不是从sub开始,而是从function开始:

Function Area(Length As Double, Optional Width As Variant)
    If IsMissing(Width) Then
        Area = Length * Length
    Else
        Area = Length * Width
    End If
End Function

这个函数应该返回一些东西。这个东西就是用函数名字命名的变量的内容(这里是Area)。

撰写回答