Как захватить лист, добавляемый через Копировать / Вставить в Excel VBA - PullRequest
2 голосов
/ 06 апреля 2009

Я пытаюсь записать рабочие листы, копируемые в рабочую книгу, из другой рабочей книги.
Событие Workbook_NewSheet не запускается, когда листы копируются из другой рабочей книги. Он запускается только в том случае, если пользователь вручную вставляет их через (пункт меню «Вставка» -> «Рабочий лист») или когда вы добавляете новый лист через VBA как ThisWorkbook.Worksheets.Add.

То, что я пытаюсь захватить, - это в основном операция вставки, которая приводит к созданию нового листа.

Это может быть одно из следующих действий пользователя:

  1. Пользователь копирует существующий лист, перетаскивая его, удерживая клавишу управления (которая добавляет новый лист)
  2. Пользователь копирует листы из другой рабочей книги
  3. пользователь переместил листы из другой рабочей книги

или любой из следующих кодов VBA:

SourceWorkbook.Sheets(“SourceSheet”).Copy Before:=TargetWorkbook.worksheets(“SheetNameIn Target”) 'copy across workbook'  
SourceWorkbook.Sheets(“SourceSheet”).Move Before:=TargetWorkbook.worksheets(“SheetNameIn Target”) 'move across workbook'  
ThisWorkbook. Sheets(“SheetName”).Copy 'copy within workbook'  

Если вам известен какой-либо способ получения результатов этого действия / макроса в VBA, это было бы очень полезно.

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

Ответы [ 5 ]

2 голосов
/ 15 февраля 2012

Когда лист копируется, его имя всегда заканчивается "(2)" или, по крайней мере, ")". Вы можете проверить это следующим образом

Private Sub Workbook_SheetActivate(ByVal Sh As Object)
    If Sh.Name Like "*(2)" Then
        Application.DisplayAlerts = False
        Sh.Delete
        Application.DisplayAlerts = True
    End If
End Sub
2 голосов
/ 06 апреля 2009

Событие SheetActivate сработает при всех этих обстоятельствах. Очевидно, что он будет срабатывать и при многих других обстоятельствах. Это звучит как королевская боль, но вы можете сохранить свою собственную коллекцию листов и сравнить свою коллекцию с коллекцией ThisWorkbook.Sheets, чтобы увидеть, было ли что-то добавлено / удалено.

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

1 голос
/ 29 мая 2010

То, как я это понял, это

Private Sub Workbook_WindowActivate(ByVal Wn As Window)
ToggleMenuOptions False, 848, 889
End Sub

Private Sub Workbook_WindowDeactivate(ByVal Wn As Window)
ToggleMenuOptions True, 847, 848, 889
End Sub

Public Function ToggleMenuOptions(bToggle As Boolean, ParamArray ControlID() As Variant) As Boolean
'848 Move or Copy Sheet...
'889 Rename Sheet
'847 Delete Sheet
On Error GoTo lblError
Dim oControl As CommandBarControl, oControls As CommandBarControls, iControl As Integer
If IsMissing(ControlID) Then
    ToggleMenuOptions = False
    Exit Function
End If

For iControl = LBound(ControlID) To UBound(ControlID)
    For Each oControl In Application.CommandBars.FindControls(ID:=ControlID(iControl))
        oControl.Enabled = bToggle
    Next
Next
ToggleMenuOptions = True
Exit Function
lblError:
    If Err.Number Then
        ToggleMenuOptions = False
        Exit Function
    End If
End Function

Private Sub Workbook_NewSheet(ByVal Sh As Object)
MsgBox "Please use Add New Project option in custom Toolbar to add new sheets!!", vbExclamation, "Not Supported"
Application.DisplayAlerts = False
Sh.Delete
Application.DisplayAlerts = True
End Sub

Так что мои пользователи не смогут переименовывать, добавлять или удалять листы. Пока это работает очень хорошо.

0 голосов
/ 05 апреля 2016

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

Вместо того, чтобы поддерживать список листов на дополнительном скрытом листе, я определяю 2 скрытых имени на каждом листе, записывающих смещение индекса листа к связанному главному листу, и ссылку на связанный мастер-лист. Так что, если мой лист (скажем) +2 вкладки от его основного листа, то на листе активируйте / деактивируйте (не уверен, какой из них лучше отслеживать на этом этапе), это смещение будет изменено, если что-либо будет вставлено, удалено или перемещено. Это охватывает большинство или все события, которые могут возникнуть при перемещении или копировании листов.

Если лист был перемещен, я перебираю рабочую книгу и вычисляю новые ссылки на ведущий / ведомый индекс для каждого листа.

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

0 голосов
/ 13 февраля 2013

Единственный способ думать об этом без ведения отдельной коллекции листов - это поддерживать статический массив имен листов (или кодовых имен листов) и сравнивать его с фактическими листами в книге каждый раз, когда происходит событие SheetActivate, чтобы обнаружить любые дополнения. Если вы не хотите / не можете сохранить список в массиве, вы всегда можете использовать скрытый лист для хранения списка. Является ли это больше или меньше боли, чем сохранение отдельной коллекции спорна:)

...