【问题标题】:Circular Error in VBA User defined FunctionVBA用户定义函数中的循环错误
【发布时间】:2018-02-20 15:20:01
【问题描述】:

我是 VBA 编程的新手,并且编写了一个用于插值的 VBA 函数。 我尝试从单元格 C17 和 C 列中的其他单元格获取输入到函数“WindPressure”

该函数然后从列 C( 离地高度 z (m) ) 获取输入并进行插值以获得设计风压,但由于圆形误差而失败。

代码如下:

Function WindPressure(z As Double) As Double

      Dim Row_Nos As Integer

      Dim x1 As Double
      Dim x2 As Double
      Dim x3 As Double

      Dim y1 As Double
      Dim y2 As Double
      Dim y3 As Double

      ' Select first line of data.
      Range("T13").Select

      ' Set Nos of row to interploate
      Row_Nos = 12

      ' Interpolation for Design Wind pressure
      For i = 0 To Row_Nos

         ' Case 1: <= 5m
         If i = 0 And z <= ActiveCell.Value Then

            WindPressure = ActiveCell.Offset(0, 1).Value

            ' Shifting Back
            ActiveCell.Offset(0, -1).Select

            'Exit If Enter this if statement
            Exit Function

         ElseIf i >= 0 And z <= ActiveCell.Value Then


         ' Case 2: > 5m
            x1 = z

            x2 = ActiveCell.Offset(-1, 0).Value

            x3 = ActiveCell.Offset(2, 0).Value

            y2 = ActiveCell.Offset(-2, 1).Value

            y3 = ActiveCell.Offset(2, 0).Value

            y1 = ((x1 - x3) / (x2 - x3) * (y2 - y3)) + y3
            WindPressure = y1

            ' Shifting Back
            ActiveCell.Offset(-1, -1).Select

            'Exit If Enter this if statement
            Exit Function

         End If
            ActiveCell.Offset(1, 0).Select
      Next i


End Function
  1. 谁能告诉我脚本中的哪一步是错误的
  2. 有没有方便的功能测试?因为它不像是直接按F5键执行的程序

非常感谢您的关注和帮助。

【问题讨论】:

    标签: vba excel excel-udf


    【解决方案1】:

    这是如何使用 F5F8 作为过程来调试它:

    Public Sub TestMe()
    
        Debug.Print windpressure(7)
    
    End Sub
    
    Function windpressure(z As Double) As Double
    
        Stop
        'the rest of the function
    '    Dim Row_Nos As Integer
    '    Dim x1 As Double
    '    Dim x2 As Double
    '    Dim x3 As Double
    
    End Function
    

    现在按 F8 运行 TestMe 并享受调试。


    另一种方法是在即时窗口中写入?WindPressure(7),并在VB 编辑器中放置一个停止标志。它会逐行进行。


    关于错误,请从函数中删除Select 部分,VBA 不允许您在那里使用它。

    【讨论】:

    • 使用Sub 调用函数(或从即时窗口调用它)意味着它将不再被视为UDF,并且与从Excel 调用的行为截然不同。 (消除大多数错误很有用,但如果函数试图修改环境则无济于事 - 这在普通函数中是允许的,但在 UDF 中是不允许的。)
    • @YowE3K - 这真的很有趣,你能举一些例子吗?
    • 嗯,最明显的就是发生错误时会发生什么。当从 Excel 调用时,它会立即停止并返回 #VALUE! 错误,但从 VBA 调用它会崩溃。下一个最明显的是,当从 Excel 调用时,诸如 Range("A1").Value = 7 之类的语句将导致 UDF 停止并返回 #VALUE!,但当从 VBA 调用时,它将更新单元格的值并继续。
    • @YowE3K - 不错,我几乎从不通过 excel 调用函数。但即使我这样做了,我也在用停车标志调试它们,到目前为止还没有注意到/经历过任何这些错误。部分是因为我从来没有在函数中写过Range("A1").Value = 7...
    • @YowE3K:非常感谢!我已经尝试过您建议的调试方式,但它似乎效果很好,因为我尝试跟踪 ActiveCell 的值,其值在我尝试在代码中执行时不断变化。就像UDF可以真正“改变excel环境”一样。
    【解决方案2】:

    正如@YowE3K 所指出的,当函数尝试修改环境时,调试无济于事。

    因此,您的代码尝试选择在 UDF 中无法执行的范围 T13。在此之后,对ActiveCell 的任何引用都是错误的,尝试更改活动单元格会失败,因为您无法修改环境。

    附带说明,您也没有将Option Explicit 放在模块的顶部,否则它还会抱怨您没有声明变量i

    因此,与其更改ActiveCell,不如设置一个对您需要的单元格的引用。每当您使用 ActiveCell 时,请改用该范围引用。

    Option Explicit
    
    Function WindPressure(z As Double) As Double
    
          Dim Row_Nos As Integer
    
          Dim x1 As Double
          Dim x2 As Double
          Dim x3 As Double
    
          Dim y1 As Double
          Dim y2 As Double
          Dim y3 As Double
    
          Dim i As Long
          Dim rT13 As Range
    
          ' Select first line of data.
          'Range("T13").Select '**** Won't work in a UDF ****
          Set rT13 = Range("T13") 'Set a reference to T13 instead.
    
    
          ' Set Nos of row to interploate
          Row_Nos = 12
    
          ' Interpolation for Design Wind pressure
          For i = 0 To Row_Nos
    
             ' Case 1: <= 5m
             If i = 0 And z <= rT13.Value Then
    
                WindPressure = rT13.Offset(0, 1).Value
    
                'Exit If Enter this if statement
                Exit Function
    
             ElseIf i >= 0 And z <= rT13.Value Then
    
    
             ' Case 2: > 5m
                x1 = z
    
                x2 = rT13.Offset(-1, 0).Value
    
                x3 = rT13.Offset(2, 0).Value
    
                y2 = rT13.Offset(-2, 1).Value
    
                y3 = rT13.Offset(2, 0).Value
    
                y1 = ((x1 - x3) / (x2 - x3) * (y2 - y3)) + y3
                WindPressure = y1
    
                'Exit If Enter this if statement
                Exit Function
    
             End If
          Next i
    
    End Function
    

    要检查您的代码,您可以在 Range("T13").Select 上设置一个断点并在 ActiveCell.Address 上添加一个监视 - 当代码到达该行时,您会看到 ActiveCell 仍然是您输入公式的单元格进入。

    【讨论】:

    • 达伦:非常感谢您的慷慨帮助!它有效!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-10
    • 2021-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多