2010-01-21 39 views
2

我有三個關於VBA和控制/操作新窗口的問題。Worksheet_Activate新表格的代碼

我設置了幾張紙。

Master | Worksheet1 | Worksheet2 |注意|工作訂單|聯繫方式

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)時,我想要關閉額外的窗口並使主工作表處於活動狀態。我在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 |的位置Worksheet1 | Worksheet2表和任何新表?

回答

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函數並更改Array參數。

因爲我們正在使用自定義類並在工作簿級別嗅探事件,所以您可以添加和刪除表單。

+0

這很好。我會盡我所能去試着理解你寫的代碼。非常感謝您的幫助dkusleika! – 2010-01-22 20:32:00

+0

雖然我知道它在VBA世界中非常標準,但我認爲如果沒有匈牙利符號,這個代碼將會更乾淨。 – User 2011-01-31 21:54:12

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是公開的。