Excel VBA: передать переменную `Target` из события Click в пользовательскую форму - PullRequest
1 голос
/ 10 июня 2019

Я создаю пользовательскую форму Excel 2016, используя VBA, и мне нужно собрать строку и столбец ячейки, из которой открывается форма. Я открываю форму в ячейке, дважды щелкнув Worksheet_BeforeDoubleClick, а затем инициализирую пользовательскую форму с UserForm_Initialize(). Я хотел бы передать Target события двойного щелчка на UserForm_Initialize(), но не уверен, как это сделать. Эта ветка форума решает эту проблему, но предоставленные решения не работают для меня.

Вот мой Worksheet_BeforeDoubleClick:

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
    Column = Target.Column
    Row = Target.Row

    'Find the last non-blank cell in column B(2)
    lRow = Cells(Rows.Count, 2).End(xlDown).Row

    'Find the last non-blank cell in row 2
    lCol = Cells(2, Columns.Count).End(xlToRight).Column
     If Not Intersect(Target, Range(Cells(3, 3), Cells(lRow, lCol))) Is Nothing Then
        Cancel = True
        EdgeEntryForm.Show
    End If

End Sub

И мой UserForm_Initialize():

Private Sub UserForm_Initialize()
    Dim Column As Long, Row As Long 'I would like to fill these with the Target values
    MsgBox ("Row is " & Row & " Column is " & Column)
     'Description.Caption = "Fill out this form to define a network edge from " & Cells(2, Row).Value & " to " & Cells(Column, 2).Value
End Sub

Ответы [ 2 ]

3 голосов
/ 10 июня 2019

Как предлагается в моих комментариях, одним из способов было бы просто использовать ActiveCell и присвоить его переменной.

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

В вашем листе код:

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
'.....
    With UserForm1
        Set .rngTarget = Target
        .Show
    End With
'.....
End Sub

В вашей пользовательской форме :

Public rngTarget As Range
Private Sub UserForm_Activate()
'....
    If Not rngTarget Is Nothing Then
        MsgBox ("Row is " & rngTarget.Row & " Column is " & rngTarget.Column)
    Else
        MsgBox "something went wrong with assigning rngTarget variable"
    End If
'....
End Sub

РЕДАКТИРОВАТЬ: Первоначально я пытался предложить что-то похожее на ответ @MathieuGuindon's, но терпел неудачу из-за моих ограниченных знаний о разнице между инициализацией и активацией (спасибо Матье).

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

2 голосов
/ 10 июня 2019

Форма показана модально, поэтому ActiveCell не изменится на вас и должна быть безопасной для использования в коде формы.

Проблема в том, что вы теперь привязали форму к ActiveSheet / ActiveCell, а теперь, чтобы протестировать все, что вам нужно, Select или Activate в ячейке.

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

Option Explicit
Private internalWorkingCell As Range

Public Property Get WorkingCell() As Range
    Set WorkingCell = internalWorkingCell
End Property

Public Property Set WorkingCell(ByVal value As Range)
    Set internalWorkingCell = value
End Property

Теперь ваш код формы может использовать WorkingCell или internalWorkingCell для своей работы, и никакой глобальной переменной не нужно плавать;

With New UserForm1 ' Initialize handler runs here
    Set .WorkingCell = Target 
    .Show ' Activate handler runs here
End With

WorkingCell принадлежит к форме - он не имеет бизнеса в глобальном масштабе.

Осторожнее с обработчиком Initialize в формах - , особенно , когда вы используете его экземпляр по умолчанию (т.е. когда вы не New его запускаете): вы не делаете контролировать, когда запускается этот обработчик, исполняется среда VBA; UserForm_Initialize будет запущен в первый раз, когда экземпляр формы будет ссылаться на (в вашем случае, непосредственно перед вызовом .Show), и никогда больше, если экземпляр не будет уничтожен (нажатие красной кнопки X сделает что).

Вызов MsgBox в обработчике Initialize будет выполнен до того, как отобразится форма; Возможно, вы захотите переместить этот код в обработчик Activate, прежде чем он вызовет проблемы.

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