Excel UDF 将评估的 SUB 的值加倍

Excel UDF doubles value of the evaluated SUB

1. 我试图回答 VBA UDF to split string array,但在计算我的 UDF 时得到了令人不快的结果。

Public Function mytest(src, dest)
    dest.Parent.Evaluate "test(" & src.Address(False, False) & ", " & dest.Address(False, False) & ")"
    mytest = "wut"
End Function

Sub test(src As Range, dest As Range)
    Dim chr, rows, cols
    rows = 0
    cols = 0
    For chr = 1 To Len(src.Value)
        Select Case Mid(src.Value, chr, 1)
            Case ","
            rows = rows + 1
            Case ";"
            cols = cols + 1
            rows = 0
            Case Else
            Cells(dest.Row + rows, dest.Column + cols).Value = Cells(dest.Row + rows, dest.Column + cols).Value & Mid(src.Value, chr, 1) '
        End Select
    Next chr
End Sub

预期结果: 公式结果: 有人可以解释为什么它会使单元格的值加倍吗?
当我使用

调试 test
Sub ffs()
    Call test(Cells(1, 1), Cells(3, 1))
End Sub

我得到了预期的结果,所以我想问题不在 test Sub?..

2. 每当我尝试向 Function 和 Sub 添加更多参数(例如定界符)时,Function 根本不计算 Sub

Public Function CellToRange(src, dest, DelimL, DelimC)
    dest.Parent.Evaluate "test(" & src.Address(False, False) & ", " & dest.Address(False, False) & ", " & DelimL & ", " & DelimC & ")"
    CellToRange = "wut"
End Function

Sub CTR(src As Range, dest As Range, Delim1, Delim2)
    Dim chr, rows, cols
    rows = 0
    cols = 0
    For chr = 1 To Len(src.Value)
        Select Case Mid(src.Value, chr, 1)
            Case Delim1
            rows = rows + 1
            Case Delim2
            cols = cols + 1
            rows = 0
            Case Else
            Cells(dest.Row + rows, dest.Column + cols).Value = Cells(dest.Row + rows, dest.Column + cols).Value & Mid(src.Value, chr, 1) '
        End Select
    Next chr
End Sub

请帮助._。并提前致谢。
解决方案:
谢谢比利和查尔斯威廉姆斯。
变化

dest.Parent.Evaluate "CTR(" & src.Address(False, False) & ", " & dest.Address(False, False) & ", " & DelimL & ", " & DelimC & ")"

dest.Parent.Evaluate "0+CTR(" & src.Address(False, False) & ", " & dest.Address(False, False) & ", " & DelimL & ", " & DelimC & ")"

谢谢大家!

1) 它在触发公式时计算一次,并在函数更新单元格 A3 时再次计算(因为它是公式所依赖的单元格之一)。

2a) 你调用了错误的子程序(test 而不是 CTR

2b) 您需要使用类似

的方式调用您的第二个函数
=CellToRange(A1;A3;""",""";""";""")

或者将代码中调用 CTR 的行更改为

dest.Parent.Evaluate "CTR(" & src.Address(False, False) & ", " & dest.Address(False, False) & ", """ & DelimL & """, """ & DelimC & """)"

3) 我强烈建议您不要使用这种 hack 来获取 UDF 来更新包含该函数的单元格以外的单元格。

问题在于 Worksheet.Evaluate 方法,该方法用于绕过不允许 UDF 修改工作表结构的限制。

考虑这段代码

Option Explicit

Public Function dummyudf() As String
    Debug.Print "Calling Evaluate method"
    ActiveSheet.Evaluate "testsub()"
    Debug.Print "Returning From Evaluate method"
    dummyudf = "done"
End Function

Sub testsub()
    Debug.Print "testsub running"
End Sub

Sub testmacro()
    Dim s As String
    Debug.Print "testmacro running"
    s = dummyudf
End Sub

UDF dummyudf() 使用 Evaluate 方法 invoke Sub 调用 testsub()。这些与 OP 第 1 部分中的 mytesttest 以及第 2 部分中的 CellToRangeCTR 类似,但被剥离到最低限度。

testsub()也可以作为宏直接调用。第二个宏 testmacro 调用 dummyudf 作为 VBA.

中的函数

从立即 Window 获得以下输出:

可以看出

  • 当作为宏调用时:testsub() 表现如预期

  • dummyudf() 在工作表上作为 UDF 调用时(例如,通过将公式 =dummyudf() 添加到单元格 A1 Evaluate 方法似乎调用 testsub() 两次

  • dummyudf() 作为函数在 VBA 中被 运行 调用时 testmacro() 作为宏调用 Evaluate 方法似乎调用 testsub()两次

文档here建议Name方法的Worksheet.Evaluate参数应该是一个对象的名称,所以有点奇怪可以提供 Sub 的名称。它似乎还调用了任何此类 Sub 两次,这更令人惊讶,但确实强调了 YowE3K 的回答中关于不在 UDF 中使用此 hack 的建议。我会更进一步:不要将 Worksheet.Evaluate 与任何 Sub 一起使用。