Rya*_*n B 2 excel vba worksheet
我有三个关于VBA和控制/操纵新窗口的问题.
我有几张床单.
大师| 工作表1 | 工作表2 | 备注| 工作订单| 联系信息
1)我在Notes,工作订单,联系信息上设置了WorkSheet_Activate功能,可以在单独的窗口中打开所有三个工作表并垂直排列.
Private Sub WorkSheet_Activate()
ActiveWindow.NewWindow
ActiveWindow.NewWindow
Windows.Arrange ArrangeStyle:=xlVertical
Sheets("Notes").Select
Windows("Mastersheet.xlsm:2").Activate
Sheets("Work Orders").Select
Windows("Mastersheet.xlsm:1").Activate
Sheets("Contact Info").Select
End Sub
Run Code Online (Sandbox Code Playgroud)
它的问题是,如果我可以再次激活这些表,它将打开更多的窗口.我希望代码能够检测窗口是否已打开,如果是,则会中断.
2)现在,当我导航到不同的工作表(例如Master)时,我希望关闭额外的窗口并使主工作表处于活动状态.我在主表上使用以下代码.
Private Sub WorkSheet_Activate()
Windows("Mastersheet.xlsm:2").Activate
ActiveWindow.Close
Windows("Mastersheet.xlsm:1").Activate
ActiveWindow.Close
ActiveWindow.WindowState = xlMaximized
End Sub
Run Code Online (Sandbox Code Playgroud)
这段代码的问题是,如果额外的窗口没有打开,那么它将会出错.我可以进行某种逻辑检查以使其工作吗?我不知道要检查什么值...
3)最后一个问题是工作簿中的宏动态生成了新工作表.这些新的工作表不会带有上面的代码来关闭多个窗口并关注活动表.是否有一个不同的对象,我应该把代码,以便它适用于Master | 工作表1 | Worksheet2表和任何新表?
那是很多问题.:)对于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
Run Code Online (Sandbox Code Playgroud)
然后插入标准模块(插入 - 模块)并粘贴此代码
Option Explicit
Public gclsAppEvents As CAppEvents
Sub Auto_Open()
Set gclsAppEvents = New CAppEvents
Set gclsAppEvents.wb = ThisWorkbook
End Sub
Run Code Online (Sandbox Code Playgroud)
这是正在发生的事情:当您打开工作簿时,Auto_Open将运行,它将创建CAppEvents对象的新实例.由于gclsAppEvents是公共的(也就是全局的),因此只要工作簿是打开的,它就不会丢失范围.它将坐在那里监听事件(因为我们在类中使用了WithEvents关键字).
在课堂上有一个名为mobjWb_SheetActivate的子课程.这是在激活此工作簿中的任何工作表时将触发的内容.首先,它检查您刚刚激活的工作表(Sh变量)是否是您要分割的工作表之一(使用IsSplitSheet).如果是,则检查是否已经拆分.如果没有,它会分裂它们.
如果Sh(您刚刚激活的工作表)不是"拆分工作表"之一,则会检查是否已完成拆分(IsSplit).如果有,它会关闭所有分割窗口.
如果您甚至想要添加,更改或删除导致拆分的工作表,请转到GetSplitSheetNames函数并更改Array参数.
因为我们使用自定义类并在工作簿级别上嗅探事件,所以您可以根据需要添加和删除工作表.