Worksheet_Activate新表格代码

时间:2010-01-21 21:20:17

标签: 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

问题在于,如果我可以再次激活这些工作表,它将打开更多窗口。我希望代码能够检测窗口是否已打开,如果是,则会中断。

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

此代码的问题在于,如果额外的窗口未打开,则会出错。我可以进行某种逻辑检查以使其工作吗?我不知道要检查什么值......

3)最后一个问题是工作簿中的宏动态生成了新工作表。这些新的工作表不会带有上面的代码来关闭多个窗口并关注活动表。是否有一个不同的对象,我应该把代码,以便它适用于Master |工作表1 | Worksheet2工作表和任何新工作表?

2 个答案:

答案 0 :(得分:5)

这是很多问题。 :)对于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函数并更改数组参数。

因为我们正在使用自定义类并在工作簿级别嗅探事件,所以您可以随意添加和删除工作表。

答案 1 :(得分:1)

1)要测试窗口是否已打开,请使用此功能

Function IsWindowOpen(windowTitle As String) As Boolean
    Dim i As Long
    For i = 1 To Windows.Count
        If Windows(i).Caption = windowTitle Then
            IsWindowOpen = True
            Exit Function
        End If
    Next
    IsWindowOpen = False
End Function

例如:

if not IsWindowOpen("Mastersheet.xlsm:2") then
     ' code to open windows
end if

2)您可以再次重复使用该功能,同样的想法:

if IsWindowOpen("Mastersheet.xlsm:2") then
     ' code to close windows
end if

3)将代码添加到模块,而不是工作表。然后从宏中调用例程,在完成此操作后添加新工作表。如果此宏位于不同的模块中,则可能必须确保您的Sub是公共的。