【问题标题】:Cells reference not working in Excel VBA 2010 Function单元格引用在 Excel VBA 2010 函数中不起作用
【发布时间】:2013-03-18 06:06:18
【问题描述】:

我正在尝试编写一个函数,该函数采用一系列数据并从用户提供的列中计算两个数字的比率。我想在行尾打印这个比率,但由于某种原因,我无法使用单元格函数引用行中的最后一个单元格。相反,Cells 函数只是不断地向我提供该单元格的值,而不是单元格地址。我认为细胞功能也提供了地址。谁能告诉我这是错的还是我的代码错了?

这里是代码

Function calculateRatio(table As Range, numerator As Integer, denominator As Integer,       Optional nameOfRatio As String)
On Error GoTo ExpectedError
    Dim num As Double
    Dim denom As Double
    Dim ratio As Double

    If table.Columns.Count < 2 Then
        MsgBox ("Not enough data. Requires at least two or more rows.")
        Exit Function
    End If
    If numerator < 1 Or numerator > table.Columns.Count Then
        MsgBox ("Not an acceptable Numerator. Must be greater than zero and less than " & table.Columns.Count)
        Exit Function
    End If
    If denominator < 1 Or denominator > table.Columns.Count Then
        MsgBox ("Not an acceptable Denominator. Must be greater than zero and less than " & table.Columns.Count)
     Exit Function
     End If
    For Counter = 1 To table.Rows.Count
        num = table.cells(Counter, numerator)
        denom = table.cells(Counter, denominator)
        ratio = num / denom
        temp = table.cells(counter, table.columns.count)
        temp.Offset(0, 1).Value = ratio
     Next Counter

 Exit Function
ExpectedError:
    Call MsgBox("Something went wrong. Make sure you are referencing columns with numbers and not text." & Err.Number & " : " & Err.Description)
End
End Function

更新

这是更新后的代码:

Function calculateRatio(table As Range, numerator As Integer, denominator As Integer, Optional nameOfRatio As String)
    Dim num As Double
   Dim denom As Double
   Dim ratio As Double
   Dim temp As Range
   Dim counter As Integer

    If table.Columns.Count < 2 Then
        MsgBox ("Not enough data. Requires at least two or more rows.")
        Exit Function
    End If
    If numerator < 1 Or numerator > table.Columns.Count Then
        MsgBox ("Not an acceptable Numerator. Must be greater than zero and less than " & table.Columns.Count)
        Exit Function
    End If
    If denominator < 1 Or denominator > table.Columns.Count Then
         MsgBox ("Not an acceptable Denominator. Must be greater than zero and less than " & table.Columns.Count)
        Exit Function
    End If
    For counter = 1 To table.Rows.Count
        num = table.cells(counter, numerator)
        denom = table.cells(counter, denominator)
        ratio = num / denom
        Set temp = table.cells(counter, table.Columns.Count)
        temp.Offset(0, 1).Value = ratio
    Next counter
End Function

【问题讨论】:

  • 您是否尝试在工作表中将此函数作为 UDF 调用?
  • 我试图在工作表中将其称为 UDF。这会导致问题吗?
  • 您无法使用 UDF 操作工作表单元格。
  • 这只能使用子程序来完成吗?我之前已经能够使用子程序操作工作表单元格。
  • 是的,可以使用子程序来完成。有关更详细解释的一些链接,请参阅下面的答案。但一般来说,子程序可以操作工作表,而函数不能。 (从子例程中调用的函数可以,但是将函数用于除向子例程返回值之外的任何事情可能是一个坏习惯。

标签: excel excel-2010 vba


【解决方案1】:

无法从工作表调用的 UDF 中操作工作表单元格。

更多信息在这里:

https://stackoverflow.com/a/15647054/1467082

这里:

http://www.excel-it.com/UDF.htm

通常,子例程可以操作工作表,而函数不能。

例外是从子例程中调用的函数可以,但是将函数用于除向子例程返回值之外的任何事情可能是一个坏习惯。

【讨论】:

    【解决方案2】:

    我假设您没有在代码中使用 Option Explicit

    您需要将“temp”声明为一个范围。

    Dim temp As Range ' somewhere at the top of your function
    
    For Counter = 1 To table.Rows.Count
    ......
    Set temp = table.cells(Counter, table.columns.count)
    ...
    Next
    

    如果你有单元格坐标,为什么不手动偏移它呢?

    table.cells(counter, table.Columns.Count+1).Value = ratio
    

    试试这个:

    Function calculateRatio(table As Range, numerator As Integer, denominator As Integer, Optional nameOfRatio As String)
        Dim num As Double
       Dim denom As Double
       Dim ratio As Double
       Dim temp As Range
       Dim counter As Integer
    
        If table.Columns.Count < 2 Then
            MsgBox ("Not enough data. Requires at least two or more rows.")
            Exit Function
        End If
        If numerator < 1 Or numerator > table.Columns.Count Then
            MsgBox ("Not an acceptable Numerator. Must be greater than zero and less than " & table.Columns.Count)
            Exit Function
        End If
        If denominator < 1 Or denominator > table.Columns.Count Then
             MsgBox ("Not an acceptable Denominator. Must be greater than zero and less than " & table.Columns.Count)
            Exit Function
        End If
        For counter = 1 To table.Rows.Count
            num = table.cells(counter, numerator)
            denom = table.cells(counter, denominator)
            ratio = num / denom
            table.cells(counter, table.Columns(table.Columns.Count).Column + 1).Value = ratio
            'Set temp = table.cells(counter, table.Columns.Count)
            'temp.Offset(0, 1).Value = ratio
        Next counter
    End Function
    

    使用 `table.columns(table.columns.count).column 将确保您引用正确的列,暂时想不出一个会导致问题但最好是安全的示例。

    【讨论】:

    • 我不确定Option Explicit 是什么。也许?
    • 我会尝试做你的第二个选项,但由于某种原因,VBA 无法识别单元格为我返回一个范围。我不知道它发生了什么。
    • Option Explicit 将阻止您使用未声明的变量。将它放在代码的开头,Function 之前。这被认为是很好的做法。
    • 选项显式意味着您必须提前声明所有变量。它有助于防止打字问题。例如:temp = 1,当您实际输入双精度时,VBA 可能会将其解释为整数。
    • 它仍然无法正常工作。看起来我的 Cells 函数只返回数字而不是范围对象。
    【解决方案3】:

    尝试将Dim temp as Range 和chagne temp = table.cells(counter, table.columns.count) 添加到set temp = table.cells(counter, table.columns.count)

    实际上,您需要做的就是添加set,没有它,Variant temp 将变为long,有了它,Variant 将变为Range 对象。

    【讨论】:

    • 似乎已经做到了。 Set 规则是什么?我找不到任何关于为什么这不起作用的信息,而且这个错误是如此无用,以至于我不知道我需要一个。
    • Range是一个对象,需要设置对象。
    • 在 VBA 和 VB6 中,无论何时将变量分配给对象,都必须使用 Set。如果你有Dim temp as Range,你会得到一个更具描述性的错误,表明你需要一个Set。如果 temp 没有 Dim,则 temp 被认为是 Variant 类型,VBA 会为您确定它是 long 并将单元格值存储在其中,因为您没有使用 Set。如果您使用 Set VBA 将确定 temp 是对象并为其分配从单元格返回的 Range 对象。 cells 方法可以返回 Range 对象或单元格的值。
    • @derigible,我将不胜感激并接受我的回答,因为它解决了您的问题。
    • 实际上,经过测试,我仍然遇到同样的问题。我已经在顶部声明了dim temp as Range,并且我有'set temp = table.cells(counter, table.columns.count)`,但它仍然没有给我范围对象。相反,它仍然将我的单元格设置为单元格的值,而不是范围对象。
    猜你喜欢
    • 1970-01-01
    • 2014-04-02
    • 2012-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多