Пропустить ошибку «Переменная не определена» в не заданном объекте с явным параметром - PullRequest
1 голос
/ 10 апреля 2020


Я написал приложение для Excel, назовем его MasterWb , содержащее несколько листов, например (кодовые имена): wsFirst, wsSecond, wsThird .

1. Чего я хотел бы достичь

Я хочу иметь вторую рабочую книгу - копию MasterWb , но без листа wsThird . Давайте назовем это ClientWb .

2. Как я сейчас достигаю своей цели

Просто в моем приложении есть макрос prepareClientsWb, который:
- создает копию ( ClientWb ) MasterWb , используя SaveCopyAs метод
- открывает ClientWb , удаляет лист wsThird и закрывает его с сохранением

3. В чем проблема

Я использую событие Workbook_Open в своем приложении, чтобы подготовить видимость листов при открытии

 Private Sub Workbook_Open()

     ' xlSheetVisible
        wsFirst.Visible = xlSheetVisible

     ' xlSheetHidden
        wsSecond.Visible = xlSheetHidden

     ' xlSheetVeryHidden
        wsThird.Visible = xlSheetVeryHidden

 End Sub

И проблема в том, что я могу не использовать Option Explicit и кодовые имена листов одновременно: конечно, произошла ошибка переменная не определена при запуске сгенерированного clientWb («wsThird» не распознается). В настоящее время я не использую Option Explicit и использую оператор On Error Resume Next. Что является более элегантным решением для решения моей проблемы? Я предполагаю, что это может быть действительно легко, но я не имею понятия, что лучше всего для этого ...

Я не могу использовать имена или индексы вместо кодовых имен, потому что это может сильно измениться. Я не буду использовать шаблоны, потому что приложение все еще развивается, и для меня весьма проблематично c вносить изменения в две книги. Я не буду хранить часть кода в другом модуле и не буду удалять этот модуль при создании clientWb - мне это кажется довольно сложным и, вероятно, потребуется Доверительный доступ к объектной модели проекта VBA , которая Я бы избежал, если это возможно. Или ...

4. Может быть, с помощью условной компиляции?

... но разве это не кувалдой, чтобы сломать орех: -)

Например, создать дополнительный лист wsConditionalConst со значением bool в диапазоне A1 (0 masterWb , 1 clientWb ) или проверьте, существует ли wsThird или другой способ определить, находимся ли мы в masterWb или ClientWb и сохраните эту информацию в логической переменной isMasterWorkbook . Я не знаю, можем ли мы использовать условные переменные вместо consts - просто идея.

 Private Sub Workbook_Open()

     ' xlSheetVisible
        wsFirst.Visible = xlSheetVisible

     ' xlSheetHidden
        wsSecond.Visible = xlSheetHidden

     ' xlSheetVeryHidden
      #If isMasterWorkbook = True Then
            wsThird.Visible = xlSheetVeryHidden
      #End If

 End Sub

Может быть, есть простой способ изменить / добавить аргумент условной компиляции через код VBA вместо его изменения вручную в свойства проекта? Я не знаю, возможно ли это вообще, никогда не пробовал.

В моем реальном случае мое приложение довольно сложное (~ 2 тыс. Строк кода с входом в систему, подготовка многих листов, например, поворот вне сетки, заголовки и т. д., чтобы приложение было максимально читабельным), у меня в MasterWb гораздо больше листов, чем в примере выше (около 15 листов), и я удаляю несколько из них при создании ClientWb.

Прошу прощения за название - я понятия не имею, как объяснить это по-английски sh короткий простой способ.

Ответы [ 2 ]

3 голосов
/ 10 апреля 2020

Я бы изменил открытый код вашей книги:

Option Explicit
Private Sub Workbook_Open()
    Dim ws As Worksheet

For Each ws In Worksheets
    Select Case ws.CodeName
        Case "wsFirst"
            ws.Visible = xlSheetVisible
        Case "wsSecond"
            ws.Visible = xlSheetHidden
        Case "wsThird"
            ws.Visible = xlSheetVeryHidden
    End Select
Next ws

End Sub


3 голосов
/ 10 апреля 2020

Вы могли бы сделать что-то вроде этого. Имейте функцию, которая находит лист, используя его кодовое имя, или, если не найден, возвращает Nothing. Затем используйте эту функцию, чтобы получить рабочие листы, если они существуют, и установить их видимость.

Public Function GetWorksheet(codeName As String) As Worksheet
    Dim ws As Worksheet

    For Each ws In ThisWorkbook
        If ws.codeName = codeName Then
            Set GetWorksheet = ws
            Exit Function
        End If

        '//If you get here, we didn't find it
        Set GetWorksheet = Nothing
    Next
End Function 

Теперь ваше событие Workbook_Open выглядит следующим образом:

Private Sub Workbook_Open()
    Dim ws As Worksheet
     ' xlSheetVisible
    Set ws = GetWorksheet("wsFirst")
    If Not ws Is Nothing Then ws.Visible = xlSheetVisible

     ' xlSheetHidden
    Set ws = GetWorksheet("wsSecond")
    If Not ws Is Nothing Then ws.Visible = xlSheetHidden

     ' xlSheetVeryHidden
    Set ws = GetWorksheet("wsThird")
    If Not ws Is Nothing Then ws.Visible = xlSheetVeryHidden

 End Sub
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...