为数据透视表添加切片器并按指定排列时遇运行时错误
VBA创建切片器报错“Method Add2 with object slicercaches failed”修复方案
问题背景
现有一段VBA代码,意图为指定数据透视表Origin_Check创建4个从A2单元格开始等距排列的切片器,但运行时触发错误:Method Add2 with object slicercaches failed。
原代码如下:
Sub AddSlicers() Dim ws As Worksheet Dim pt As pivotTable Dim sl1 As slicerCache, sl2 As slicerCache, sl3 As slicerCache, sl4 As slicerCache Dim sl1Obj As slicer, sl2Obj As slicer, sl3Obj As slicer, sl4Obj As slicer ' Set the worksheet and pivot table On Error Resume Next Set ws = ActiveWorkbook.Sheets("sanity_check") On Error GoTo 0 If ws Is Nothing Then MsgBox "Worksheet 'sanity_check' not found!", vbExclamation Exit Sub End If On Error Resume Next Set pt = ws.PivotTables("Origin_Check") On Error GoTo 0 If pt Is Nothing Then MsgBox "Pivot table 'Origin_Check' not found in the 'sanity_check' worksheet!", vbExclamation Exit Sub End If ' Add slicer caches Set sl1 = ActiveWorkbook.slicercaches.Add2(pt, "Origin_Region") Set sl2 = ActiveWorkbook.slicercaches.Add2(pt, "Origin_Country") Set sl3 = ActiveWorkbook.slicercaches.Add2(pt, "Destination_Region") Set sl4 = ActiveWorkbook.slicercaches.Add2(pt, "Destination_Country") ' Add slicers Set sl1Obj = sl1.Slicers.Add(ws, , "Slicer1", "Origin_Region" & Chr(10) & "(enter AP, AM, EURO, MEA)", _ Left:=ws.Range("A2").Left, Top:=ws.Range("A2").Top) Set sl2Obj = sl2.Slicers.Add(ws, , "Slicer2", "Origin_Country" & Chr(10) & "(in 2-letter codes)", _ Left:=ws.Range("B2").Left, Top:=ws.Range("B2").Top) Set sl3Obj = sl3.Slicers.Add(ws, , "Slicer3", "Destination_Region" & Chr(10) & "(enter AP, AM, EURO, MEA)", _ Left:=ws.Range("C2").Left, Top:=ws.Range("C2").Top) Set sl4Obj = sl4.Slicers.Add(ws, , "Slicer4", "Destination_Country" & Chr(10) & "(in 2-letter codes)", _ Left:=ws.Range("D2").Left, Top:=ws.Range("D2").Top) ' Refresh the pivot table pt.RefreshTable End Sub
错误原因
- 字段名称不匹配:
Add2方法中传入的字段名必须与数据透视表内的字段名称完全一致(含大小写、空格、特殊字符),拼写错误或字段不存在会直接触发报错。 - 重复缓存冲突:若目标字段已存在切片器缓存,再次调用
Add2创建同名缓存会失败。 - 版本兼容性问题:
Add2是Excel 2013及以上版本新增的方法,旧版Excel不支持该方法。
修复方案
1. 验证字段正确性
打开sanity_check工作表的Origin_Check数据透视表,确认Origin_Region、Origin_Country、Destination_Region、Destination_Country这四个字段确实存在,且名称完全匹配(无拼写错误、空格差异)。
2. 避免重复创建缓存
先检查是否已有对应字段的切片器缓存,存在则直接复用,不存在再新建:
' 替换原缓存创建代码 Set sl1 = GetSlicerCache(pt, "Origin_Region") Set sl2 = GetSlicerCache(pt, "Origin_Country") Set sl3 = GetSlicerCache(pt, "Destination_Region") Set sl4 = GetSlicerCache(pt, "Destination_Country") ' 新增辅助函数 Function GetSlicerCache(pt As PivotTable, fieldName As String) As SlicerCache Dim sc As SlicerCache On Error Resume Next Set sc = ActiveWorkbook.SlicerCaches("Slicer_" & fieldName) On Error GoTo 0 If sc Is Nothing Then ' 用Add替代Add2提升兼容性 Set sc = ActiveWorkbook.SlicerCaches.Add(pt, fieldName) End If Set GetSlicerCache = sc End Function
3. 替换兼容方法
将Add2替换为兼容性更好的Add方法(Excel 2010及以上均支持),避免版本问题。
4. 优化切片器排列逻辑
原代码依赖单元格Left属性,切片器默认宽度可能导致重叠,改为固定宽度并按间距排列:
' 替换原切片器创建代码 Dim slicerWidth As Integer slicerWidth = 150 ' 设置切片器固定宽度 Set sl1Obj = sl1.Slicers.Add(ws, , "Slicer_Origin_Region", "Origin_Region" & Chr(10) & "(enter AP, AM, EURO, MEA)", _ Left:=ws.Range("A2").Left, Top:=ws.Range("A2").Top, Width:=slicerWidth) Set sl2Obj = sl2.Slicers.Add(ws, , "Slicer_Origin_Country", "Origin_Country" & Chr(10) & "(in 2-letter codes)", _ Left:=sl1Obj.Left + slicerWidth + 10, Top:=ws.Range("A2").Top, Width:=slicerWidth) Set sl3Obj = sl3.Slicers.Add(ws, , "Slicer_Destination_Region", "Destination_Region" & Chr(10) & "(enter AP, AM, EURO, MEA)", _ Left:=sl2Obj.Left + slicerWidth + 10, Top:=ws.Range("A2").Top, Width:=slicerWidth) Set sl4Obj = sl4.Slicers.Add(ws, , "Slicer_Destination_Country", "Destination_Country" & Chr(10) & "(in 2-letter codes)", _ Left:=sl3Obj.Left + slicerWidth + 10, Top:=ws.Range("A2").Top, Width:=slicerWidth)
完整修复后代码
Sub AddSlicers() Dim ws As Worksheet Dim pt As PivotTable Dim sl1 As SlicerCache, sl2 As SlicerCache, sl3 As SlicerCache, sl4 As SlicerCache Dim sl1Obj As Slicer, sl2Obj As Slicer, sl3Obj As Slicer, sl4Obj As Slicer Dim slicerWidth As Integer ' 设置切片器固定宽度 slicerWidth = 150 ' Set the worksheet and pivot table On Error Resume Next Set ws = ActiveWorkbook.Sheets("sanity_check") On Error GoTo 0 If ws Is Nothing Then MsgBox "Worksheet 'sanity_check' not found!", vbExclamation Exit Sub End If On Error Resume Next Set pt = ws.PivotTables("Origin_Check") On Error GoTo 0 If pt Is Nothing Then MsgBox "Pivot table 'Origin_Check' not found in the 'sanity_check' worksheet!", vbExclamation Exit Sub End If ' 获取或创建切片器缓存 Set sl1 = GetSlicerCache(pt, "Origin_Region") Set sl2 = GetSlicerCache(pt, "Origin_Country") Set sl3 = GetSlicerCache(pt, "Destination_Region") Set sl4 = GetSlicerCache(pt, "Destination_Country") ' 创建并排列切片器 Set sl1Obj = sl1.Slicers.Add(ws, , "Slicer_Origin_Region", "Origin_Region" & Chr(10) & "(enter AP, AM, EURO, MEA)", _ Left:=ws.Range("A2").Left, Top:=ws.Range("A2").Top, Width:=slicerWidth) Set sl2Obj = sl2.Slicers.Add(ws, , "Slicer_Origin_Country", "Origin_Country" & Chr(10) & "(in 2-letter codes)", _ Left:=sl1Obj.Left + slicerWidth + 10, Top:=ws.Range("A2").Top, Width:=slicerWidth) Set sl3Obj = sl3.Slicers.Add(ws, , "Slicer_Destination_Region", "Destination_Region" & Chr(10) & "(enter AP, AM, EURO, MEA)", _ Left:=sl2Obj.Left + slicerWidth + 10, Top:=ws.Range("A2").Top, Width:=slicerWidth) Set sl4Obj = sl4.Slicers.Add(ws, , "Slicer_Destination_Country", "Destination_Country" & Chr(10) & "(in 2-letter codes)", _ Left:=sl3Obj.Left + slicerWidth + 10, Top:=ws.Range("A2").Top, Width:=slicerWidth) ' Refresh the pivot table pt.RefreshTable End Sub ' 辅助函数:获取已有切片器缓存,不存在则创建 Function GetSlicerCache(pt As PivotTable, fieldName As String) As SlicerCache Dim sc As SlicerCache On Error Resume Next Set sc = ActiveWorkbook.SlicerCaches("Slicer_" & fieldName) On Error GoTo 0 If sc Is Nothing Then Set sc = ActiveWorkbook.SlicerCaches.Add(pt, fieldName) End If Set GetSlicerCache = sc End Function
内容的提问来源于stack exchange,提问作者H BG
相关产品推荐
相关产品推荐

