Подтвердить что ты не робот

Почему оператор VBA TypeOf не работает

Я уже несколько дней борюсь с проблемой Excel 2007. Ниже приведен список всех фактов, которые, как я могу думать, могут иметь значение:

  1. IDetailSheet - это класс, объявленный в проекте VBA несколькими способами, и который вызывает ошибку в его инициализаторе класса, так что он не может быть создан (делая его абстрактным).

  2. Параметр Explicit устанавливается во всех модулях.

  3. Десять рабочих листов проекта VBA реализуют IDetailSheet и компилируются (как и весь проект).

  4. CDetailSheets - это класс, объявленный в проекте VBA, который обертывает объект Collection и предоставляет объект Collection в виде коллекции IDetailSheet. Он также предоставляет некоторые дополнительные методы для выполнения определенных методов 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
    
  6. В некоторых обратных вызовах ленты выполняется следующий код:

       If TypeOf ActiveWorkbook.ActiveSheet is IDetailSheet Then
          Dim DetailSheet as IDetailSheet
          Set DetailSheet = ActiveWorkbook.ActiveSheet
          DetailSheet.Refresh  *[correction]*
       End If
    
  7. Все элементы ActiveX были удалены из рабочей книги, после того как были идентифицированы с другими проблемами стабильности (первоначально было несколько десятков). Для замены функций, первоначально связанных с элементами управления ActiveX, была создана свободная интерфейсная лента.

  8. Существует надстройка Hyperion от корпоративного шаблона, но она не используется в этой книге.

Когда все сказано и сделано, появляется следующий симптом, когда рабочая книга запущена:

  • Любое количество экземпляров IDetailSheet распознается в Инициализаторе CDetailSheets по TypeOf Is, от 1 (наиболее часто встречающегося) до иногда 2 или 3. Никогда не ноль, не более 3, и, конечно же, никогда не доступны 10 доступных. (Не всегда один и тот же, хотя и находится рядом с передним рядом с набором, по-видимому, увеличивает вероятность признания.)
  • Каковы бы ни были экземпляры реализации IDetailSheet в инициализаторе CDetailSheets (и как только я могу определить, только такие экземпляры) также распознаются с помощью TypeOf... Является ли обратная связь ленты.

Может кто-нибудь объяснить, почему большая часть TypeOf... Не работает ли операция? Или как решить проблему?

Я прибегал к ручному созданию v-таблиц (т.е. Больших уродливых операторов Select Case... End Select), чтобы заставить работать функциональность, но на самом деле мне кажется довольно неловко иметь мое имя рядом с таким кодом. Кроме того, я вижу, что это будущий кошмар.

Думая, что это могут быть устаревшие проблемы с p-кодом, я пошел до степени удаления файла Project.Bin из расширенного zip файла XLSM, а затем вручную импортировал весь код VBA. Без изменений. Я также попытался добавить имя проекта ко всем обычаям IDetailSheet, чтобы сделать их miFab.IDetailSheet, но опять же безрезультатно. (miFab - название проекта.)

4b9b3361

Ответ 1

Есть несколько способов обмануть, используя CallByName. Вам придется обойти эту ошибку так или иначе.

Быстрый грязный пример

Каждый лист, начинающийся с строки реализации, должен иметь общедоступную функцию GetType. Я подключил субтитры TestSheet к кнопке на моей ленте. Он помещает возвращаемое имя типа в ячейку A1, чтобы продемонстрировать функцию.

Module1

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

Ответ 2

Я нашел этот вопрос после публикации моей собственной аналогичной проблемы, поскольку TypeOf не работает с ActiveSheet рабочей книги Excel, который реализует интерфейс

У меня нет окончательного объяснения, но я думаю, что у меня есть обходное решение.

Я подозреваю, что это потому, что [код] реализует интерфейс на Sheet1 или Chart и расширяет Sheet1/Chart1, но Sheet1 уже расширяет рабочий лист (а Chart1 уже расширяет диаграмму).

В моем тестировании я могу заставить VBA вернуть реальное значение TypeOf, сначала получив доступ к свойству листа. Это означает, что вы делаете что-то некрасивое, как:

'Explicitly access ThisWorkbook.ActiveSheet.Name before using TypeOf
If TypeOf ThisWorkbook.Sheets(ThisWorkbook.ActiveSheet.Name) Is PublicInterface Then

Ответ 3

Если вы не доверяете 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 в это время по крайней мере.