Страницы: 1
RSS
Корректная передача UserForm как параметр Sub-а, Корректность использования процедуры типа sub test (frm as UserForm)
 
Работаю над оптимизацией кода. Т.к. он получается очень нагромождённым.
И некоторые процессы, я понимаю, что их можно упростить. Но в виду слабого понимания ограничений VBA не могу корректно изложить код.

суть проблемы:
Есть код, например:
Код
sub GetData()
UserForm1.Show vbModeless
WaitForInput (UserForm1)
end sub

sub WaitForInput (frm as UserForm)
Do Until frm.Visible = False
    DoEvents
Loop
end sub
По не понятной мне причине, VBA ругается на Typemismatch.

Поиском пользовался. Ответа не нашел.
Благодарю, если поделитесь знаниями.

Тестовый файл приложен.
 
Код
frm as Variant
'или
frm as Object
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
The_Prist, пробовал как Object и как Variant, но тогда, он ругается на моменте:
Код
Do Until frm.Visible = False

И говорит, что такого параметра у этой переменной нету =(
Как можно Object или Variant преобразовать в форму в нутри дочернего модуля?
Или я задаю не правильный вопрос?
Изменено: SanShiney - 01.05.2016 09:52:38
 
Доброе время суток
Вариант в объектно-событийном стиле, без всяких там DoEvents. Правда, оказалось, что событие форм QueryClose относится к Private - снаружи не видно. Пришлось добавлять собственное событие в форму и привязывать класс обработчик события к конкретному классу формы, что, увы, становится не универсальным решением.
 
Вопрос по первой ошибке.
Код
Call WaitForInput(UserForm1)

Явное указание перехода к другой процедуре не вызывает ошибки, WaitForInput начинает работать. Почему с Call работает, а без него не хочет?
 
Виктор, у меня и с Call и без Call была ошибка (Excel 2016 64bit), так как в самом классе UserFrom нет свойства Visible. Вот если явно указывать в WaitForInput параметр UserForm1 тогда да. Но в любом случае возникает ошибка при закрытии формы. Опять же получаем не универсальное решение
Код
Sub GetData()
    UserForm1.Show vbModeless
    WaitForInput UserForm1
End Sub
 
Sub WaitForInput(frm As UserForm1)
On Error GoTo ExitCode
Do While frm.Visible
    DoEvents
Loop
ExitCode:
MsgBox "form was closed"
End Sub
Изменено: Андрей VG - 01.05.2016 10:42:32
 
Адндрей, я  писал - по первой ошибке. без Call ошибка возникает на строке перехода к процедуре:
Код
WaitForInput (UserForm1)
с Call в процедуру заходит
Код
Call WaitForInput (UserForm1)

Т.е. пустой макрос отрабатывает
Код
Sub WaitForInput(frm As UserForm)
End Sub
 
Цитата
vikttur написал: Т.е. пустой макрос отрабатывает
Извиняюсь, этот момент пропустил. У меня и с Call и без него работает. Ошибки не возникает. Думаю, от версии VBA зависит.
 
Вить, в своё время была тема: пришли к выводу, что лучше в любом случае писать Call. Помнится, там ещё пример был: имя вызываемой процедуры было Copy. Вот и получим команду вместо вызова ))
 
Я имею представление как работает код. И примерно догадываюсь о возможностях.
Если, изложенный вопрос трудно реализуем, то, можно ли:
Передать в WaitForInput имя формы?
А в самом макросе,
Код
Sub WaitForInput (frmname As String)

Через наименование формы "подвязаться" к корретной форме?
Т.е. если принять, что frmname содержит название нужной формы, то можно ли как то сослаться на корректный объет?

Прошу прощения, если я несу ахинею.
Самоучка (думаю, как и все тут). Но терминологию не зубрил. Могу некоторые вещи называть не правильно.
 
SanShiney, а позвольте поинтересоваться, чем предложенные мной варианты вас не устроили? Или форм много и для каждой писать свой метод затратно? Тогда просто напишите общую процедуру без параметров и в каждой форме для события Terminate напишите её вызов. Самый простой подход.
Изменено: Андрей VG - 01.05.2016 13:07:44
 
Андрей VG,
Понял. Спасибо!
Просто, комментарий, о том, что решение не универсально у меня расценивалось "ответ не найден". =)

Форм у меня не много. Просто, бюсь, в последующем, при доработке и добавлении форм, могу забыть  об этой особенности и затрачу уйму времении на поиск ошибки. =)

Но спасибо большое!
Буду пользоваться вашим вариантом.
 
Цитата
SanShiney написал:
Просто, комментарий, о том, что решение не универсально у меня расценивалось "ответ не найден". =)
Ну, наиболее универсальным, в силу объектной модели MSForms - нет доступного события закрытия формы, будет как раз последний вариант: вызов универсального метода, обрабатывающего закрытие формы из события формы
Допустим в обычном модуле
Код
Public Sub OnFormClosed(ByVal FormName As String)
    MsgBox "A form " & FormName & " was closed"
End Sub

А в коде формы
Код
Private Sub UserForm_Terminate()
    OnFormClosed Me.Name
End Sub

Успехов.
 
Андрей VG, только сейчас понял о чем речь!
Спасибо!
Это идеальный вариант!
 
Не совсем понял смысл всех манипуляций, но может такой вариант тоже когда-то пригодится:
Код
Public lFrm_cnt As Long
Sub GetData()
lFrm_cnt = UserForms.Count
UserForm1.Show vbModeless
WaitForInput UserForm1
End Sub

Sub WaitForInput(frm As Object)
Do Until lFrm_cnt <> UserForms.Count
    DoEvents
Loop
MsgBox frm.Name
End Sub
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Доброе время суток.
Цитата
The_Prist написал: Не совсем понял смысл всех манипуляций
Дмитрий, да смысл простой - только не совсем внятно сформулирован. Попробую перефразировать.
Имеется немодальная форма. Необходимо выполнить некоторый код после её закрытия. Или по другому, как отследить событие закрытия немодальной формы.
 
Цитата
vikttur написал: без Call ошибка возникает на строке перехода к процедуре: WaitForInput (UserForm1)
с Call в процедуру заходит: Call WaitForInput(UserForm1)
Господа, Вы забыли, что в первом случае VBA вычисляет выражение в скобках и передаёт его в процедуру. Тогда как, во втором случае VBA обращается к процедуре с параметром UserForm1. Эти два варианта даже различаются написанием:
- в первом случае между именем процедуры и открывающей скобкой VBA вставляет пробел;
- во втором - имя процедуры и скобка пишутся вместе.
Чтобы избавиться от "Call" надо убрать скобки вокруг параметра.
Страницы: 1
Наверх