VBA为函数内的单元格赋值?

时间:2010-02-20 17:09:03

标签: excel vba excel-vba

无论如何,我可以为函数中的单元格指定值/名称吗?

谢谢

修改

很抱歉不清楚,这是我的要求。

我有一个用户定义的函数(= MyFunction()),可以从excel表调用。因此,当用户单击按钮时,我还有一个菜单按钮,我需要调用所有函数调用= MyFunction()。

我的计划是在MyFunction()内部,为调用单元格指定名称rerefence并将其存储在vba中。所以我可以有一系列的单元名称。然后,当单击菜单按钮时,我可以调用这些单元格引用。

请帮助我实现这一目标。有没有更好的方法来保持细胞参考?

2 个答案:

答案 0 :(得分:1)

编辑:

啊,现在我明白了。 最简单的方法是制作一个虚假的参数:MyFunction(ByVal r As Variant),并且,无论何时在工作表上使用此函数,都要提供与参数完全相同的单元格:=MyFunction(A1)。单击菜单项时,将A1中的值更改为任何值,并且所有MyFunction都将重新计算。

或者,您可以在函数体中使用Application.Volatile。这样,每次更改任何打开的工作簿中的任何单元格时,它都会重新计算。

也可以使用模块级集合来存储引用,但Excel有时会重置项目,从而丢失模块级变量。如果你有足够的勇气尝试:

Option Explicit

Private RefsToCalculate As New Collection

Public Function MyFunction() As Long
  Static i As Long

  i = i + 1
  MyFunction = i

  If TypeOf Application.Caller Is Excel.Range Then
    On Error Resume Next
    RefsToCalculate.Add Application.Caller, Application.Caller.Address
    On Error GoTo 0
  End If
End Function

Public Sub MenuButtonClicked()
  Dim i As Long

  For i = 1 To RefsToCalculate.Count
    RefsToCalculate(i).Dirty
  Next
End Sub

答案 1 :(得分:0)

“我有一个用户定义的函数(= MyFunction()),可以从excel表调用。因此,我还有一个菜单按钮,我需要调用所有函数调用= MyFunction() ,当用户点击按钮时。“

这可以轻松完成,无需创建缓存来存储一系列单元格。但是,您需要小心计算方法。我相信下面的代码确保您的范围将始终计算,但是:(1)如果calc方法不是手动的,那么Excel最终控制计算的内容,时间和原因,因此它也可能重新计算其他单元格。 (2)同样,我相信无论使用何种计算方法,我都相信它可以保证使用您的函数重新计算所有单元格,但我没有测试下面的表格和半自动计算方法。

以下代码提供了两种方法:

(1) - 重新计算包含公式的所有单元格:优点是您跳过循环及其中的代码,缺点是您可能会强制重新计算比您真正需要的更多单元格。

(2) - 构建一系列兴趣和重新计算范围:缺点是构建该范围可能需要一些严肃的计算工作。优点是,如果calc方法设置为手动,那么我相信Excel只会重新计算该范围内的单元格。

我猜选择取决于您需要解决的问题的具体细节。

“我的计划是在MyFunction()内部,为调用单元格指定一个名称rerefence并将其存储在vba中。所以我可以有一个单元格名称数组。然后我可以在菜单按钮时调用这些单元格引用点击“。

如果你真的想要遵循这种方法,或者你肯定需要为你描述的目的创建一个单元格的缓存,那么这可以做到,尽管是初步的,它甚至可以以这样的方式构建在Excel会话之间保留。然而,这需要更多的工作,更先进的方法,它仍然是非常基本的。国际海事组织,这个问题明显有些过分。更糟糕的是,每次更新单元时都必须调用代码,以确保缓存保持最新,这可能会对性能产生很大的影响。至于GSerg的建议:这种方法 - 正如他自己提到的 - 并没有给你任何真正的控制缓存本身的生命。这是,每次到达缓存时,您都必须检查Excel是否已将其擦除,如果是这种情况,则重建它。

结论:我建议您不要缓存细胞。相反,我建议您尝试按需查找需要重新计算的单元格,并以最佳方式强制重新计算这些单元格。还是不相信?在这种情况下,使用Application.Caller.Address(参见下面的代码)来检索调用函数的单元格的地址。

备注:在Excel 2003中实施和测试。包含C#样式的注释符号用于格式化。

Option Explicit

Public Sub ReEvaluateMyFunction()

    On Error GoTo Handle_Exception

    Dim targetCells As Range
    Dim targetCell As Range
    Dim rangeToRecalc As Range

    /*'Workbook and worksheet names
    'hard-coded for the example*/

    Set targetCells = Application _
    .Workbooks("Book1") _
    .Worksheets("Sheet1").UsedRange _
    .SpecialCells(xlCellTypeFormulas)

    If targetCells Is Nothing Then Exit Sub

    /*'You can narrow down the range if you know
    'more about the function's return type, e.g.:

    '.SpecialCells(xlCellTypeFormulas, xlNumbers)
    '.SpecialCells(xlCellTypeFormulas, xlTextValues)

    'OPTION 1: re-calculate all cells in the range

    'Remark: unless calc method is set to "Manual", which
    'should give you full control, I think there's no
    'guarantee that other cells will not be recalculated*/

    If Application.Calculation = xlCalculationManual Then
        //'Use to force recalculation if calc mode is manual
        targetCells.Calculate
    Else
        //'Use this to force recalculation in other cases
        targetCells.Dirty
    End If

    Set targetCells = Nothing
    Exit Sub

    /*'OPTION 2: create a range specific to your
    'function and recalculate that range*/

    For Each targetCell In targetCells

        If targetCell.Formula = "=MyFunction()" Then

            If rangeToRecalc Is Nothing Then
                Set rangeToRecalc = targetCell
            Else
                Set rangeToRecalc = Union(rangeToRecalc, targetCell)
            End If

        End If

    Next targetCell

    //'Same comments as before
    If Application.Calculation = xlCalculationManual Then
        rangeToRecalc.Calculate
    Else
        rangeToRecalc.Dirty
    End If

    Set rangeToRecalc = Nothing
    Set targetCell = Nothing
    Set targetCells = Nothing

    Exit Sub

Handle_Exception:

    Set rangeToRecalc = Nothing
    Set targetCell = Nothing
    Set targetCells = Nothing

    MsgBox "An error has been found: " + Err.Description, vbCritical

End Sub

Public Function MyFunction() As String

    MyFunction = Application.Caller.Address

End Function