OnClick в Excel VBA - PullRequest
       18

OnClick в Excel VBA

21 голосов
/ 07 октября 2008

Есть ли способ поймать щелчок по ячейке в VBA в Excel? Я не имею в виду событие Worksheet_SelectionChange, так как оно не сработает несколько раз, если щелкнуть ячейку несколько раз. BeforeDoubleClick также не решает мою проблему, так как я не хочу требовать, чтобы пользователь дважды щелкнул по этой кнопке.

Мое текущее решение работает с событием SelectionChange, но оно требует использования глобальных переменных и других неоптимальных методов кодирования. Это также кажется склонным к ошибке.

Ответы [ 6 ]

20 голосов
/ 08 октября 2008

Ясно, что нет идеального ответа. Однако, если вы хотите разрешить пользователю

  1. выберите определенные ячейки
  2. позволяют им менять эти клетки, и
  3. ловить каждый клик, даже повторные клики в той же ячейке,

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

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

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

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  'prevent Select event triggering again when we extend the selection below
  Application.EnableEvents = False
  Target.Resize(1, 2).Select
  Application.EnableEvents = True
End Sub
7 голосов
/ 08 октября 2008

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

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

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  'put your code here to process the selection, then..
  ActiveWindow.VisibleRange.Cells(1, 1).Select
End Sub
1 голос
/ 07 октября 2008

SelectionChange - это событие, встроенное в объектную модель Excel для этого. Он должен делать именно так, как вы хотите, стреляя в любое время, когда пользователь нажимает в любом месте ...

Я не уверен, что понимаю ваши возражения против глобальных переменных, вам понадобится только 1, если вы используете событие Application.SelectionChange. Однако в этом нет необходимости, если вы используете код класса Workbook позади (для перехвата события Workbook.SelectionChange) или код класса Worksheet позади (для перехвата события Worksheet.SelectionChange). (Если ваша проблема не является проблемой «сброса глобальной переменной» в VBA, для которой есть только одно решение: обработка ошибок везде. Не допускайте необработанных ошибок, вместо этого регистрируйте их и / или «мягко сообщайте» об ошибке как сообщение ящик для пользователя.)

Вам также может понадобиться перехватывать события Worksheet.Activate () и Worksheet.Deactivate () (или эквивалент в классе Workbook) и / или события Workbook.Activate и Workbook.Deactivate (), чтобы знать, когда пользователь переключил рабочие листы и / или рабочие тетради. Окно активации и деактивации событий должно завершить этот подход. Все они могут вызывать одну и ту же точную процедуру, однако все они обозначают одно и то же: пользователь изменил «фокус», если хотите.

Если вам не нравится VBA, кстати, вы можете сделать то же самое с помощью VB.NET или C #.

[Редактировать: Dbb очень хорошо отмечает, что событие SelectionChange не поднимает щелчок, когда пользователь щелкает в выбранной ячейке. Если вам нужно поднять это, вам нужно использовать подклассы.]

0 голосов
/ 25 мая 2018

У меня была похожая проблема, и я исправил ее, запустив макрос "onTime" и используя некоторые глобальные переменные для запуска только после того, как пользователь перестал щелкать.

Public macroIsOnQueue As Boolean
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    macroIsOnQueue = False
    Application.OnTime (Now() + TimeValue("00:00:02")), "addBordersOnRow"
    macroIsOnQueue = True
End sub
Sub addBordersOnRow()
    If macroIsOnQueue Then        
       macroIsOnQueue = False
       ' add code here
    End if
End sub

Таким образом, всякий раз, когда пользователь меняет выбор в течение 2 секунд, переменная macroIsOnQueue устанавливается в значение false, но выбор последнего раза изменяется, macroIsOnQueue устанавливается в значение true, и макрос запускается.

Надеюсь, это поможет, Веселитесь вместе с VBA !!

0 голосов
/ 14 октября 2008

Это сработало для меня .....

Private Sub Worksheet_Change(ByVal Target As Range)

    If Mid(Target.Address, 3, 1) = "$" And Mid(Target.Address, 2, 1) < "E" Then
       ' The logic in the if condition will filter for a specific cell or block of cells
       Application.ScreenUpdating = False
       'MsgBox "You just changed " & Target.Address

       'all conditions are true .... DO THE FUNCTION NEEDED 
       Application.ScreenUpdating = True
    End If
    ' if clicked cell is not in the range then do nothing (if condttion is not run)  
End Sub

ПРИМЕЧАНИЕ: эта функция в реальном использовании пересчитала сводную таблицу, если пользователь добавил элемент в диапазоне данных от A4 до D500. На листе были защищенные и незащищенные разделы, поэтому фактическая проверка щелчка выполняется, если столбец меньше «E». Логика может быть настолько сложной, насколько вы хотите включить или исключить любое количество областей

block1  = row > 3 and row < 5 and column column >"b" and < "d" 
block2  = row > 7 and row < 12 and column column >"b" and < "d" 
block3  = row > 10 and row < 15 and column column >"e" and < "g"

If block1 or block2 or block 3 then
  do function .....
end if  
0 голосов
/ 07 октября 2008

Я так не думаю. Но вы можете создать объект формы (или слово, или что-то похожее), перехватить событие Click и поместить объект в положение указанной ячейки.

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