Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Microsoft Office и VBA программирование > Microsoft Office Excel
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 11.01.2012, 17:20   #1
vinvin
Новичок
Джуниор
 
Регистрация: 11.01.2012
Сообщений: 7
По умолчанию Создание элементов UserForms в RunTime

Пытаюсь динамически создать CommandButton в UserForm. Событие Click для кнопки уже прописано, но после добавления - не работает. Что делать? И почему не работает? Пробовал в 2003, 2007.

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

PHP код:
Private Sub UserForm_Initialize()
    
Me.Controls.Add "Forms.CommandButton.1""CommandButton1"True
End Sub
Private Sub CommandButton1_Click()
    
MsgBox "This is CommandButton"
End Sub 

Последний раз редактировалось vinvin; 11.01.2012 в 17:22. Причина: Изменил заголовок
vinvin вне форума Ответить с цитированием
Старый 11.01.2012, 17:47   #2
Казанский
Старожил
 
Аватар для Казанский
 
Регистрация: 31.12.2010
Сообщений: 2,133
По умолчанию

Поиск по "модуль класса", например http://www.programmersforum.ru/showt...872#post279872
exceleved@yandex.ru Яндекс.Деньги: 410011500007619
Казанский вне форума Ответить с цитированием
Старый 12.01.2012, 15:32   #3
slan
Форумчанин
 
Аватар для slan
 
Регистрация: 30.01.2008
Сообщений: 314
По умолчанию

а почему сразу не создать, а потом менять видимость и местоположение?
slan вне форума Ответить с цитированием
Старый 13.01.2012, 14:08   #4
vinvin
Новичок
Джуниор
 
Регистрация: 11.01.2012
Сообщений: 7
По умолчанию

Согласен, видимость лучше делать после всех установок, касающихся отображения.

Вопрос я решил.

Короче, в режиме Runtime добавлять контролы можно, но вот события к ним привязать динамически нельзя!

Выход только один: использовать режим Design. А именно - создавать форму, добавлять к ней контролы, добавлять в код формы события, а потом уже запускать форму. При этом в настройках Excel должен быть разрешен доступ к коду.

Для экономии времени форму можно не создавать с нуля: создавать в Дизайнере, запихивать в нее код и контролы по максимуму (все, что не требует динамики), а затем экспортировать ее в проект и "измываться" над ней далее - добавляя, так же в режиме Дизайнера , контролы и код событий.

Выглядит это примерно так:

PHP код:
   ' Проверяем есть ли такая форма в проекте
    On Error Resume Next
    Set frm = ThisWorkbook.VBProject.VBComponents.Item("UserForm2")
    If Err.Number = 0 Then
        ' 
Если есть удаляем ее
        ThisWorkbook
.VBProject.VBComponents.Remove frm
    End 
If
    
On Error GoTo 0

    
' Экспортируем ее
    Set frm = ThisWorkbook.VBProject.VBComponents.Import(ThisWorkbook.Path & "\frm\UserForm2.frm")
    
    ' 
Добавляем кнопку
    Set cmb 
frm.Designer.Controls.Add("Forms.CommandButton.1")
    
With cmb
        
.Name "CommandButton1"
        
.Top 50
        
.Left 100
        
.Caption "Ok"
    
End With
    
    
' Событие к кнопке
    code = "Private Sub  CommandButton1_Click" & vbCr
    code = code & "msgbox ""Привет!""" & vbCr
    code = code & "end Sub" & vbCr
    
   ' 
Добавляем код в конец модуля
   With frm
.CodeModule
        
.InsertLines .CountOfLines 1code
    End With

    
' Показываем форму
    VBA.UserForms.Add(frm.Name).Show
    ' 
Удаляем форму
    ThisWorkbook
.VBProject.VBComponents.Remove frm 
Но есть проблемы. В частности при добавлении ComboBox я не могу добавить список выбора:

PHP код:
   Set cmb frm.Designer.Controls.Add("Forms.ComboBox.1")
        
With cmb
            
.Top 10
            
.Left 10
            
.Width 100
            
            
' Не работает
            arr(0) = "1"
            arr(1) = "2"
            arr(2) = "3"
            .List() = arr
            
            ' 
И так не работает
            
.AddItem "1"
            
.AddItem "2"
            
.AddItem "3"
        
End With 
В чем проблема - понимаю, List и AddItem работают в режиме Runtime. Т.е. нужно добавить список выбора в Дизайнере. А вот как это сделать я не нашел. (Если кто знает - подскажите!) Вместо этого решил генерить код, который будет добавлять список, ну а вызов этого кода вставить в инициализацию форму.
vinvin вне форума Ответить с цитированием
Старый 13.01.2012, 14:32   #5
Казанский
Старожил
 
Аватар для Казанский
 
Регистрация: 31.12.2010
Сообщений: 2,133
По умолчанию

Это вырезание гландов через ж... в чистом виде
Почитайте про модуль класса.
exceleved@yandex.ru Яндекс.Деньги: 410011500007619
Казанский вне форума Ответить с цитированием
Старый 13.01.2012, 14:50   #6
vinvin
Новичок
Джуниор
 
Регистрация: 11.01.2012
Сообщений: 7
По умолчанию

Вот весь код - может кому-нибудь пригодиться:

PHP код:
Sub aaa()
    
Dim arr(3)
    
    
' Проверяем есть ли такая форма в проекте
    On Error Resume Next
    Set frm = ThisWorkbook.VBProject.VBComponents.Item("UserForm2")
    If Err.Number = 0 Then
        ' 
Если есть удаляем ее
        ThisWorkbook
.VBProject.VBComponents.Remove frm
    End 
If
    
On Error GoTo 0

    
' Экспортируем ее
    Set frm = ThisWorkbook.VBProject.VBComponents.Import(ThisWorkbook.Path & "\frm\UserForm2.frm")
    
    ' 
Добавляем кнопку
    Set btn 
frm.Designer.Controls.Add("Forms.CommandButton.1")
    
With btn
        
.Name "CommandButton1"
        
.Top 50
        
.Left 100
        
.Caption "Ok"
    
End With
    
    
' Событие к кнопке
    code = "Private Sub CommandButton1_Click()" & vbCr
    code = code & "For i=0 to Controls.Count-1" & vbCr
    code = code & " Debug.Print Controls(i).Name" & vbCr
    code = code & "Next" & vbCr
    code = code & "end Sub" & vbCr
        
    Set cmb = frm.Designer.Controls.Add("Forms.ComboBox.1")
        With cmb
            .Name = "ComboBox1"
            .Top = 10
            .Left = 10
            .Width = 100
        End With
        
    ' 
Добавляем  список
    code 
code "Private Sub  AddItem1()" vbCr
    code 
code "Dim obj as Object " vbCr
    code 
code "Set obj = Controls(""ComboBox1"")" vbCr
    code 
code "With obj" vbCr
    code 
code ".AddItem ""1""" vbCr
    code 
code ".AddItem ""2""" vbCr
    code 
code ".AddItem ""3""" vbCr
    code 
code "end With" vbCr
    code 
code "end Sub" vbCr
    
    
' Делаем вызов процедуры добавления формы в инициализацию формы
    code = code & "Private Sub UserForm_Initialize()" & vbCr
    code = code & "Call AddItem1" & vbCr
    code = code & "end Sub" & vbCr
    
    With frm.CodeModule
        .InsertLines .CountOfLines + 1, code
    End With
    
    
    VBA.UserForms.Add(frm.Name).Show
    ThisWorkbook.VBProject.VBComponents.Remove frm
    
End Sub 
vinvin вне форума Ответить с цитированием
Старый 13.01.2012, 14:55   #7
vinvin
Новичок
Джуниор
 
Регистрация: 11.01.2012
Сообщений: 7
По умолчанию

Спасибо за подсказку - почитаю. Хотя классы использовал, но как сюда привязать не знаю. Если подскажите что-то конкретнее буду очень признателен.
vinvin вне форума Ответить с цитированием
Старый 13.01.2012, 15:46   #8
vinvin
Новичок
Джуниор
 
Регистрация: 11.01.2012
Сообщений: 7
По умолчанию

Да, забыл сказать. А то с первого взгляда действительно кажется через ж...
Дело в том, что форма сложная. На нее добавляются контролы, к которым нужно привязывать события. А это можно сделать ИМХО только через Дизайнер.

Модуль класса не работает с таким кодом как, например:

Public WithEvents Chk As CheckBox

Так автоматизация событий в CheckBox не предусмотрена.

А мне нужно привязать код к CheckBox.
ComboBox, не требуют от меня событий, но они тоже создаются автоматически. Их можно создать динамически при инициализации формы.
Но получается, что часть элементов я в программе буду создавать через дизайнер, часть в RunTime. Вот это и будет бардак.
Так что лучше через ж... , но единообразно.

Последний раз редактировалось vinvin; 13.01.2012 в 15:47. Причина: некорректное слово
vinvin вне форума Ответить с цитированием
Старый 14.01.2012, 00:45   #9
Казанский
Старожил
 
Аватар для Казанский
 
Регистрация: 31.12.2010
Сообщений: 2,133
По умолчанию

Модуль класса не работает с таким кодом как, например:

Public WithEvents Chk As CheckBox

Однако, смотрите Нажимайте кнопку и кликайте чекбоксы.
Вложения
Тип файла: zip 183299.zip (13.0 Кб, 24 просмотров)
exceleved@yandex.ru Яндекс.Деньги: 410011500007619
Казанский вне форума Ответить с цитированием
Старый 14.01.2012, 00:51   #10
Казанский
Старожил
 
Аватар для Казанский
 
Регистрация: 31.12.2010
Сообщений: 2,133
По умолчанию

Можно даже обойтись без переменных кроме коллекции. Модуль формы:
Код:
Dim cl As New Collection

Private Sub CommandButton1_Click()

cl.Add New Class1           'создать новый экземпляр класса
Set cl(cl.Count).Chk = Me.Controls.Add("Forms.CheckBox.1")
With cl(cl.Count).Chk
    .Caption = "Чекбокс " & cl.Count
    .Top = cl.Count * 20
    .Left = 10
End With

End Sub
exceleved@yandex.ru Яндекс.Деньги: 410011500007619
Казанский вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Runtime Error ultrasfan Общие вопросы C/C++ 3 12.10.2010 16:16
Runtime Error RoS Qt и кроссплатформенное программирование С/С++ 7 06.09.2010 16:44
В массиве из п элементов много совпадающих элементов. Найти количество различных элементов Strax Фриланс 11 12.06.2010 20:13
Runtime runtime = Runtime.getRuntime(); Pti44ka Общие вопросы по Java, Java SE, Kotlin 1 22.11.2009 10:45
RunTime Error713 (VB) vio Помощь студентам 2 12.12.2008 20:45