2008-10-07 2 views
19

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

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

ответ

18

Очевидно, что нет идеального ответа.Тем не менее, если вы хотите, чтобы позволить пользователю

  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 
0

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

+0

Хм, проблема в том, что я хочу поймать, в какой ячейке она была, и иметь произвольное количество строк, которые я хочу поймать, вместе с линией, в которую он попал (SelectionChange вручает мне хороший диапазон для этого) ... – haslo 2008-10-07 14:46:09

+0

И пользователь должен иметь возможность легко редактировать лист тоже без ограничений, таких как «вам придется нажать эту кнопку, если вы добавите новую строку вручную, это не сработает». Но я абсолютно уверен, что на самом деле нет способа (VBA меня еще не удивляет), я мог бы официально принять ваш ответ ... – haslo 2008-10-07 14:47:55

1

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

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

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

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

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

+0

Глобальные переменные просто уродливые, вот и все :) Причина, по которой я использовал ее здесь в частности, потому, что я также изменил рабочий лист во время обработки события, скопировал строки в другой лист. Это действительно просто крошечное приложение, VB.NET или C# (хотя мне они нравятся намного лучше) немного перевернуты. – haslo 2008-10-09 08:51:54

+0

Кроме этого, очень хорошее понимание, спасибо! – haslo 2008-10-09 08:52:31

5

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

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

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 
0

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

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