Это много вопросов. :) Для 3 вам нужно переместить ваши события из того места, где они есть, в специальный модуль класса, который обрабатывает события уровня приложения. Начните с вставки нового модуля класса в ваш проект (Вставка - Модуль класса). Назовите этот модуль CAppEvents (F4, чтобы показать страницу свойств, где вы можете изменить имя). Затем вставьте этот код в модуль класса
Option Explicit
Private WithEvents mobjWb As Workbook
Private Sub Class_Terminate()
Set mobjWb = Nothing
End Sub
Public Property Get wb() As Workbook
Set wb = mobjWb
End Property
Public Property Set wb(objwb As Workbook)
Set mobjWb = objwb
End Property
Private Sub mobjWb_SheetActivate(ByVal Sh As Object)
Dim wn As Window
If IsSplitSheet(Sh) Then
If Not IsSplit(Sh) Then
CreateSplitSheets Sh
End If
Else
If IsSplit(Sh) Then
For Each wn In Me.wb.Windows
If wn.Caption Like Me.wb.Name & ":#" Then
wn.Close
End If
Next wn
ActiveWindow.WindowState = xlMaximized
Sh.Activate
End If
End If
End Sub
Private Function IsSplitSheet(Sh As Object) As Boolean
Dim vaNames As Variant
Dim i As Long
IsSplitSheet = False
vaNames = GetSplitSheetNames
For i = LBound(vaNames) To UBound(vaNames)
If vaNames(i) = Sh.Name Then
IsSplitSheet = True
Exit For
End If
Next i
End Function
Private Function IsSplit(Sh As Object) As Boolean
Dim wn As Window
IsSplit = False
For Each wn In Me.wb.Windows
If wn.Caption Like Sh.Parent.Name & ":#" Then
IsSplit = True
Exit For
End If
Next wn
End Function
Private Sub CreateSplitSheets(Sh As Object)
Dim vaNames As Variant
Dim i As Long
Dim wn As Window
Dim wnActive As Window
vaNames = GetSplitSheetNames
Set wnActive = ActiveWindow
For i = LBound(vaNames) To UBound(vaNames)
If vaNames(i) <> Sh.Name Then
Set wn = Me.wb.NewWindow
wn.Activate
On Error Resume Next
wn.Parent.Sheets(vaNames(i)).Activate
On Error GoTo 0
End If
Next i
Sh.Parent.Windows.Arrange xlVertical
wnActive.Activate
Sh.Activate
End Sub
Private Function GetSplitSheetNames() As Variant
GetSplitSheetNames = Array("Notes", "Work Orders", "Contact Info")
End Function
Затем вставьте стандартный модуль (Вставка - Модуль) и вставьте этот код
Option Explicit
Public gclsAppEvents As CAppEvents
Sub Auto_Open()
Set gclsAppEvents = New CAppEvents
Set gclsAppEvents.wb = ThisWorkbook
End Sub
Вот что происходит: когда вы открываете книгу, Auto_Open запустится и создаст новый экземпляр вашего объекта CAppEvents. Так как gclsAppEvents является общедоступным (он же глобальный), он не потеряет возможности до тех пор, пока рабочая книга открыта. Он будет сидеть и слушать события (потому что мы использовали ключевое слово WithEvents в классе).
В классе есть подпрограмма с именем mobjWb_SheetActivate. Это то, что срабатывает всякий раз, когда активируется какой-либо лист в этой книге. Сначала он проверяет, является ли лист, который вы только что активировали (переменная Sh), одним из тех, которые вы хотите разделить (используя IsSplitSheet). Если это так, то он проверяет, был ли он уже разделен. Если нет, то это разделяет их.
Если Sh (лист, который вы только что активировали) не является одним из «разделенных листов», то он проверяет, было ли выполнено разделение (IsSplit). Если он есть, он закрывает все разделенные окна.
Если вы даже хотите добавить, изменить или удалить листы, которые вызывают разделение, перейдите в функцию GetSplitSheetNames и измените аргументы Array.
Поскольку мы используем пользовательский класс и отслеживаем события на уровне рабочей книги, вы можете добавлять и удалять листы, сколько хотите.