Я написал приложение для 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. Что является более элегантным решением для решения моей проблемы? Я полагаю, это может быть очень легко, но я не знаю, как лучше всего это делать ...

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

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

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

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

 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.

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

1
Rafał B. 10 Апр 2020 в 15:29

2 ответа

Лучший ответ

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

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
Ron Rosenfeld 10 Апр 2020 в 13:28

Вы могли бы сделать что-то вроде этого. Имейте функцию, которая находит лист, используя его кодовое имя, или, если не найден, возвращает 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
3
ArcherBird 10 Апр 2020 в 13:26