为什么VBA TypeOf运算符会失败

Pie*_*ens 14 excel vba excel-2007 excel-vba

我已经和Excel 2007问题争吵好几天了.以下列出了我能想到的所有可能相关的事实:

  1. IDetailSheet是在VBA项目中声明的具有多个方法的类,它在其类初始化程序中引发错误,因此无法实例化(使其成为抽象).

  2. Option Explicit在所有模块中设置.

  3. VBA项目中的十个工作表实现 IDetailSheet并干净地编译(整个项目也是如此).

  4. CDetailSheets是在VBA项目中声明的类,它包装Collection对象并将Collection对象公开为IDetailSheet的Collection .它还公开了一些额外的方法来在所有集合中执行IDetailSheet的某些方法.

  5. 在其类初始值设定项(从Workbook _ Open事件处理程序调用并分配给全局变量)中,CDetailSheet执行以下代码以填充专用集合DetailSheets:

    Dim sht as EXCEL.WorkSheet
    For Each sht in ActiveWorkbook.Worksheets
      If TypeOf sht is IDetailSheet Then
        Dim DetailSheet as IDetailSheet
        Set DetailSheet = sht
        DetailSheets.Add DetailSheet, DetailSheet.Name
      End If
    Next sht
    
    Run Code Online (Sandbox Code Playgroud)
  6. 在某些功能区回调中,运行以下代码:

       If TypeOf ActiveWorkbook.ActiveSheet is IDetailSheet Then
          Dim DetailSheet as IDetailSheet
          Set DetailSheet = ActiveWorkbook.ActiveSheet
          DetailSheet.Refresh  *[correction]*
       End If
    
    Run Code Online (Sandbox Code Playgroud)
  7. 在识别出其他稳定性问题之后,所有ActiveX控件都已从工作簿中删除(最初有几十个).已创建Fluent Interface功能区以替换最初与ActiveX控件关联的功能.

  8. 公司模板中有一个Hyperion加载项,但未在此工作簿中使用.

完成所有操作后,运行工作簿时会出现以下症状:

  • 通过TypeOf Is在CDetailSheets初始化程序中识别任意数量的IDetailSheet实例,从1(最常见)到偶尔2或3.从不为零,从不超过3,并且绝大多数肯定不是完整的10.(并不总是相同的,虽然靠近集合的前面似乎增加了被识别的可能性.)
  • 在CDetailSheets初始化程序中发现了IDetailSheet实现的哪个实例(并且尽可能接近我只能确定这样的实例)也被TypeOf识别...在Ribbon调用回调中.

任何人都可以解释为什么大多数TypeOf ...操作是否失败?或者如何解决问题?

我已经使用手动创建v-tables(即丑陋的Select Case ... End Select语句)来使功能正常工作,但实际上我觉得让我的名字在这些代码旁边相当尴尬.除此之外,我可以看到这是未来的维护噩梦.

考虑到它可能是一个陈旧的p代码问题,我从扩展的XLSM zip中删除了Project.Bin文件,然后手动导入所有VBA代码.没有变化.我还尝试将项目名称添加到IDetailSheet的所有用法中,以使它们成为miFab.IDetailSheet,但再次无济于事.(miFab是项目名称.)

And*_*ASM 8

有几种方法可以使用CallByName作弊.你将不得不以这种或那种方式解决这个问题.

一个快速的脏例子

以实现行开头的每个工作表都应具有公共GetType函数.我将"TestSheet"子附加到功能区上的按钮上.它将返回的类型名称放在单元格A1中以演示该函数.

模块1

'--- Start Module1 ---
Option Explicit

Public Sub TestSheet()
  Dim obj As Object
  Set obj = ActiveSheet
  ActiveSheet.[A1] = GetType(obj)
End Sub

Public Function GetType(obj As Object) As String
  Dim returnValue As String
  returnValue = TypeName(obj)
  On Error Resume Next
  returnValue = CallByName(obj, "GetType", VbMethod)
  Err.Clear
  On Error GoTo 0
  GetType = returnValue
End Function
'--- End Module1 ---
Run Code Online (Sandbox Code Playgroud)

工作表Sheet1

'--- Start Sheet1 ---
Implements Class1
Option Explicit

Public Function Class1_TestFunction()
End Function

Public Function GetType() As String
    GetType = "Class1"
End Function
'--- End Sheet1 ---
Run Code Online (Sandbox Code Playgroud)