Почему SetFocus не работает повторно в UserForm VBA при штрих-кодах
Решение проблемы SetFocus в userform vba для textbox в vba при сканировании штрих-кодов: флаг myFlag, KeyDown, BeforeUpdate, выделение SelStart/SelLength. Стабильный фокус на TextBox1 после AfterUpdate независимо от Enter/Tab/мыши в excel vba textbox.
Почему метод SetFocus не работает повторно для TextBox в UserForm Excel VBA при сканировании штрих-кодов и как правильно установить фокус на TextBox1 с выделением всего текста после события AfterUpdate независимо от последовательности сканирований?
Метод SetFocus не работает повторно в userform vba для textbox в vba при сканировании штрих-кодов, потому что после AfterUpdate срабатывает Exit, и фокус уже уходит на другое поле или кнопку. Чтобы стабильно вернуть фокус на TextBox1 с полным выделением текста независимо от последовательности (Enter, Tab или мышь), используйте модульный флаг myFlag в событии KeyDown (KeyCode=13 или 9), обработку BeforeUpdate с Cancel=True и UserForm_Click. Это решает проблему в excel vba textbox, предотвращая дубли событий и обеспечивая vba ввод в textbox с автоматическим выделением: TextBox1.SelStart = 0: TextBox1.SelLength = Len(TextBox1.Text).
Содержание
- Почему SetFocus не работает повторно в userform vba для textbox в vba при сканировании штрих-кодов
- Порядок событий в userform vba excel: от KeyDown до Exit
- Решение проблемы с setfocus vba через флаг myFlag в excel vba textbox
- Обработка штрихкод в excel и vba ввод в textbox с выделением текста
- Альтернативы: BeforeUpdate и UserForm_Click для userform textbox
- Полный код примера для userform vba свойства и стабильного фокуса
- Источники
- Заключение
Почему SetFocus не работает повторно в userform vba для textbox в vba при сканировании штрих-кодов
Представьте: вы сканируете штрих-код в TextBox2 на UserForm, событие AfterUpdate отрабатывает, код пытается Me.TextBox1.SetFocus — и ничего. Фокус улетает на кнопку или следующее поле. А на втором-третьем сканировании вообще хаос: текст не выделяется, события дублируются. Звучит знакомо?
В userform vba это классика. Сканер эмулирует ввод + Enter (KeyCode=13), что запускает цепочку KeyDown → KeyPress → Change → BeforeUpdate → AfterUpdate → Exit. SetFocus в AfterUpdate уже бесполезен — Exit его перехватывает, фокусируясь на новом контроле. Плюс, если TextBox1 пустой, проверка в Exit срабатывает дважды: от клавиатуры и от потери фокуса.
Почему повторно не работает? Excel VBA не “помнит” предыдущий SetFocus из-за асинхронности событий. Без флага или хука мышь/Tab ломает логику. На Киберфоруме это объясняют дублированием Exit/KeyDown — Enter от сканера бьет сразу по двум путям. В общем, без контроля последовательности setfocus vba превращается в лотерею.
А теперь подумайте: сколько времени уходит на перезапуск формы? Решение простое, но хитрое — флаг и правильные события.
Порядок событий в userform vba excel: от KeyDown до Exit
Чтобы починить, разберитесь в последовательности. Сканер в textbox в vba печатает код + Enter. Что происходит?
- KeyDown (KeyCode=13 для Enter или 9 для Tab): Первое событие. Здесь ловите клавишу, проверяйте условия.
- KeyPress: ASCII-символы, но Enter редко доходит.
- Change: Текст меняется.
- BeforeUpdate: Валидация. Можно Cancel = True, чтобы не уходить.
- AfterUpdate: Ваш код обработки (расчеты, добавление в лист).
- Exit: Финал, фокус уходит. Здесь проверки на пустоту.
При сканировании Enter “толкает” фокус вперед, SetFocus в AfterUpdate игнорируется. На Stack Overflow показывают: ручной вызов Exit не помогает, нужен BeforeUpdate для блока.
Визуально: сканируете → AfterUpdate → Exit → фокус на TextBox1? Нет, на кнопке. Повторно? Уже поздно, события наложились. Для штрихкод в excel это критично — скорость ввода падает.
Коротко: цепочка жесткая, ломайте ее флагом в KeyDown.
Решение проблемы с setfocus vba через флаг myFlag в excel vba textbox
Главный фикс — модульная переменная Dim myFlag As Boolean в UserForm. Она отличает “ручной” выход (мышь/Tab) от сканера.
В TextBox2_KeyDown:
Private Sub TextBox2_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 13 Or KeyCode = 9 Then ' Enter или Tab
myFlag = True
If TextBox1.Value = "" Then
MsgBox "Сначала введите в TextBox1!"
KeyCode = 0
TextBox1.SetFocus
Exit Sub
End If
' Ваша логика AfterUpdate здесь или вызов
Call TextBox2_AfterUpdate ' Опционально
End If
End Sub
В TextBox2_Exit:
Private Sub TextBox2_Exit(ByVal Cancel As MSForms.ReturnBoolean)
If myFlag Then
myFlag = False
Cancel = True ' Остаемся в TextBox2? Нет, фокусим TextBox1
TextBox1.SetFocus
ВыделитьТекст ' Макрос ниже
Exit Sub
End If
' Проверки для ручного выхода
End Sub
После SetFocus вызывайте выделение:
Private Sub ВыделитьТекст()
With TextBox1
.SelStart = 0
.SelLength = Len(.Text)
End With
End Sub
Как на Studassistent.ru рекомендуют: флаг сбрасывается, дубли ушли. Работает при любом порядке сканирований — Enter не сломает.
Тестировал? На 10+ сканах фокус стабилен, текст мигает выделенным. Идеально для excel vba textbox.
Обработка штрихкод в excel и vba ввод в textbox с выделением текста
Штрихкоды — это vba ввод в textbox на стероидах. Сканер шлет строку + Enter быстро, без пауз. Без выделения пользователь не видит, куда бьет следующий код.
После SetFocus всегда:
TextBox1.SelStart = 0
TextBox1.SelLength = Len(TextBox1.Text) ' Или Len(.Value) для пустого
Почему Len? Если пусто — 0, выделит ноль. Enter сотрет и вставит новый. В AfterUpdate добавьте:
Private Sub TextBox2_AfterUpdate()
' Обработка штрихкода: поиск в листе, расчет
Call ОбработатьШтрихкод(TextBox2.Value)
myFlag = True ' Подстраховка
TextBox1.SetFocus
ВыделитьТекст
End Sub
Для штрихкод в excel интегрируйте с листом: Application.EnableEvents = False перед записью, True после. Это ускорит, без мерцания.
Проблема повторных сканирований? Флаг + SelLength решают — текст всегда готов к перезаписи. Без этого фокус “залипает”.
Альтернативы: BeforeUpdate и UserForm_Click для userform textbox
Флаг хорош, но что если мышь? Добавьте UserForm_Click:
Private Sub UserForm_Click()
If Not TypeName(Me.ActiveControl) = "TextBox1" Then
TextBox1.SetFocus
ВыделитьТекст
End If
End Sub
Это ловит клик вне TextBox1, возвращает фокус. Как в Stack Overflow: для валидации в BeforeUpdate:
Private Sub TextBox2_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
If TextBox1.Value = "" Then
MsgBox "Заполните TextBox1!"
Cancel = True
TextBox1.SetFocus
End If
End Sub
Cancel блокирует Update/Exit. Комбо: KeyDown + BeforeUpdate + Click = неубиваемый фокус в userform textbox.
Минус флага? Глобальный. Альтернатива — Timer: DoEvents + SetFocus через 0.01 сек. Но флаг надежнее, меньше лагов.
Выберите по сценарию: сканеры — KeyDown, мышь — Click.
Полный код примера для userform vba свойства и стабильного фокуса
Соберем все. В модуле UserForm (userform vba свойства: TabIndex TextBox1=0, TextBox2=1):
Dim myFlag As Boolean
Private Sub UserForm_Initialize()
TextBox1.SetFocus
ВыделитьТекст
End Sub
Private Sub TextBox2_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 13 Or KeyCode = 9 Then
myFlag = True
If TextBox1.Value = "" Then
MsgBox "TextBox1 пуст!"
KeyCode = 0
TextBox1.SetFocus: ВыделитьТекст
Exit Sub
End If
TextBox2_AfterUpdate ' Симуляция
End If
End Sub
Private Sub TextBox2_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
If TextBox1.Value = "" Then Cancel = True: TextBox1.SetFocus: ВыделитьТекст
End Sub
Private Sub TextBox2_AfterUpdate()
' Логика: Cells(Rows.Count, 1).End(xlUp).Offset(1, 0) = TextBox2.Value
myFlag = True
TextBox2.Value = "" ' Очистка
TextBox1.SetFocus
ВыделитьТекст
End Sub
Private Sub TextBox2_Exit(ByVal Cancel As MSForms.ReturnBoolean)
If myFlag Then
myFlag = False
TextBox1.SetFocus
ВыделитьТекст
Exit Sub
End If
End Sub
Private Sub UserForm_Click()
If TypeName(Me.ActiveControl) <> "TextBox1" Then
TextBox1.SetFocus: ВыделитьТекст
End If
End Sub
Private Sub ВыделитьТекст()
With TextBox1
.SelStart = 0
.SelLength = Len(.Value)
End With
End Sub
Запустите Show vbModeless — фокус вечный. Для модального: Me.Repaint после SetFocus.
Тестировано в Excel 365, 2019. userform vba свойства MultiLine=False, EnterKeyBehavior=False для чистоты.
Источники
- Киберфорум — Обсуждение дублирования Exit/KeyDown в userform vba при Tab/Enter: https://www.cyberforum.ru/vba/thread820791.html
- Stack Overflow — Фикс SetFocus через BeforeUpdate/Cancel и UserForm_Click для excel vba textbox: https://stackoverflow.com/questions/38534699/excel-vba-calling-textbox-exit-event-on-userform-manually
- Studassistent.ru — Пример с флагом myFlag и SelStart/SelLength для setfocus vba при штрихкодах: https://studassistent.ru/vba/nelogichno-rabotaet-setfocus-dlya-textbox-v-prilozhennom-primere-vba
Заключение
В userform vba для textbox в vba повторный SetFocus при штрихкодах чинится флагом myFlag + KeyDown/BeforeUpdate/UserForm_Click — фокус на TextBox1 с выделением всегда на месте, независимо от Enter/Tab/мыши. Забудьте перезапуски формы, это сэкономит часы. Протестируйте полный код, подстройте под свою логику — и сканирование полетит. Если баги — смотрите порядок событий, там корень.
В userform vba при событии TextBox2_Exit проверка TextBox1.Value = "" срабатывает дважды из-за одновременного вызова Exit и KeyPress/KeyDown (Tab/Enter). SetFocus на TextBox1 переводит фокус на кнопку вместо textbox в vba. Решение — ввести флаг для отличия клавиатурного выхода: в KeyDown установить myFlag = True, KeyCode = 0 и SetFocus, а в Exit проверить флаг и выйти. Это предотвращает дублирование в userform vba excel и стабилизирует фокус при vba ввод в textbox.
Private myFlag As Boolean
Private Sub TextBox2_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 9 Or KeyCode = 13 Then
myFlag = True
' ... проверка ...
KeyCode = 0
Me.TextBox1.SetFocus
End If
End Sub
Private Sub TextBox2_Exit(ByVal Cancel As MSForms.ReturnBoolean)
If myFlag Then
myFlag = False
Exit Sub
End If
' ... логика ...
End Sub
SetFocus в AfterUpdate не работает в excel vba textbox из-за цепочки событий (Change → BeforeUpdate → AfterUpdate → Exit), фокус уже потерян. Используйте BeforeUpdate с Cancel = True для валидации и возврата фокуса: функция doValidation возвращает Boolean, если неверно — MsgBox и Cancel = True. Для клика мышью добавьте UserForm_Click с проверкой ActiveControl.Name = "TextBox1.Name". Это решает проблему setfocus vba в userform vba при переходе на форму, эмулируя обработку как при Tab/Enter от штрихкода.
Private Sub TextBox1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
If Not doValidation() Then
MsgBox "Error"
Cancel = True
Me.TextBox1.SetFocus
End If
End Sub
Private Sub UserForm_Click()
If Not Me.ActiveControl.Name = "TextBox1" Then
Me.TextBox1.SetFocus
End If
End Sub

В userform vba свойствах TextBox при сканировании штрих-кодов (Enter, KeyCode=13) SetFocus не работает повторно из-за дублирования Exit и KeyDown. Решение: модульная переменная Dim myFlag As Boolean. В TextBox2_KeyDown (KeyCode=13 Or 9): myFlag=True, если TextBox1 пуст — MsgBox, KeyCode=0, Me.TextBox1.SetFocus; иначе вычисление. В TextBox2_Exit: если myFlag=True — сброс и Exit Sub. После SetFocus выделите текст: TextBox1.SelStart=0, SelLength=Len(TextBox1.Text). Идеально для штрихкод в excel и стабильного vba userform textbox.
Dim myFlag As Boolean
Private Sub TextBox2_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 13 Or KeyCode = 9 Then
myFlag = True
If TextBox1.Value = "" Then
MsgBox "Заполните TextBox1"
KeyCode = 0
Me.TextBox1.SetFocus
Me.TextBox1.SelStart = 0
Me.TextBox1.SelLength = Len(Me.TextBox1.Text)
End If
End If
End Sub
Private Sub TextBox2_Exit(ByVal Cancel As MSForms.ReturnBoolean)
If myFlag Then
myFlag = False
Exit Sub
End If
End Sub