使用Evaluate写入其他单元格的UDF是不可预测的

时间:2017-04-24 23:34:28

标签: excel vba excel-vba udf

我不愿意提出有关UDF设计用于写入其他单元格的问题,因为根据设计,这种行为应该被禁用。但是......无论如何,我将通过所有潜在的批评来解决问题。我真的不希望完全回答这个问题,所以我只是想了解我遇到的奇怪行为。

我有一个UDF,旨在计算允许的简单轴承。它需要10个参数。如果任何参数超出范围,UDF将在调用单元格中返回“Error”。我希望通过列出所有违规输入来提高这个相当无用的反馈,以便用户不必一个接一个地进行单个校正。这样就会列出所有不良输入,用户可以立即纠正所有输入。仅供参考,由于某些输入交互,输入有10个以上的潜在问题。否则,用户可以尝试按摩输入数十次但没有成功。这就是我想立刻列出所有反馈的原因。

UDF:速记 - 它将数据发送到类模​​块以执行所有检查和计算。

public Function LBA(ByVal layup_string As String, ByVal diaBolt As Double, ByVal boltHead As String, _
ByVal eD As Double, ByVal tMetallicFitting As Double, ByVal tempF As Double, ByVal depth As Double, _
ByVal allowable_type As String, ByVal basis As String, ByVal cond As String) As Variant
    '
    ' declare variables
    Dim s As String
    Dim val As Variant
    Dim clba As New cFunc_LBA
    '
    ' send to class constructor 
    clba.init layup_string, diaBolt, boltHead, eD, tMetallicFitting, tempF, depth, allowable_type, basis, cond
    '
    ' get errors
    If clba.contains_errs Then ' ............................... check for design space violattions: errors
        s = clba.get_errs ' .................................... get concat string of all errors
        Evaluate ("post_error_messages(""" & s & """)") ' ...... run the subroutine to post err msgs
        val = "Error" ' ........................................ return value to calling cell
        '
    Else
        '
        ' return a valid bearing allowable
        val = clba.LBA ' ....................................... expose bearing allowable property
        '
    End If
    '
    LBA = val
End Function

类模块按预期工作。所有计算和错误日志都有效。在UDF中,当我检查是否有错误时,它返回错误。然后我将错误(在一个长串联字符串中)发送到另一个子程序,该子程序应该将错误输出到其他工作表单元格中。

The Sub:

Private Sub post_error_messages(ByVal s As String)
    ' declare variables
    Dim arr As Variant
    '
    ' initialize variables
    arr = Split(s, ",")
    '
    ' post error messages
    For i = 0 To UBound(arr) ' .................. loop thru error messages
        m.Cells(17 + i, 2) = CStr(arr(i)) ' ..... write msg in cell, increment by ROW#
    Next i
End Sub

我一路上注意到的一个怪癖...我只能得到子程序(由Evaluate调用)来接受一个参数。此外,我只能接受一个简单的数据类型string。我尝试了arraysvariantsscripting.dictionary但都没有效果。因此,所有我的错误消息连接成一个长字符串然后拆分并循环在子。

我现在的问题是这个设置只是有点工作。

问题1:无论返回多少错误,Sub to post错误消息将只返回三个项目。事实上它总是返回三个项目,即使只有两个项目(显示的最后一项重复)。如果有10条错误消息 - 显示3条错误消息。我在我的错误消息sub中放了debug.print语句,这样我就可以看到发生了什么,它表明当只返回2个错误消息时,它应该只打印到2个单元格,但它仍打印到第三个单元格。超过3个错误就会被删除。

问题2:如果我删除显示错误消息的工作表中的单元格并再次执行UDF,则消息将不会返回。只有当我关闭工作簿并再次打开它时,错误消息子例程才会再次打印到单元格(来自UDF)。

此外,这不是一个真正的问题,Evaluate运行两次。我看了这个,这似乎是一个已知的问题。我只是把它放在那里,但我不确定这会导致任何问题。

同样,由于我的工作超出了Excel UDF的预期功能,我不期望有一个解决方案。那就是说,任何人都可以对此提出任何见解吗?

1 个答案:

答案 0 :(得分:2)

不是你问题的答案,但这个精简版本对我来说没问题:

Public Function LBA() As Variant
    Dim val, s

    s = "A,B,C,D,E"

    Evaluate "post_error_messages(""" & s & """)"

    val = "Error" '

    LBA = val
End Function

Private Sub post_error_messages(s As String)

    Dim arr As Variant, i

    With Sheet1.Cells(17, 2)
        .Resize(10, 1).Value = "" '<<< clear any previous errors!
        arr = Split(s, ",")
        .Resize(UBound(arr) + 1, 1).Value = Application.Transpose(arr)
    End With

End Sub