excel - VBA - 在 Evaluate() 中包含自己的函数

标签 excel vba function evaluate

在 VBA 中,我习惯于使用 Evaluate() 计算列的值,这是另一列的函数,以便不使用循环。例如,要评估第 2 列,其值是第 1 列值的指数,我会写(这里限于前 10 行):

Dim rng1 As Range
Dim rng2 As Range

Set rng1 = Worksheets("Sheet1").Range(Cells(1,1),Cells(10,1))
Set rng2 = Worksheets("Sheet1").Range(Cells(1,2),Cells(10,2))

rng2 = Evaluate("EXP(" & rng1.Address & ")")
我现在想以同样的方式处理我自己的功能。为了进行测试,我创建了一个返回输入指数值的函数:
Function TestExpo(alpha) As Double
    TestExpo = EXP(alpha)
End Function
我以与之前 Evaluate() 相同的方式进行操作:
rng2 = Evaluate("TestExpo(" & rng1.Address & ")")
我没有收到错误,但 Excel 工作表上什么也没发生。我试图通过在函数名称中输入错误来触发错误,例如:
rng2 = Evaluate("TestEx(" & rng1.Address & ")")
我实际上在工作表上 rng2 的每个单元格处都出现了“名称”错误。因此,调用函数“TestExpo”有效。我还尝试使用实数而不是 rng1.Address:
rng2 = Evaluate("TestExpo(" & 2 & ")")
并且我在工作表上 rng2 的所有单元格中都得到了正确的 exp(2) 值,因此调用该函数并取回单元格中的值就是这样工作的。
我试图以不同的方式指定输入和输出的类型。例如:
Function TestExpo(alpha) ' No error, but no values on the sheet
Function TestExpo(alpha) As Range ' No error, but no values on the sheet
Function TestExpo(alpha) As Variant ' No error, but no values on the sheet
Function TestExpo(alpha As Range) ' No error, but no values on the sheet
Function TestExpo(alpha As Variant) ' No error, but no values on the sheet
Function TestExpo(alpha As Double) ' Value error for each cell of the range rng2
除了最后一次使用 alpha As Double 进行的测试外,我没有收到任何错误,但 Excel 表上也没有任何值。
我的想法不多了...我试图找到VBA的EXP()函数的代码,以查看如何指定输入和输出,认为如果我在函数“TestExpo”中使用相同的类型和参数,它可能有效,但我找不到 EXP() 函数的代码,它可能不是公开的。
有没有人遇到过类似的情况并解决了?
亲切的问候
泽维尔

更新:
感谢您的贡献!我继续前进!
当我使用时,正如@FaneDuru 所建议的那样
rng2 = Evaluate("""=TestExpo(" & rng1.Address & ")""")
我在每个单元格中都有一个值错误。检查工作表中的单元格,我可以看到每个单元格都归因于公式:
"=@TestExpo($A$1:$A$35)"
我与写作相比
rng2 = Evaluate("""=EXP(" & rng1.Address & ")""")
哪个起作用并将公式归因于每个单元格
"=EXP(@$A$1:$A$35)"
所以@出现在不同的位置。我手动将公式“=@TestExpo($A$1:$A$35)”更正为“=TestExpo(@$A$1:$A$35)”,它成功了!
所以问题是@的位置,我不明白为什么@在使用函数EXP时默认放在括号内的范围前面,但在使用我自己的函数时放在函数名前面。
然而,手动更正单元格中的公式并不方便。受@FaneDuru 提议的启发,我通过以下方式在范围名称后添加 .Cells(1,1).Address(0,0) 来更正我的代码:
rng2 = Evaluate("""=TestExpo(" & rng1.Cells(1,1).Address(0,0) & ")""")
这行得通!
现在,第一个单元格中的公式如下所示:
"=@TestExpo(A1)"
并且单元格地址适应每一行(第2行公式为“=@TestExpo(A2)”,第3行“=@TestExpo(A3)”等)
@ 仍然出现在函数名称的前面,但括号内有一个单元格名称而不是范围,这使得公式有效。
现在我不得不承认我并不真正了解代码语法是如何工作的。实际上,添加 .Cells(1,1).Address(0,0),我希望 rng2 的所有单元格都将引用范围 rng1 的 Cell(1,1),但公式却适应了每个单元格以适当的方式。
所以,我最初的问题已经解决了:
rng2 = Evaluate("""=TestExpo(" & rng1.Cells(1,1).Address(0,0) & ")""")
甚至更简单:
rng2 = "=TestExpo(" & rng1.Cells(1,1).Address(0,0) & ")"
尽管如此,我还是很想了解代码语法是如何工作的——即,如果代码明确引用了 rng1.Cells(1,1).Address(0,0) 中的 cell(1,1),那么怎么可能rng2 的单元格不是指单元格(1,1),而是指正确的单元格(单元格(2,1)、单元格(3,1)等)?
而且我还想了解为什么 @ 在使用函数 EXP 时默认放在范围前面,但在使用我自己的函数时放在函数名前面。有人会有想法吗?

最佳答案

不幸的是,我认为你不能以这种方式做你想做的事。
我认为您的示例没有达到您的预期。

rng2 = Evaluate("EXP(" & rng1.Address & ")")
将返回一个值数组,但只会将第一个值输入到 rng2 中的每个单元格中。 .
所以,即使你可以模仿 EXP 正在做的事情,它仍然不会做你想做的事情。
但是,如果您仍想模仿 EXP 获得的(可能不正确的)功能,功能:
EXP 和您的 UDF 之间的区别在于 EXP 函数可以处理和返回数组,而您的 UDF 不能。
这是一个非常快速的功能,可以(并且应该)显着改进,但它可能会给您一个起点。
Public Function test(a As Variant) As Variant
    Dim arr() As Double
    If IsNumeric(a) Then
        ReDim arr(1 To 1)
        arr(1) = Exp(a)
    Else
        ReDim arr(1 To a.Count)
        Dim i As Long
        For i = 1 To a.Count
            arr(i) = Exp(a(i))
        Next i
    End If
    test = arr
End Function
更新:
显然,EXP 之间似乎也存在差异。工作表和 VBA 版本的公式中使用的函数。
VBA 版本只接受一个单元格或值,而工作表版本能够接受一个范围/值数组。
通常,您可以使用 Application.WorksheetFunction 访问工作表版本。 ,但不幸的是,这似乎不适用于 EXP .

关于excel - VBA - 在 Evaluate() 中包含自己的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69086467/

相关文章:

mysql - 如何创建超过 4096 列的 MySQL 表?

vba - 运行时错误 '1004' Range.boarders

sql-server-2008 - 首次运行时自动刷新 Excel 中的数据透视表数据

vba - 我应该在退出子过程之前重新打开.CutCopyMode吗?

VBA [Internet Explorer] - 按钮提交(登录)

c - C语言中函数指针的理解

windows - 抑制 'Excel has stopped working' 对话框

vba - excel vba中出现错误 “Out of Memory”

c - 需要帮助在 C 中创建给出特定数量\n 的函数

c++ - sizeof(function) 有意义吗?