Событие BeforeOneClick в Excel VBA

Я ищу что-то вроде:
Private Sub Worksheet_BeforeOneClick(ByVal Target As Range, Cancel As Boolean)

Каждый раз, когда я щелкаю левой кнопкой мыши по ячейке «A1», я хочу изменить ее значение с «Да» на «Нет» и с «Нет» на «Да» (в зависимости от того, какое значение было перед щелчком).

Проблема в том, что в Excel нет такого события, как Worksheet_Before One Click. События в Excel VBA предназначены только для двойного щелчка, щелчка правой кнопкой мыши и изменения выбора (для левой кнопки - одно нажатие). Но учтите, что продолжайте нажимать один раз на A1, и я не изменяю выбор.

Я могу это сделать:
Private Sub Worksheet_SelectionChange(ByVal Target As Range) 'do my code here Range("A2").Select 'so I can again click on A1

Есть ли способ лучше?


person Przemyslaw Remin    schedule 10.12.2014    source источник


Ответы (1)


Вариант 4, представленный ниже, кажется лучшим вариантом для удовлетворения требований OP.

В Excel нет события «Worksheet_BeforeOneClick». Однако вы можете создать метку, поместить ее поверх рассматриваемой ячейки и назначить макрос событию Label_Click, которое изменяет заголовок метки и / или значение ячейки:

ВАРИАНТ 1

Шаг 1. Создайте метку ActiveX на рассматриваемом листе.

Шаг 2: Используйте следующую временную подпрограмму, чтобы разместить метку там, где вы хотите:

Sub PlaceLabel()
'Use this sub to place "Label1" where you want it. Change the Worksheet
'reference ("Sheet1") and the Range reference ("B2") as necessary.

With Label1
    .Left = Worksheets("Sheet1").Range("B2").Left + 1
    .Top = Worksheets("Sheet1").Range("B2").Top + 1
    .Height = Worksheets("Sheet1").Range("B2").Height - 1
    .Width = Worksheets("Sheet1").Range("B2").Width - 1
    .Caption = "Yes"
    .BackStyle = fmBackStyleTOpaque
End With

End Sub

Шаг 3: Добавьте следующий код на рассматриваемый рабочий лист:

Private Sub Label1_Click()
'Use this sub to change the caption of Label1 as necessary. If you rename
'the label, you will need to replace "Label1" both in the code and in the
'name of the sub with the new label name.

If Label1.Caption = "Yes" Then
    Label1.Caption = "No"
    Worksheets("Sheet1").Range("B2").Value = "No"
    GoTo EndOfSub
ElseIf Label1.Caption = "No" Then
    Label1.Caption = "Yes"
    Worksheets("Sheet1").Range("B2").Value = "Yes"
End If

EndOfSub:

End Sub

Как отмечено в прокомментированных частях подпрограммы, если метка будет переименована, «Label1» необходимо будет заменить как в коде, так и в имени подпрограммы.

Это позволит вам ссылаться либо на значение ячейки, либо на заголовок метки.

ВАРИАНТ 2 - показывает форматирование ячеек (при необходимости).

Шаг 1. Создайте метку ActiveX на рассматриваемом листе.

Шаг 2: Используйте следующую временную подпрограмму, чтобы разместить метку там, где вы хотите:

Sub PlaceLabel()
'Use this sub to place "Label1" where you want it. Change the Worksheet
'reference ("Sheet1") and the Range reference ("B2") as necessary.

With Label1
    .Left = Worksheets("Sheet1").Range("B2").Left + 1
    .Top = Worksheets("Sheet1").Range("B2").Top + 1
    .Height = Worksheets("Sheet1").Range("B2").Height - 1
    .Width = Worksheets("Sheet1").Range("B2").Width - 1
    .Caption = ""
    .BackStyle = fmBackStyleTransparent
End With

End Sub

Шаг 3: Добавьте следующий код на рассматриваемый рабочий лист:

Private Sub Label1_Click()
'Use this sub to change the value of the cell in question as necessary.
'Rename the Worksheet and Range as necessary.

With Worksheets("Sheet1").Range("B2")
    If .Value = "Yes" Then
        .Value = "No"
        GoTo EndOfSub
    ElseIf .Value = "No" Then
        .Value = "Yes"
    End If
EndOfSub:
End With

End Sub

Эта опция использует прозрачную метку, поэтому формат ячейки будет виден вместо метки. Однако вам нужно будет переместить курсор с метки, чтобы изменение отобразилось.

ВАРИАНТ 3

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

Private Sub Worksheet_BeforeRightClick(ByVal Target As Range, Cancel As Boolean)
'This sub changes the value of cell "B2" from No to Yes or from Yes to No as necessary
'on right click. It also disables the right-click menu for that cell only if the value
'of the cell is either Yes or No.

If Target.Column = 2 And Target.Row = 2 Then
    If Target.Value = "No" Then
        Target.Value = "Yes"
        Cancel = True
    ElseIf Target.Value = "Yes" Then
        Target.Value = "No"
        Cancel = True
    End If
End If

End Sub

Затем вы можете добавить входное сообщение в разделе «Проверка данных», чтобы дать пользователю указание щелкнуть правой кнопкой мыши:

введите описание изображения здесь

ВАРИАНТ 4

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

Шаг 1. Создайте метку ActiveX на рассматриваемом листе и поместите ее в левый верхний угол листа. (Его можно разместить где угодно, но если вы поместите его в левом верхнем углу, при необходимости будет легче найти)

Шаг 2. Установите следующие свойства метки, щелкнув ее правой кнопкой мыши или щелкнув «Свойства» на вкладке «Разработчик», когда метка выбрана:

(Name)        ReadyLabel
BackStyle     0 - fmBackStyleTransparent
Caption                                     '(Set to empty)
Enabled       False
PrintObject   False
Visible       False

Шаг 3: Добавьте следующий код на рассматриваемый рабочий лист:

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

If Target.Column = 4 And Target.Row = 4 Then
    Application.ScreenUpdating = False
    If Target.Value = "No" Then
        Target.Value = "Yes"
        ActiveSheet.Range("A1").Select
        ReadyLabel.Visible = True
        ReadyLabel.Select
        ReadyLabel.Visible = False
        Application.ScreenUpdating = True
    ElseIf Target.Value = "Yes" Then
        Target.Value = "No"
        ActiveSheet.Range("A1").Select
        ReadyLabel.Visible = True
        ReadyLabel.Select
        ReadyLabel.Visible = False
        Application.ScreenUpdating = True
    End If
End If

End Sub

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

Если ваша ячейка «Да / Нет» находится в ячейке «A1», код нужно будет немного изменить, чтобы он работал. Кроме того, вам сначала нужно будет поставить в ячейку либо «Да», либо «Нет».

person TheEngineer    schedule 10.12.2014
comment
Спасибо за ваш ответ. Цель моего вопроса - создать форму - контрольный список - в Excel. Почему-то я хотел избежать флажков Control или AcitveX. Просто щелкните ячейку, чтобы отметить ее, и щелкните еще раз, чтобы снять ее. - person Przemyslaw Remin; 11.12.2014
comment
Вы согласны с использованием метки ActiveX, как я описал, или вы ищете другое решение? Если вы будете использовать мое решение, я был бы признателен, если бы вы отметили ответ как правильный. - person TheEngineer; 11.12.2014
comment
Как я уже сказал в своем комментарии, я не доволен ни решениями Control, ни ActiveX. Мне нужны только ячейки Excel в моей форме. - person Przemyslaw Remin; 12.12.2014
comment
Я добавил третий вариант, использующий событие щелчка правой кнопкой мыши, которое отключает контекстное меню для этой ячейки. Я не могу придумать другого способа достичь того, что вы ищете, одним щелчком мыши. Надеюсь, вы сможете использовать один из этих вариантов. - person TheEngineer; 12.12.2014
comment
Поскольку я могу использовать скрытый столбец, мое решение по-прежнему кажется наиболее интуитивно понятным. Что-то вроде Selection = Nothing решило бы проблему, потому что мне вообще не пришлось бы использовать скрытый столбец. - person Przemyslaw Remin; 15.12.2014
comment
Я добавил четвертый вариант, который должен удовлетворить все ваши требования. Однако он использует элемент управления ActiveX; хотя это только для удаления выделения. - person TheEngineer; 16.12.2014
comment
@PrzemyslawRemin Удалось ли вам использовать четвертый вариант? - person TheEngineer; 22.12.2014
comment
Спасибо за ваш вариант Forth. Хотя это дело вкуса, я все же считаю свое основное решение более простым и элегантным. - person Przemyslaw Remin; 29.12.2014
comment
@PrzemyslawRemin Если ваше решение - это то, что вы использовали, пожалуйста, добавьте его в качестве ответа и примите его, чтобы будущие посетители могли легко увидеть, что сработало для вас. - person TheEngineer; 29.01.2015