刷新没有 application.volatile 的用户定义函数
Refresh User-defined function without application.volatile
我正在使用我在 Internet 上找到的函数来提取切片器的值(连接到 Table,而不是 PivotTable)并将其存储在单元格中.该函数包括 application.volatile
的添加,效果很好,正如问题 Refresh Excel VBA Function Results .
中所讨论的那样
问题是,由于 volatile 函数,我的 OpenSolver 模型无法 运行。因为每次迭代 Excel 都在进行计算,这使得 OpenSolver 认为 Excel 尚未准备好进行建模。
是否有一种方法可以在每次切片器更改值时更新单元格的值,而不使用 application.volatile
?
我已经尝试使用:
Private Sub Worksheet_Change(ByVal Target As Range)
ActiveWorkbook.Sheets("Dashboard").Range("B7").Formula = _
ActiveWorkbook.Sheets("Dashboard").Range("B7").Formula
End Sub
和
Private Sub Worksheet_Change(ByVal Target As Range)
ActiveWorkbook.Sheets("Dashboard").Range("B7").Calculate
End Sub
我用来提取切片器值的函数取自 http://www.jkp-ads.com/articles/slicers05.asp :
Public Function GetSelectedSlicerItems(SlicerName As String) As String
Dim oSc As SlicerCache
Dim oSi As SlicerItem
Dim lCt As Long
On Error Resume Next
Set oSc = ThisWorkbook.SlicerCaches(SlicerName)
If Not oSc Is Nothing Then
For Each oSi In oSc.SlicerItems
If oSi.Selected Then
GetSelectedSlicerItems = GetSelectedSlicerItems & oSi.Name & ", "
lCt = lCt + 1
End If
Next
If Len(GetSelectedSlicerItems) > 0 Then
If lCt = oSc.SlicerItems.Count Then
GetSelectedSlicerItems = "maandag"
Else
GetSelectedSlicerItems = Left(GetSelectedSlicerItems, Len(GetSelectedSlicerItems) - 2)
End If
Else
GetSelectedSlicerItems = "No items selected"
End If
Else
GetSelectedSlicerItems = "No slicer with name '" & SlicerName & "' was found"
End If
End Function
如果您希望切片器的值出现在单元格中,您可以使用另一种不涉及 VBA 的方法,这可能会间接解决您的问题。
- 创建原始数据透视表的副本,其中除了切片器控制的字段外什么都没有。
- 将该字段拖到“数据透视表字段”对话框的“报表过滤器”窗格中。
- 将切片器连接到这个新数据透视表中的这个字段
太棒了:现在您有一个伪装成数据验证下拉列表的数据透视表。现在,只要有人点击切片器,数据透视表过滤器就会包含他们点击的内容的名称。
我写了一个 post 来解释这个方法,在下面 link:
http://dailydoseofexcel.com/archives/2014/08/16/sync-pivots-from-dropdown/
我尝试了一种完全不同的方法,我不需要从切片器中提取值的函数,从而使 volatile 变得多余。相反,我从 table 中减去所选的值。我是这样做的:
根据日期选择的切片器作为字符串:星期一、星期二等。我添加了一个用整数表示日期的列(星期一 = 1,星期日 = 7)。然后,我在单元格中使用了以下公式:
=SUBTOTAL(9;AF10:AF200)/SUBTOTAL(2;AF10:AF200)
这段代码首先将所有可见单元格的整数值相加,除以可见单元格的数量(即我计算平均值)。这应该始终导致所选日期的整数值。有了那个数字,我再次找到当天的字符串表示形式。
除了上面的公式,你当然也可以使用:
=SUBTOTAL(1;AF10:AF200)
我正在使用我在 Internet 上找到的函数来提取切片器的值(连接到 Table,而不是 PivotTable)并将其存储在单元格中.该函数包括 application.volatile
的添加,效果很好,正如问题 Refresh Excel VBA Function Results .
问题是,由于 volatile 函数,我的 OpenSolver 模型无法 运行。因为每次迭代 Excel 都在进行计算,这使得 OpenSolver 认为 Excel 尚未准备好进行建模。
是否有一种方法可以在每次切片器更改值时更新单元格的值,而不使用 application.volatile
?
我已经尝试使用:
Private Sub Worksheet_Change(ByVal Target As Range)
ActiveWorkbook.Sheets("Dashboard").Range("B7").Formula = _
ActiveWorkbook.Sheets("Dashboard").Range("B7").Formula
End Sub
和
Private Sub Worksheet_Change(ByVal Target As Range)
ActiveWorkbook.Sheets("Dashboard").Range("B7").Calculate
End Sub
我用来提取切片器值的函数取自 http://www.jkp-ads.com/articles/slicers05.asp :
Public Function GetSelectedSlicerItems(SlicerName As String) As String
Dim oSc As SlicerCache
Dim oSi As SlicerItem
Dim lCt As Long
On Error Resume Next
Set oSc = ThisWorkbook.SlicerCaches(SlicerName)
If Not oSc Is Nothing Then
For Each oSi In oSc.SlicerItems
If oSi.Selected Then
GetSelectedSlicerItems = GetSelectedSlicerItems & oSi.Name & ", "
lCt = lCt + 1
End If
Next
If Len(GetSelectedSlicerItems) > 0 Then
If lCt = oSc.SlicerItems.Count Then
GetSelectedSlicerItems = "maandag"
Else
GetSelectedSlicerItems = Left(GetSelectedSlicerItems, Len(GetSelectedSlicerItems) - 2)
End If
Else
GetSelectedSlicerItems = "No items selected"
End If
Else
GetSelectedSlicerItems = "No slicer with name '" & SlicerName & "' was found"
End If
End Function
如果您希望切片器的值出现在单元格中,您可以使用另一种不涉及 VBA 的方法,这可能会间接解决您的问题。
- 创建原始数据透视表的副本,其中除了切片器控制的字段外什么都没有。
- 将该字段拖到“数据透视表字段”对话框的“报表过滤器”窗格中。
- 将切片器连接到这个新数据透视表中的这个字段
太棒了:现在您有一个伪装成数据验证下拉列表的数据透视表。现在,只要有人点击切片器,数据透视表过滤器就会包含他们点击的内容的名称。
我写了一个 post 来解释这个方法,在下面 link:
http://dailydoseofexcel.com/archives/2014/08/16/sync-pivots-from-dropdown/
我尝试了一种完全不同的方法,我不需要从切片器中提取值的函数,从而使 volatile 变得多余。相反,我从 table 中减去所选的值。我是这样做的:
根据日期选择的切片器作为字符串:星期一、星期二等。我添加了一个用整数表示日期的列(星期一 = 1,星期日 = 7)。然后,我在单元格中使用了以下公式:
=SUBTOTAL(9;AF10:AF200)/SUBTOTAL(2;AF10:AF200)
这段代码首先将所有可见单元格的整数值相加,除以可见单元格的数量(即我计算平均值)。这应该始终导致所选日期的整数值。有了那个数字,我再次找到当天的字符串表示形式。
除了上面的公式,你当然也可以使用:
=SUBTOTAL(1;AF10:AF200)