Переименовать событие листа в Excel - PullRequest
7 голосов
/ 21 декабря 2009

Каков наилучший способ заставить код VBA работать при переименовании листа Excel?

Ответы [ 4 ]

4 голосов
/ 21 декабря 2009

Вот один из подходов. Хитрость заключается в том, чтобы перехватывать события на уровне приложения через выделенный класс. Используя событие 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

Создайте это с помощью глобальной переменной, используя событие открытия Workbook:

Public xlc As CExcelEvents

Sub Workbook_Open()
    Set xlc = New CExcelEvents
End Sub

Приведенный выше пример сработает только тогда, когда пользователь выберет другой лист. Если вам нужна дополнительная детализация, следите за событием «Смена листа».

3 голосов
/ 21 декабря 2009

Очевидно, что нет события, чтобы справиться с этим, даже используя объект приложения. Как раздражает.

Я бы, вероятно, попытался перехватить его, сохранив начальное значение рабочего листа и проверив его на как можно большем количестве событий - что, по общему признанию, является хаком.

Мне показалось, что следующее работает, надеюсь, это поможет.

В модуле ThisWorkbook:

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
0 голосов
/ 18 февраля 2019

Я знаю, что это старый вопрос, но недавно я начал использовать функцию CELL("filename") в Excel, которая возвращает сведения как об именах файлов, так и листов.

Мы можем разобрать имя листа, используя эту известную формулу:

= MID (CELL ("" имя файла "", 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
0 голосов
/ 21 декабря 2009

Я с нетерпением жду ответа на этот вопрос, потому что я не понял его после долгих поисков. На найденном мною листе нет события переименования, поэтому вы вынуждены использовать альтернативный подход.

Лучшее, что я видел (а это ужасно ) - это запретить переименование на листах, сделав их доступными только для чтения или невидимыми, а затем предоставив собственную панель инструментов или кнопку, которая выполняет переименование. Очень некрасиво и пользователи ненавидят это.

Я также видел приложения, которые отключают пункт меню переименования на офисной панели инструментов, но это не мешает дважды щелкнуть вкладку и переименовать ее. Тоже очень некрасиво и пользователи ненавидят это.

Удачи, надеюсь, кто-нибудь придумает лучший ответ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...