Страницы: 1
RSS
один обработчик событий для группы TextBox`ов
 
Добрый день! А я снова к Вам с вопросами. Честно искала решение, но не нашла. Помогите, пожалуйста!  
На userform очень много textbox`ов (57 штук), все они, кроме восьми, предназначены для ввода сумм и обработчики событий (например, KeyPress) для этих textbox`ов одинаковые.  
Очень не хочется писать руками 57-8 одинаковых Sub, а хочется решить вопрос автоматически.  
Быть может, в момент инициализации формы вставить циклы как-то так (правда, не работает):  
Dim kol As Integer  
For kol = 19 To 54 Step 5  
With TempForm.CodeModule  
       Line = .CountOfLines  
       .InsertLines Line + 1, "Sub " & List_SMB.Controls("TextBox" & kol) & "_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)"  
       .InsertLines Line + 2, "If (KeyAscii < 48 Or KeyAscii > 57) And (KeyAscii <> 44 And KeyAscii <> 46) Then KeyAscii = 0"  
       .InsertLines Line + 3, "End Sub"  
   End With  
Next kol  
 
Подскажите, пожалуйста, решение!
 
Ну так Вы сделайте Sub отдельно от textbox'ов, а в каждом текстбоксе напишите  
Call subname (имя Вашего обработчика)  
 
Или я не так понял постановку задачи?
 
{quote}{login=Haken}{date=18.03.2010 03:34}{thema=}{post}Ну так Вы сделайте Sub отдельно от textbox'ов, а в каждом текстбоксе напишите  
Call subname (имя Вашего обработчика)  
 
Или я не так понял постановку задачи?{/post}{/quote}  
 
Так придется делать 57-8=49 записей. А иное решение может быть?
 
{quote}{login=The_Prist}{date=18.03.2010 03:47}{thema=}{post}Решение есть. Необходимо создавать модуль класса. И через классы обрабатывать события. Именно для таких целей как у Вас классы и существуют - чтоб не прописывать по 50 раз одно действие на каждый контрол.{/post}{/quote}  
 
The_Prist, Вы не могли бы привести небольшой пример именно по моему вопросу?
 
Я создала модуль класса, прописала в нем обработчики для KeyPress и KeyDown - разрешение на ввод только цифр, запятой и точки.  
 
А как в  коде формы исключить несколько TextBox`ов, на которые правила класса не должны распространяться? Моя нижеприведенная попытка успехом не увенчалась:  
Dim Buttons() As New ChBoxClass  
Private Sub UserForm_Initialize()  
Dim ButtonCount As Integer  
Dim ctl As Control  
 
ButtonCount = 0  
For Each ctl In List_SMB.Controls  
       If TypeName(ctl) = "TextBox" Then  
           If ctl.Name <> "TextBox18" Or ctl.Name <> "TextBox23" Then    
               ButtonCount = ButtonCount + 1  
               ReDim Preserve Buttons(1 To ButtonCount)  
               Set Buttons(ButtonCount).ButtonGroup = ctl  
           End If  
       End If  
   Next ctl  
End Sub
 
{quote}{login=The_Prist}{date=18.03.2010 05:28}{thema=}{post}Смотрите, изучайте. Пример наипростейший. Чтоб проще было разобраться как мог расписал комментариями.{/post}{/quote}  
 
Спасибо Вам за пример! Пока разбиралась с классами модуля самостоятельно и выкладывала результат, даже не посмотрела, что Вы уже так понятно и хорошо все объяснили в своем ответе!
 
{quote}{login=The_Prist}{date=18.03.2010 05:43}{thema=}{post}If ctl.Name <> "TextBox18" and ctl.Name <> "TextBox23" Then{/post}{/quote}  
 
Спасибо!
 
Не могу никак допереть  
как в вышеприведённом примере (post_109260.xls)  
обратиться к произвольному ТекстБоксу, чтобы изменить его значение.  
Т.е. по событию TxtBx_Change() можно работать с текущим.  
А я хочу, например, ввести в текущий ТекстБокс число, а в ТекстБоксе ниже  
должно появляться число на единицу больше.  
 
Чую, что можно как-то по индексу - как к обычному элементу массива, но как... ?
 
Допёр как обратиться :)  
 
aoTxtBxes(i).oTxtBx.Value = ...  
 
А как узнать индекс текущего текстбокса, событие от которого обрабатывается?  
Не из имени же "выковыривать" :(
 
{quote}{login=Ilya}{date=10.09.2010 08:46}{thema=}{post}Не могу никак допереть  
как в вышеприведённом примере (post_109260.xls)  
обратиться к произвольному ТекстБоксу, чтобы изменить его значение.  
Т.е. по событию TxtBx_Change() можно работать с текущим.  
А я хочу, например, ввести в текущий ТекстБокс число, а в ТекстБоксе ниже  
должно появляться число на единицу больше.  
 
Чую, что можно как-то по индексу - как к обычному элементу массива, но как... ?{/post}{/quote}  
Private Sub TextBox1_Change()  
TextBox2 = Val(TextBox1) + 1  
End Sub  
один из вариантов
Спасибо
 
{quote}{login=Ilya}{date=10.09.2010 08:46}{thema=}{post}А я хочу, например, ввести в текущий ТекстБокс число, а в ТекстБоксе ниже должно появляться число на единицу больше.{/post}{/quote}  
Что значит "ниже"? Визуально TextBox, о котором Вы говорите, может быть размещён действительно "ниже", но, его индекс (TabIndex) совсем необязательно будет +1 к текущему. Другое дело, если Вы предварительно расставили эти индексы в нужном порядке (TabOrder)... Но даже и в этом случае можно обойтись без индекса: ведь Вам известно - в каком конкретно TextBox'е должно измениться значение.  
P.S. На всякий случай - так можете узнать индекс: ActiveControl.TabIndex
 
Нет, ну я не на столько "начинающий" :)  
По образованию я "СИ-шник",  
а за VBA в Экселе иногда приходится усаживаться чтобы для наших бухгалтеров сваять что-нибудь эдакое. Вот потихоньку каждый раз и натыкаюсь на нечто новое, нужное в текущем проекте.  
 
Вот сейчас парюсь с адресацией по элементам динамической формы...  
 
Насилу разобрался, в чём проблема (в самом событии TxtBx_Change),  
но пока как её разрешить не понял:  
 
возвращаемся к примеру от The_Prist (post_109260.xls) - использую его, чтобы понять физику работы новых для меня "динамических форм".  
 
В процедуре  
Private Sub oTxtBx_Change()  
 
Строка  
MsgBox oTxtBx.Name  
работает замечательно - выводится имя текущего/изменённого текстбокса  
 
Однако придуманная мною "по мотивам" строка  
aoTxtBxes(4).oTxtBx.Value = oTxtBx.Name  
уже не пашет как надо :( - я хотел в четвёртый текстбокс выводить имя изменённого текстбокса,  
НО фишка (которую я часа два "отлавливал") в том, что четвёртый-то  
текстбокс тоже изменяется такой операцией - в итоге снова генерится  
событие oTxtBx_Change()  
и значение aoTxtBxes(4).oTxtBx.Value переписывается на имя этого текстбокса,  
т.е. "TextBox4"  
И тут событие oTxtBx_Change() генерится самостоятельно уже в ТРЕТИЙ раз! %-)  
И туда вписывается снова  "TextBox4"  
Но поскольку оно равно предыдущему состоянию,  
то четвёртый раз oTxtBx_Change() уже не происходит...  
:)  
 
Вот такой детектив...  
 
Т.е. стало понятно что внутри процедуры oTxtBx_Change() изменять  
принудительно значения этих самых oTxtBx нииззя...  
 
Как быть?  
Мне очень надо чтобы по изменению юзером значения, скажем, в первом боксе,  
в другом боксе оно выставлялось на основании этого значения в первом.  
Причём эти боксы при инициализации создаются динамически и входят в один массив и один класс.  
Чую, решение где-то под носом, но бошка уже не варит...  
продолжу завтра это творчество...  
 
{quote}{login=Юрий М}{date=10.09.2010 11:45}{thema=Re: }{post}так можете узнать индекс: ActiveControl.TabIndex{/post}{/quote}  
 
Спасибо, погляжу что это такое.
 
The_Prist, спасибо за разъяснения.  
 
Сам-то пример я внимательно изучил, но...  
Я просто думал, что есть ещё способ узнать порядковый номер элемента массива кроме как из его имени. Сейчас понимаю, что просто неоткуда.  
 
Насчёт эдакого "флага запрета прерываний" (по аналогии из системного программирования :) ) тоже была мысля, но никак не могла созреть до состояния готового кода :) (мысль уходила в сторону, что на уровне Экселя можно как-то разграничить "аппаратное" (конкретно по нажатию юзером кнопки) и "программное" событие TxtBx_Change)  
 
Сейчас-то мне тоже это всё кажется элементарными вещами.  
 
Ещё раз спасибо.
 
{quote}{login=The_Prist}{date=18.03.2010 05:28}{thema=}{post}Смотрите, изучайте. Пример наипростейший. Чтоб проще было разобраться как мог расписал комментариями.{/post}{/quote}  
 
а как сделать этот же пример, но с учетом того что textbox расположены на листе, а не на форме.    
За ранее спасибо.
 
и еще вопросик: как правильнее использовать текстбоксы (комбобоксы) на форме или на листе?
 
{quote}{login=The_Prist}{date=20.03.2011 11:12}{thema=Re: }{post}{quote}{login=}{date=20.03.2011 10:39}{thema=}{post}и еще вопросик: как правильнее использовать текстбоксы (комбобоксы) на форме или на листе?{/post}{/quote}Это странный вопрос. Правильность зависит от Ваших потребностей.  
По первому вопросу: не хочу для Вас пример делать. Вам же лень сделать пример со своим TextBox-ом. А я не знаю какой именно он у Вас: элемент формы или ActiveX{/post}{/quote}  
 
Ясна. Обязательно сделаю - о результате сообщу.
 
Вообщем попробовал делать как в этом файле post_109260.xls, который прикреплен  выше по теме. Только одно но, у меня Combobox и находятся они на листе.  
 
Вот тут Me.Controls выдает ошибку (при открытии книги): Method or data  member not found  
Private Sub Workbook_Open()  
   Dim i As Integer  
       Set cbBoxes(1).ocbBx = Me.Controls("Fasad1_1_1")  
       Set cbBoxes(2).ocbBx = Me.Controls("Fasad1_2_1")  
       Set cbBoxes(3).ocbBx = Me.Controls("Fasad1_1_2")  
       Set cbBoxes(4).ocbBx = Me.Controls("Fasad1_2_2")  
End Sub
 
Вот сделал тестовый файлик
Страницы: 1
Читают тему
Наверх