在一张纸上重新计算Excel VBA功能会破坏其他纸张

时间:2016-06-08 07:23:54

标签: excel vba function

我创建了一个计算给定月份中项目数的函数。

A列是月份,B列是该月份的项目数。

Cell B1有:

=countItems(A1)

Excel数据:

Excel data

代码:

Function countItems(month)
    Application.Volatile
    Dim count As Integer
    If Not (month = 0) Then
        count = 0
        Do While Not (Cells(month.row + count + 1, 3) = 0)
            count = count + 1
        Loop
        countItems = count
    Else
        countItems = ""
    End If
End Function

我将公式从B1拖到B500,每个月都能正常运行。如果相应的A单元格中没有月份,则公式不返回任何内容。

我在类似结构的数据集上使用相同的公式有多张表。 只要列B中的值更新此工作表1,其他工作表也将更改。但是,工作表2将使用工作表1中的C列更新

如果我重新计算了Sheet 2,则Sheet 1将使用Sheet 2中的C列进行更新。

该函数通过检查C列在找到空白单元格之前可以读取的距离来计算给定月份中的项目数,表明月份已结束。 工作表2在第一个月有1个项目,但由于工作表1有3个项目(计数第1行到第3行,第4行停止),它仍然会返回3。 工作表2的第二个月从第3行开始。但由于该功能正在读取工作表1中的C列,在计算1个项目后将进入空白单元格(计数第3行并在第4行停止)。因此,无论Sheet 2 Month 2中有多少项,它都将返回1.

该功能始终使用正确的A列,并且只在B列中显示A列中有日期的数字。

结果是只有一张纸可以具有正确的值,这样做会破坏其他纸张。

我现在无法解决这个问题,因为我是VBA的新手。

我想过让所有功能的细胞参考都包括对当前细胞片的自我参考,但我不知道如何做到这一点,我不知道&#39 ;知道它是否有效。

编辑:我无法通过这种方式使其工作,但具有相对单元格位置的Application.Caller.Offset()可用作解决方案。我仍然想知道是否有办法使用绝对细胞位置。

这些表格未组合在一起。

1 个答案:

答案 0 :(得分:0)

它是因为有一个"时空转移"传递给函数的范围和范围"感觉"作为"来电者"一个由功能

您可以通过修改功能代码来查看此行为,如下所示

Function countItems(month)
    Application.Volatile
    Dim count As Integer

    Dim r As Range
    Dim p As Variant, a As Variant

    Set r = Application.Caller '<~~ retrieve the actual "calling cell" of the current function "instance"
    p = r.Parent.Name
    a = r.Address

    MsgBox p & " vs " & month.Parent.Name & vbCrLf & a & " vs " & month.Address '<~~ compare the function "calling cell" vs the "passed cell"

    If Not (month = 0) Then
        count = 0
        Do While Not (Cells(month.Row + count + 1, 3) = 0)
            count = count + 1
        Loop
        countItems = count
    Else
        countItems = ""
    End If
End Function

并且您将看到msgboxs提示您显示函数&#34;调用单元格&#34;并且&#34;通过了细胞&#34;地址和/或表格

所以为了避免这种行为,你可以只依赖&#34;呼叫范围&#34;,如下所示:

Option Explicit

Function countItems(month)
    Application.Volatile
    Dim r As Range

    Set r = Application.Caller '<~~ retrieve the actual "calling cell" of the current function "instance"

    'the "calling cell" is the one with the called function in its formula, i.e. in column "B" as per your data structure. then ...
    If Not IsEmpty(r.Offset(, -1)) Then '<~~ ... the column with dates are one column to the left, and  ...
        Do While Not IsEmpty(r.Offset(countItems + 1, 1)) '<~~ ...  the values to be checked for are one column to the right
            countItems = countItems + 1
        Loop
    End If
End Function