VBA为变量分配了不正确的值

时间:2017-04-10 08:22:58

标签: excel vba excel-vba

我在VBA中有一个功能,它是更大设置的一部分。该函数位于Class Module内,基本上只是一个美化的减法。我想知道为什么我得到一些奇怪的结果,所以我(over-)简化了函数以进行调试。事实证明,其中一个变量并没有分配它应该的值,而是一些看似随机的值。一个简单的分配怎么会出错?

甚至更奇怪,为什么它并不总是分配不正确的值?它有时只会发生。其他时候是正确的。而且似乎根本没有评估任何东西,函数只返回0(零)。

从我所能看到的一切都不是我的代码的问题,而是与VBA的工作方式(幕后)相关。但只要我不理解它,就很难缓解。

代码:

Public Property Get MySubtractionFunction() As Double
    Dim tmpValue1 As Double
    Dim tmpValue2 As Double
    Dim tmpOutput As Double

    'When debugging, sometimes CDbl(Me.Value2) evaluates to approximately 18.000
    'However tmpValue2 evaluates to approximately 10.000
    tmpValue1 = CDbl(Me.Value1)
    tmpValue2 = CDbl(Me.Value2) 

    tmpOutput = tmpValue1 - tmpValue2 'Breakpoint is set at this line
    tmpOutput = Application.WorksheetFunction.Min(tmpOutput , tmpValue1)

    'Return output
    MySubtractionFunction= tmpOutput 

End Property

更新1 当我在到达断点之前将鼠标悬停在Me.Value2之上时,它实际上显示了分配给tmpValue2的值。如果我然后移除鼠标,然后再次将鼠标悬停在Me.Value2上,则会显示不同的值。如果没有执行任何代码,属性值如何才能改变呢?

更新2 也许我应该提一下,只有在循环中使用Class Object时才会出现问题。它被称为:

For i = 1 To 1000
    Dim myObject As myClass
    Set myObject = New myClass
    'Some initialization
    result = myObject.MySubtractionFunction
    'A bunch of other stuff
    Set myObject = Nothing
Next i

2 个答案:

答案 0 :(得分:0)

当处理双打(浮点)时,所有计算机语言都存在巨大问题。因此,在C#中,您应该使用decimal来避免此问题。在Excel中,你应该圆。

看一看微软对此的看法: https://support.microsoft.com/en-us/help/78113/floating-point-arithmetic-may-give-inaccurate-results-in-excel

答案 1 :(得分:0)

<强>解决方案

正如我所提到的,我遇到问题的属性是许多链中的最后一个。所有调用类模块的其他属性(链中的第一个除外)。这个问题起源很早,并且贯穿了所有步骤。

它是如此难以识别的原因是,当我在调试模式下将鼠标悬停在变量上以检查变量时,最初不正确的属性值被更新。

解决方案是以类似于原始帖子的方式扩展链中的所有步骤。这并不总是必需的,因为问题只表现在我快速运行多次计算时。但如果有人遇到类似的问题,我建议你试试这个问题。

这不起作用:

Public Property Get myProperty() As Double
    myProperty = Me.someOtherProperty + Me.aThirdProperty
End Property

这样做:

Public Property Get myProperty() As Double
    Dim tempSomeOtherProperty As Double
    Dim tempAThirdProperty As Double
    Dim tempResult As Double

    tempSomeOtherProperty = Me.someOtherProperty
    tempAThirdProperty = Me.aThirdProperty
    tempResult = tempSomeOtherProperty + tempAThirdProperty

    myProperty = tempResult

End Property