programing

Excel에서 워크시트 이벤트 이름 바꾸기

subpage 2023. 9. 1. 20:59
반응형

Excel에서 워크시트 이벤트 이름 바꾸기

엑셀 시트의 이름을 바꿀 때 VBA 코드를 실행하는 가장 좋은 방법은 무엇입니까?

응용 프로그램 개체를 사용하더라도 이를 처리할 이벤트가 없는 것 같습니다.짜증나.

워크시트의 시작 값을 저장하고 가능한 한 많은 이벤트를 확인하여 캡처하려고 합니다. 이는 명백한 해킹입니다.

다음은 저에게 효과가 있는 것 같습니다. 도움이 되길 바랍니다.

이 워크북 모듈에서:

Private strWorksheetName As String

Private Sub Workbook_Open()
    strWorksheetName = shtMySheet.Name
End Sub

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
    Call CheckWorksheetName
End Sub
Private Sub Workbook_NewSheet(ByVal Sh As Object)
    Call CheckWorksheetName
End Sub
Private Sub Workbook_WindowDeactivate(ByVal Wn As Window)
    Call CheckWorksheetName
End Sub
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
    Call CheckWorksheetName
End Sub
Private Sub Workbook_SheetDeactivate(ByVal Sh As Object)
    Call CheckWorksheetName
End Sub
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
    Call CheckWorksheetName
End Sub

Private Sub CheckWorksheetName()
    'If the worksheet has changed name'
    If shtMySheet.Name <> strWorksheetName Then

        DoSomething

    End If
End Sub

한 가지 접근법이 있습니다.이 방법은 전용 클래스를 통해 응용 프로그램 수준에서 이벤트를 트랩하는 것입니다.SheetActivate 이벤트를 사용하여 활성화된 시트와 시트 이름에 대한 참조를 저장합니다.시트가 비활성화된 경우(및 다른 활성화된 경우) 시트 참조의 이름을 저장된 문자열과 비교합니다.CExcelEvents라고 하는 클래스는 다음과 같습니다.

Option Explicit

Private WithEvents xl As Application

Private CurrSheet As Worksheet
Private CurrSheetName As String


Private Sub Class_Initialize()
    Set xl = Excel.Application
    Set CurrSheet = ActiveSheet
    CurrSheetName = CurrSheet.Name
End Sub

Private Sub Class_Terminate()
    Set xl = Nothing
End Sub



Private Sub xl_SheetActivate(ByVal Sh As Object)
    If CurrSheetName <> CurrSheet.Name Then
        Debug.Print "You've renamed the sheet: " & CurrSheetName & " to " & CurrSheet.Name
'       Do something here - rename the sheet to original name?
    End If

    Set CurrSheet = Sh
    CurrSheetName = CurrSheet.Name
End Sub

워크북 열기 이벤트를 사용하여 글로벌 변수로 인스턴스화합니다.

Public xlc As CExcelEvents

Sub Workbook_Open()
    Set xlc = New CExcelEvents
End Sub

위의 예제는 사용자가 다른 워크시트를 선택한 경우에만 트리거됩니다.보다 세분화하려면 시트 변경 이벤트도 모니터링합니다.

오래된 질문인 것은 알지만 최근에 엑셀을 사용하기 시작했습니다.CELL("filename")파일 및 시트 이름에 대한 세부 정보를 반환하는 함수입니다.

다음과 같은 잘 알려진 공식을 사용하여 시트 이름을 구문 분석할 수 있습니다.

=MID("파일명", A1), FIND("]", CELL("파일명", A1)+1,255)"

숨겨진 워크시트에 이 함수를 쓴 다음 모니터링합니다._Calculate해당 시트에 이벤트가 있으면 워크시트 이름의 변경 사항을 확인할 수 있습니다.

고객과 VBA 코드를 공유해야 했기 때문에 이 방법을 사용해야 했습니다. 이를 통해 고객은 특정 워크시트 이름을 프로그래밍 방식으로 변경할 수 있을 뿐만 아니라 탭에 입력할 수도 있었습니다.이 메서드는 코드로 작성된 경우에도 시트 이름 변경 이벤트를 캡처합니다.

아래의 스켈레톤 코드에서 활성 워크시트의 이름 변경을 캡처했지만 대상 워크시트 목록을 추가하고 그에 따라 처리 코드를 조정하는 것을 막을 수 있는 것은 없습니다.

아래 코드는 워크북 코드 뒤에 있습니다.

Option Explicit
Private mSheetNamesWS As Worksheet
Private mOldSheetName As String

Private Sub Workbook_Open()

    'Find or create the hidden worksheet
    'containing the sheet reference.
    On Error Resume Next
    Set mSheetNamesWS = Me.Worksheets("SheetNames")
    On Error GoTo 0

    If mSheetNamesWS Is Nothing Then

        'Disable events so that the _calculate event
        'isn't thrown.
        Application.EnableEvents = False

        Set mSheetNamesWS = Me.Worksheets.Add
        With mSheetNamesWS
            .Name = "SheetNames"
            .Visible = xlSheetVeryHidden
        End With

        Application.EnableEvents = True

    End If

    'Update the sheet reference.
    If TypeOf ActiveSheet Is Worksheet Then
        UpdateCellFormula
    End If

End Sub

Private Sub Workbook_SheetActivate(ByVal Sh As Object)
    'Active sheet has changed so update the reference.
    If TypeOf ActiveSheet Is Worksheet Then
        UpdateCellFormula
    End If
End Sub

Private Sub UpdateCellFormula()
    Dim cellRef As String

    'Sense check.
    If mSheetNamesWS Is Nothing Then Exit Sub

    'The CELL function returns details about
    'the file and sheet name of any
    'specified range.
    'By adding a formula that extracts the
    'sheet name portion from the CELL function,
    'we can listen for any changes
    'of that value in the _calculate event method.

    'Disable events to avoid a spurious
    '_calculate event.
    Application.EnableEvents = False
    cellRef = ActiveSheet.Name & "!A1"
    With mSheetNamesWS.Range("A1")
        .Formula = _
            "=MID(CELL(""filename""," & _
            cellRef & _
            "),FIND(""]"",CELL(""filename""," & _
            cellRef & _
            "))+1,255)"
        mOldSheetName = .Value
    End With
    Application.EnableEvents = True

End Sub

Private Sub Workbook_SheetCalculate(ByVal Sh As Object)

    'Disregard any sheet that isn't our reference sheet.
    If Not Sh Is mSheetNamesWS Then Exit Sub

    'The reference sheet has recalculated.
    'It means the value of the cell containing
    'the current sheet name has changed.
    'Ergo we have a sheet name change.

    'Handle the event here ...
    MsgBox "You can't change the name of this sheet!"
    Application.EnableEvents = False
    ActiveSheet.Name = mOldSheetName
    Application.EnableEvents = True

End Sub

시트 이름 변경 후 발생하는 유일한 이벤트:Application.CommandBars_OnUpdate이를 기반으로 시트 이름이 변경되었는지 빠르게 확인하는 코드를 만들 수 있습니다.분명히 그러한 접근법은 투박해 보이고, 그로 인해 약간의 간접비가 있습니다.OnUpdate이벤트는 거의 모든 애플리케이션의 변경 사항에 대해 실행됩니다. 어쨌든 없는 것보다는 낫습니다.나는 그 후에 알아차렸습니다.Application_SheetSelectionChange최대 초당 약 2회 작동하므로 애플리케이션을 중단해서는 안 됩니다.

은 래퍼 입니다.Application.CommandBars_OnUpdate이벤트는 추가, 이름 바꾸기, 이동 및 삭제와 같은 추가 워크시트 이벤트를 추적하는 데 도움이 됩니다.

클래스 모듈을 만들고 이름을 지정cSheetEvents다음 코드를 입력합니다.

Option Explicit

Public Event SheetAdd(ByVal wb As Workbook, ByVal sh As Object)
Public Event SheetRename(ByVal wb As Workbook, ByVal sh As Object, ByVal oldName As String)
Public Event SheetMove(ByVal wb As Workbook, ByVal sh As Object, ByVal oldIndex As Long)
Public Event SheetDelete(ByVal wb As Workbook, ByVal oldName As String, ByVal oldIndex As Long)
Public Event SheetAny()

Private WithEvents app As Application
Private WithEvents appCmdBars As CommandBars
Private skipCheck As Boolean
Private sheetData As Object

Private Sub Class_Initialize()
    
    Set app = Application
    Set appCmdBars = Application.CommandBars
    Set sheetData = CreateObject("Scripting.Dictionary")
    Dim wb As Workbook
    For Each wb In app.Workbooks
        Dim sh As Object
        For Each sh In wb.sheets
            sheetData(sh) = Array(sh.Name, sh.index, wb)
        Next
    Next
    
End Sub

Private Sub Class_Terminate()
    
    Set sheetData = Nothing
    
End Sub

Private Sub app_NewWorkbook(ByVal wb As Workbook)
    
    Dim sh As Object
    For Each sh In wb.sheets
        sheetData(sh) = Array(sh.Name, sh.index, wb)
    Next
    
End Sub

Private Sub app_WorkbookOpen(ByVal wb As Workbook)
    
    Dim sh As Object
    For Each sh In wb.sheets
        sheetData(sh) = Array(sh.Name, sh.index, wb)
    Next
    
End Sub

Private Sub app_WorkbookNewSheet(ByVal wb As Workbook, ByVal sh As Object)
    
    sheetData(sh) = Array(sh.Name, sh.index, wb)
    RaiseEvent SheetAdd(wb, sh)
    RaiseEvent SheetAny
    skipCheck = True
    
End Sub

Private Sub app_SheetChange(ByVal sh As Object, ByVal Target As Range)
    
    skipCheck = True
    
End Sub

Private Sub appCmdBars_OnUpdate()
    
    If skipCheck Then
        skipCheck = False
    Else
        Dim anyEvt As Boolean
        Dim wb As Workbook
        For Each wb In app.Workbooks
            Dim sh As Object
            For Each sh In wb.sheets
                If Not sheetData.exists(sh) Then
                    sheetData(sh) = Array(sh.Name, sh.index, wb)
                    RaiseEvent SheetAdd(wb, sh)
                    anyEvt = True
                End If
            Next
        Next
        On Error Resume Next
        For Each sh In sheetData
            Set wb = sheetData(sh)(2)
            If wb.Name = "" Then
                sheetData.Remove sh
                Set sh = Nothing
                Set wb = Nothing
            Else
                Dim oldName As String
                oldName = sheetData(sh)(0)
                Dim oldIndex As Long
                oldIndex = sheetData(sh)(1)
                If sh.Name = "" Then
                    sheetData.Remove sh
                    Set sh = Nothing
                    RaiseEvent SheetDelete(wb, oldName, oldIndex)
                    anyEvt = True
                Else
                    If sh.Name <> oldName Then
                        sheetData(sh) = Array(sh.Name, sh.index, wb)
                        RaiseEvent SheetRename(wb, sh, oldName)
                        anyEvt = True
                    ElseIf sh.index <> oldIndex Then
                        sheetData(sh) = Array(sh.Name, sh.index, wb)
                        RaiseEvent SheetMove(wb, sh, oldIndex)
                        anyEvt = True
                    End If
                End If
            End If
        Next
        If anyEvt Then
            RaiseEvent SheetAny
        End If
    End If
    
End Sub


한 몇 가지 예를 들어보겠습니다.OnUpdate직의사건 Application_SheetChange플래그 변수를 추가하여 오버헤드를 줄이기 위해 건너뜁니다.당신은 다른 불필요한 이벤트를 건너뛸 수도 있습니다.참고, 그것은 예를 들어.Application_SheetSelectionChange사용자가 입력하여 시트의 이름을 바꾼 후 시트의 셀을 클릭하면 이벤트가 발생합니다.Application_SheetCalculate이벤트는 시트의 이름이 변경되고 휘발성 공식이 어딘가에 존재할 때 발생합니다.

오브젝트 모듈이라도 할 수 를 들어, 테트를위객모사수있다습니용할듈을체같은스해다음과,▁for▁module,다▁any▁let▁use있▁you▁object니습'.ThisWorkbook모듈에 다음 코드를 입력합니다.

Option Explicit

Private WithEvents sheetEvents As cSheetEvents

Private Sub Workbook_Open()
    
    Set sheetEvents = New cSheetEvents
    
End Sub

Private Sub sheetEvents_SheetAdd(ByVal wb As Workbook, ByVal sh As Object)
    
    MsgBox _
        "Sheet added" & vbCrLf & _
        Now & vbCrLf & vbCrLf & _
        "Workbook: " & wb.Name & vbCrLf & _
        "Name: " & sh.Name
    
End Sub

Private Sub sheetEvents_SheetRename(ByVal wb As Workbook, ByVal sh As Object, ByVal oldName As String)
    
    MsgBox _
        "Sheet renamed" & vbCrLf & _
        Now & vbCrLf & vbCrLf & _
        "Workbook: " & wb.Name & vbCrLf & _
        "Old name: " & oldName & vbCrLf & _
        "New name: " & sh.Name
    
End Sub

Private Sub sheetEvents_SheetMove(ByVal wb As Workbook, ByVal sh As Object, ByVal oldIndex As Long)
    
    MsgBox _
        "Sheet renamed" & vbCrLf & _
        Now & vbCrLf & vbCrLf & _
        "Workbook: " & wb.Name & vbCrLf & _
        "Name: " & sh.Name & vbCrLf & _
        "Old index: " & oldIndex & vbCrLf & _
        "New index: " & sh.Index
    
End Sub

Private Sub sheetEvents_SheetDelete(ByVal wb As Workbook, ByVal oldName As String, ByVal oldIndex As Long)
    
    MsgBox _
        "Sheet deleted" & vbCrLf & _
        Now & vbCrLf & vbCrLf & _
        "Workbook: " & wb.Name & vbCrLf & _
        "Name: " & oldName & vbCrLf & _
        "Index: " & oldIndex
    
End Sub

한 후. 각각의 워크북은SheetRename그리고.SheetDelete이벤트가 경고됩니다.

저는 이것에 대한 답변을 기다리고 있습니다. 왜냐하면 저는 많은 검색 끝에 그것을 알아내지 못했기 때문입니다.찾은 워크시트에 이름 바꾸기 이벤트가 없으므로 다른 방법을 사용해야 합니다.

제가 본 가장 좋은 방법은 (끔찍한 일이지만) 시트의 이름을 읽기 전용 또는 보이지 않게 만들어 이름을 바꾸는 것을 금지한 다음 이름을 변경하는 자체 도구 모음이나 단추를 제공하는 것입니다.매우 못생겼고 사용자들은 그것을 싫어합니다.

사무실 도구 모음에서 이름 바꾸기 메뉴 항목을 비활성화하는 응용 프로그램도 보았지만, 그렇다고 해서 탭을 두 번 클릭하고 이름을 바꾸는 것을 막을 수는 없습니다.또한 매우 못생겼고 사용자들은 그것을 싫어합니다.

행운을 빌어요, 누군가 더 좋은 답을 찾아냈으면 좋겠어요.

언급URL : https://stackoverflow.com/questions/1939919/rename-worksheet-event-in-excel

반응형