2010-01-21 4 views
2

VBA와 새 창 제어/조작에 관한 세 가지 질문이 있습니다.워크 시트 _ 새 시트 코드 활성화

몇 장이 설정되어 있습니다.

마스터 | 워크 시트 1 | 워크 시트 2 | 노트 | 작업 주문 | 연락처 정보

1) WorkSheet_Activate 기능을 Notes, Work Orders, Contact Info에 설정하여 별도의 창에서 세 장을 모두 열고 수직으로 정렬하십시오.

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) 이제 마스터와 같은 다른 시트를 탐색 할 때 여분의 창을 닫고 마스터 시트를 활성화하고 싶습니다. 마스터 시트에 다음 코드를 사용하고있었습니다.

Private Sub WorkSheet_Activate() 


    Windows("Mastersheet.xlsm:2").Activate 
    ActiveWindow.Close 
    Windows("Mastersheet.xlsm:1").Activate 
    ActiveWindow.Close 
    ActiveWindow.WindowState = xlMaximized 

End Sub 

이 코드의 문제점은 추가 창이 열려 있지 않으면 오류가 발생한다는 것입니다. 이 기능을 작동시키기 위해 어떤 종류의 논리 검사를 수행 할 수 있습니까? 어떤 값을 확인할 지 모르겠다.

3) 마지막 문제는 통합 문서 내의 매크로에 의해 동적으로 생성 된 새로운 시트가 있다는 것입니다. 새로운 워크 시트는 여러 창을 닫고 activesheet에 초점을 맞추는 위 코드를 수행하지 않습니다. 코드를 넣어야하는 다른 객체가 마스터에 적용되도록해야합니까? 워크 시트 1 | 워크 시트 2 시트 및 새 시트? 윈도우가 이미 열려있는 경우

답변

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는 public (일명 global)이므로 통합 문서가 열려있는 한 범위를 잃지 않습니다. 우리는 클래스에서 WithEvents 키워드를 사용했기 때문에 거기에 앉아서 이벤트를 수신합니다.

클래스에는 mobjWb_SheetActivate라는 하위가 있습니다. 이 통합 문서의 시트가 활성화 될 때마다 실행됩니다. 먼저 방금 활성화 한 시트 (Sh 변수)가 분리하려는 시트 중 하나 (IsSplitSheet 사용)인지 확인합니다. 그럴 경우 이미 분할되어 있는지 확인합니다. 그렇지 않다면, 그것들을 나눕니다.

Sh (방금 활성화 한 시트)가 '분할 시트'중 하나가 아닌 경우 분할이 완료되었는지 (IsSplit) 확인합니다. 있다면, 모든 분할 창을 닫습니다.

분할을 일으키는 시트를 추가, 변경 또는 삭제하려는 경우 GetSplitSheetNames 함수로 이동하여 Array 인수를 변경하십시오.

우리는 사용자 지정 클래스를 사용하고 통합 문서 수준의 이벤트에 대해 스니핑하므로 원하는 모든 시트를 추가하거나 삭제할 수 있습니다.

+0

완벽하게 작동합니다. 필자가 작성한 코드를 이해하고 이해하기 위해 최선을 다할 것입니다. 도와 주셔서 대단히 감사합니다 dkusleika! –

+0

VBA 세계에서 꽤 표준이라는 것을 알고 있지만,이 코드는 헝가리 표기법 없이는 더 깨끗할 것이라고 생각합니다. – User

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가 공개인지 확인해야 할 수 있습니다.

관련 문제