为什么VBA TypeOf运算符会失败

时间:2013-08-29 00:54:51

标签: excel vba excel-vba excel-2007

我几天来一直在与Excel 2007问题作斗争。以下列出了我能想到的所有可能相关的事实:

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

  2. 选项显式在所有模块中设置。

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

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

  5. 在其类初始值设定项(从工作簿 _ 打开事件处理程序调用并分配给全局变量)中, 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
    
  6. 在某些功能区回调中,运行以下代码:

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

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

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

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

    有人可以解释为什么大多数 TypeOf ... 操作失败了吗?或者如何解决问题?

    我已经使用手动创建v-tables(即大丑 Select Case ... End Select 语句)来使功能正常工作,但实际上我发现在旁边有我的名字真令人尴尬这样的代码。除此之外,我可以看到这是未来的维护噩梦。

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

3 个答案:

答案 0 :(得分: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 ---

Sheet 1中

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

Public Function Class1_TestFunction()
End Function

Public Function GetType() As String
    GetType = "Class1"
End Function
'--- End Sheet1 ---

答案 1 :(得分:3)

我在发布自己的类似问题TypeOf fails to work with Excel workbook's ActiveSheet that implements interface

后发现了这个问题

我没有明确的解释,但我认为我确实有一个解决方法。

  

我怀疑是因为[代码]在Sheet1或Chart上实现了一个接口,并且正在扩展Sheet1 / Chart1,但Sheet1已经在扩展Worksheet(并且Chart1已经在扩展Chart)。

在我的测试中,我可以通过首先访问工作表的属性来强制VBA返回[Authorize(roles=Admin)]的实际值。这意味着,做一些丑陋之类的事情:

TypeOf

答案 2 :(得分:0)

如果您不信任TypeOf,请继续并忽略错误:

Dim sht as EXCEL.WorkSheet
For Each sht in ActiveWorkbook.Worksheets
  'If TypeOf sht is IDetailSheet Then
  Dim DetailSheet As IDetailSheet
  On Error Resume Next
  Set DetailSheet = sht
  On Error GoTo 0
  If Not DetailSheet Is Nothing Then
    DetailSheets.Add DetailSheet, DetailSheet.Name
  End If
Next sht

如果此 不起作用,那么工作表至少当时不是IDetailSheet