16

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

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

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

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

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

  5. 在其 Class 初始化程序(从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
    
  6. 在某些功能区回调中,运行以下代码:

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

  8. 企业模板中有一个 Hyperion 加载项,但本工作簿中没有使用它。

综上所述,运行工作簿时会出现以下症状:

  • TypeOf Is在 CDetailSheets Initializer 中识别出任意数量的 IDetailSheet 实例,从 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是项目名称。)

4

3 回答 3

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 ---

表 1

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

Public Function Class1_TestFunction()
End Function

Public Function GetType() As String
    GetType = "Class1"
End Function
'--- End Sheet1 ---
于 2013-09-03T22:34:35.663 回答
3

我在发布我自己的类似问题后发现了这个问题,因为TypeOf 无法与 Excel 工作簿的实现接口的 ActiveSheet 一起工作

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

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

在我的测试中,我可以TypeOf通过首先访问工作表的属性来强制 VBA 返回 的实际值。这意味着,做一些丑陋的事情,比如:

'Explicitly access ThisWorkbook.ActiveSheet.Name before using TypeOf
If TypeOf ThisWorkbook.Sheets(ThisWorkbook.ActiveSheet.Name) Is PublicInterface Then
于 2017-04-12T03:43:38.110 回答
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,那么至少在那个时候工作表真的不是。

于 2013-09-04T15:34:20.770 回答