2016-07-22 4 views
0

Я создаю пользовательскую форму, где у нее есть два текстовых поля для ввода дат. После ввода даты я проверяю их, когда происходит событие Exit. Если проверяется, что пользовательские данные не являются тем, что необходимо, пользователь уведомляется, текстовое поле очищается, а фокус возвращается обратно в текстовое поле.Excel VBA - Вызов события TextBox для входа в Userform вручную?

Проблема возникает, если пользователь использует мышь для выбора вне поля, а не Tab. Если используется Tab, он срабатывает отлично и, как ожидалось, и поле очищается, а фокус возвращается. Если мышь используется, она не срабатывает. Согласно this article, это ожидаемое поведение (это для доступа, но я не видел аналогичную соответствующую статью MSDN для Excel.)

Так что вместо этого я попробовал событие AfterUpdate. Однако SetFocus не работает в событии AfterUpdate, я предполагаю из-за цепочки событий, как указано в ответе на this question. Таким образом, у меня нет способа вернуть фокус обратно в текстовое поле после его запуска. Этот поток имел предложение в качестве альтернативного ответа на SetFocus на другой элемент управления и возвращался в качестве обходного пути, но это не работает для меня, поэтому я предполагаю, что это может быть обходное решение для конкретного доступа.

Моего последний варианта Я рассмотрел это имеющий AfterUpdate события просто называю Exit события, однако Exit события имеет необходимый аргумент (ByVal Cancel As MSForms.ReturnBoolean), который, как вы отмените выход и возвращаете пользователь в текстовое поле. Таким образом, нет никакого значения, которое вы можете передать ему, которое не вызывает ошибку, которую я могу найти (ближайший я обнаружил, что он прошел Nothing, но он не удался при попытке установить его на True позже, чтобы отменить выход .)

Есть ли способ достичь того, что я ищу здесь, или я должен просто придерживаться AfterUpdate и игнорировать SetFocus, которого я пытаюсь достичь?

+0

Было бы очень полезно показать существующий код. Вам не нужно класть весь свой код в обработчики событий: переместите сравнение дат в автономный суб и просто вызовите это из обработчиков событий. Новый Sub позаботится о том, чтобы установить фокус обратно в соответствующее текстовое поле. –

+0

Спасибо, Тим, я попытаюсь перенести его на отдельный суб-первый. Это может помочь мне уменьшить часть моего кода, поскольку в настоящее время у меня есть дублирование для разных текстовых полей. Я не опубликовал полный код, поскольку он довольно длинный (он проверяет довольно много сравнений между разными датами и текущим временем), но при необходимости я вернусь и отредактирую в соответствующих битах. – Goose306

ответ

0

Exit событие работает на всех щелчках мыши, которые запускают Enter для другого элемента управления на форме. Но когда вы нажимаете, прямо на форме вместо любого другого элемента управления, ничего не происходит.

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

Образец кода, переработайте его в соответствии с вашими требованиями.

Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean) 
    Call doValidation(Me.TextBox1.Text) '/ Validation Routine when user leaves TextBox 
End Sub 

Private Sub UserForm_Click() 
    '/ If user clicked on the user form instead of ay other control 
    If Me.ActiveControl.Name = Me.TextBox1.Name Then 
     Call doValidation(Me.TextBox1.Text) '/ Validation Routine when user leaves TextBox 
    End If 
End Sub 

Private Sub doValidation(strText) 
     MsgBox strText 
End Sub 

Консультировать: Для Дата входа используйте DateTimePicker вместо TextBox, избавят вас от многих проблем в будущем.

+0

Это оказалось лучшим решением, которое я смог найти, спасибо. Я не могу использовать DateTimePicker, поскольку для этого требуются элементы управления ActiveX, которые не работают в x64 версиях Office. – Goose306

+0

ах 64-разрядная дилемма ... :) – cyboashu

0

В VBA вы можете вызвать любую определенную подфункцию или функцию со словом Call Subname: , например. Call Textbox1_exit (params)

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

и порядок формы событий:

https://support.office.com/en-us/article/Order-of-events-for-database-objects-e76fbbfe-6180-4a52-8787-ce86553682f9

Я думаю, что для вашего приложения с описанием вы дали lost_focus или got_focus для некоторых компонентов может оказаться полезным. Кроме того, вы можете вручную настроить фокусировку практически на любой компонент, встроенный в метод: compName.SetFocus()

+1

К сожалению, это не помощь. Статьи clinked для Access, и если вы читаете далее, вы заметите, что Excel VBA не имеет события Lost_Focus, он связан с событием Exit, для которого требуется параметр, который, как представляется, не может быть вызван вручную. Кроме того, SetFocus не работает в AfterUpdate, что является единственным способом (легко) захватить пользователя, выходящего из элемента управления, с помощью мыши и щелкая в другом месте. Наконец, обычно использование Call не является лучшей практикой во многих случаях, так как вы не можете возвращать значения и использовать результаты круглых скобок в оценке. – Goose306

+0

Угадайте, я прочитал это неправильно, я думал, что он делает форму доступа. Спасибо – bzn

0

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

Для проверки данных Excel Textbox используйте событие BeforeUpdate, оно срабатывает перед событием AfterUpdate и имеет возможность предотвратить потерю фокуса на элементе управления.

Ремонтное образец кода с вашими требованиями

Cancel = True Помните останавливает обновление управления для контроля и остается в центре внимания.

Private Sub TextBox1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean) 
    Cancel = doValidation(Textbox1.Text) 'Validation Route 
End Sub 

Private Function doValidation(strText) as Boolean 
    'Do Validation 
    if Valid then 
     doValidation = False 
    Else 
     msgBox "Not Valid" 
     doValidation = True 
    End if 
End Sub 

На мой взгляд, это самый простой способ проверить вход на Excel UserForm Textbox

Я не могу сейчас найти правильную статью MSDN в это время, все Google хочет вернуть доступ Результаты.