{quote}{login=The_Prist}{date=07.10.2009 04:57}{thema=Re: }{post}{quote}{login=Kindness}{date=07.10.2009 04:48}{thema=}{post}Спасибо. Читал. Если бы понял, не просил бы о помощи... Если знаете, помогите, плиз... Очень надо...{/post}{/quote}Как бы сказать, чтоб не обидеть. Если Вы читали и не поняли, то стоит отказаться на время от использования классов. Пока не придет озарение. Поищите примеры использования классов и анализируйте.{/post}{/quote}
The_Prist, спасибо. Вы помните, я давно спрашивал про классы. Тогда Вы мне дали совет изучить материалы. Я ему последовал. Я Вам благодарен, мои знания значительно пополнились. К сожалению задача осталась нерешенной... Бросить ее нельзя. Забыть тоже. Может Вы сможете дать мне хоть маленькую подсказку? И я надеюсь меня озарит...
Поскольку разговор общий, то и совет общий. На пальцах, так_сказать. Вы некоторым кодом объединили некие объекты в класс. Теперь в модуле класса создаете событие клик Private Sub ИмяКласса_Click() В нем код обработки. Клик на любом объекте тогда вызывает этот код. Еще совет. Скачайте любой пример с классами и измените под себя. Пока будете менять разберетесь как оно работает.
Спасибо. Всегда стараюсь выкладывать итоговое решение. Выложу файл, когда он будет готов. Вообще задача не из простых, и ответов по подобным задачам крайне мало... Плюс столкнулся с тем, что люди часто пишут код, а он не работает. Например я рассматривал возможность создания модуля с "Sub имя_Click" для созданного в коде объекта, а мой VBA почему-то не воспринимает слово CodeModule... Разные штуки случаются...
{quote}{login=Лузер™}{date=07.10.2009 05:16}{thema=}{post}Поскольку разговор общий, то и совет общий. На пальцах, так_сказать. Вы некоторым кодом объединили некие объекты в класс. Теперь в модуле класса создаете событие клик Private Sub ИмяКласса_Click() В нем код обработки. Клик на любом объекте тогда вызывает этот код. Еще совет. Скачайте любой пример с классами и измените под себя. Пока будете менять разберетесь как оно работает.{/post}{/quote}
Наверное я неправильно объектв класс загоняю... именно в этом ошибка. Вот код:
Public myListbox() As New myLB 'наименование классмодуля
Sub SozdanieListboxov1() k = 0: KS = 6 For n = 1 To KS k = k + 1 T = T + 78 Set NewListbox = UserForm1.Frame1.Controls.Add(bstrProgID:="Forms.ListBox.1")
With NewListbox .Name = "myListBox" .Left = 210 .Top = T .Height = 60 .Width = 585 .Enabled = True .TextAlign = 1 .Locked = False .AddItem "pppppppp" .AddItem "jjjjjjjj" End With 'переопределяем ReDim Preserve myListbox(1 To k) 'загоняем созданный объект в класс Set myListbox(k) = New myLB
Next n
UserForm1.Frame1.ScrollHeight = T k = 0: KS = 0: T = 0 End Sub
Извините, файл пока выложить не могу, его надо почистить...
Set myListbox(k) = NewListbox Либо сразу: Sub SozdanieListboxov1() k = 0: KS = 6 For n = 1 To KS k = k + 1 T = T + 78 ReDim Preserve myListbox(1 To k) Set myListbox(k) = UserForm1.Frame1.Controls.Add(bstrProgID:="Forms.ListBox.1") With myListbox(k)
И, наверное, имя стоит поменять. Что они все как близнецы... .Name = "myListBox" & k Или что-то в этом роде. Я не пробовал, но думаю одноименные объекты не допускаются.
Kindness, если е секрет, что за фичу вы творите. Как это должно выглядеть? Почему спрашиваю - управлять вновь созданными Листбоксами занчительно сложнее - привязки, размеры, месторасположение, связи все это надо описывать. Гораздо проще на мой взгляд использовать свойство .Visible. То есть все ListBox-ы, которые будут участвовать в расчетах на момент описания кода вы можете расставить на просторной UserForm, а по завершении работы наложить один на другой, включая отображение нужных по стандартным событиям. Не пожалейте трафика и скачайте http://www.planetaexcel.ru/docs/forum_upload/post_64038.rar. Здесь пример управления элементами, наложенными друг на друга в несколько слоев. Думаю Вам этот опыт пригодится. Ну а классы могут подождать, потому как осваивать VBA, начиная с классов, это все равно что учиться водить на формуле 1. Не успеете получить удовольствие, как пропадет охота этим заниматься.
VovaK, нет там ничего сложного. Есть нюансы, но не сложнее остального кода в VBA. Чем лучше класс: - Для обработки события нужно написать один раз один код. Если Вы создадите Х элементов управления без класса, Вам нужно будет Х процедур, как минимум. Для двух событий Х*2 процедур, а в классе всего две. - Если Вы не знаете заранее сколько нужно будет элементов управления, тогда без класса вообще труба.
Потом, Kindness создает листбоксы не друг на друге, а друг под другом. Может ему нужно все 6 одновременно видеть. И не похоже, чтобы Kindness только начинал осваивать VBA.
Лузер, спасибо большое, от Вас такие слова для меня огромная награда за труды. Скажу честно, мозг мой потемки. Почему увлекся программированием не знаю, но затянуло. Образование у меня экономическое, сейчас учусь на юриста. Много технических моментов для меня загадка, но интересно безумно. С VBA борюсь уже года два, но считаю что двигаюсь вперед очень медленно. На курсы не ходил (времени свободного недостаточно), пытаюсь сам, очень часто нахожу решение здесь на сайте, или обращаюсь за помощью. После подсказки (подсказок) как правило все становится ясно и начинаю рулить новыми возможностями с легкость. Владимир, действительно, рисовать заранее неопределенное количество объектов не представляется возможным. Это просто, но не всегда решает поставленную задачу. Вы же не можете не использовать циклы? Здесь что-то похожее...
Сейчас буду разбирать советы Лузера. Результат объявлю по завершении процесса.
{quote}{login=Лузер™}{date=07.10.2009 07:35}{thema=}{post}Да. Не так. Либо:
Set myListbox(k) = NewListbox Либо сразу: Sub SozdanieListboxov1() k = 0: KS = 6 For n = 1 To KS k = k + 1 T = T + 78 ReDim Preserve myListbox(1 To k) Set myListbox(k) = UserForm1.Frame1.Controls.Add(bstrProgID:="Forms.ListBox.1") With myListbox(k)
...{/post}{/quote}
В первом случае, выдает ошибку Type mismatch Во втором случае не распознает методы объекта как методы листбокса. То есть видимо программа не понимает, что создаваемый класс - это листбоксы. Понимаю, что чисто теоретически можно определить для класса каждый из методов. Но интуитивно делать этого не желаю, так как задача точно решается намного проще...
Маленький кусочек забыл, но пока Вы не выложили Public WithEvents myLBox As MSForms.ListBox - его и написать было нельзя.
значит так Либо:
Set myListbox(k).myLBox = NewListbox
Либо сразу:
Sub SozdanieListboxov1() k = 0: KS = 6 For n = 1 To KS k = k + 1 T = T + 78 ReDim Preserve myListbox(1 To k) Set myListbox(k).myLBox = UserForm1.Frame1.Controls.Add(bstrProgID:="Forms.ListBox.1") With myListbox(k).myLBox
Возникла еще одна загвоздка с созданным классом листбоксов.
Как в последствии при работе с ними на них ссылаться?
Смысл такой - кликаю листбокс - в текстбоксе ниже появляется значение кликнутой строки - это я сделал через событие класса. При изменении текста текстбокса - меняется и значение строки листбокса - вот с этим труба. Как только не пробовал, не получается. Как правильно писать ссылку на него?
Одна из попыток была такова: Userform1.Frame1.Activecontrol.Text = Userform1.Textbox1.Text
Я пришел к необходимости создания класса, когда столкнулся со следующей задачей: заранее неизвестно количество элементов, которые будут созданы друг под другом. Так как количество неизвестно, их заранее нельзя нарисовать на форме. Можно в коде. Нарисовал. А дальше возникла проблема - как назначить им событие, т.е. как прописать что будет, когда пользователь на них кликает? Получается, что только через определение их в отдельном классе... Кликаешь на каждый, а действие одно... Вот так вот. А теперь вопрос - как с ними дальше работать, если событие исходит не от них, но в коде к этому событию необходимо произвести с одним из элементов класса определенное действие...
Я когда создам конечный продукт, выложу его здесь.
{quote}{login=The_Prist}{date=08.10.2009 03:02}{thema=}{post}Наверное, как-то так Private Sub TextBox1_Change() Me.Controls("myListBox" & Mid(Me.ActiveControl.Name, 8)).List(0) = Me.ActiveControl.Value End Sub Но если учесть, что все равно все события TextBox-ов прописывать и имена их известны, то можно и так: Private Sub TextBox1_Change() Me.Controls("myListBox" & 1).List(0) = TextBox1 End Sub{/post}{/quote}
Второй вариант работает. А вот первый выдает ошибку: Does not suppot this property or method
Попробовал так Me.Controls("myListBox" & Mid(Me.ActiveControl.Name, 8)).List(0)=Textbox1 Пишет, "не могу найти такой объект". Текстбокс всегда один. Активные листбоксы разные. Расшифруйте, плиз,Mid(Me.ActiveControl.Name, 8) - и что значит "8"?
{quote}{login=The_Prist}{date=08.10.2009 03:19}{thema=}{post}8 - это кол-во буковок в имени объекта TextBox + 1. Это чтоб выцепить номер TextBox-а. А ошибку выдает, скоре всего потому, что у Вас Textbox-ы расположены на объекте Frame, который является, так сказать, доминирующим и соответственно активным при обращении к любому TextBox-у(и не только) на нем. Кстати с объектами MultiPage такая же история. Чтобы это проверить можете вставить в код строку dim sControlName as string sControlName = Me.ActiveControl.Name И посмотрите, какой объект форма считает активным.{/post}{/quote}
Про Frame понял, действительно это так. Написал вот так: Me.Controls("myLBoxes" & Mid(Userform1.Frame1.ActiveControl.Name, 9)).List(0) = Me.ActiveControl.Value Все равно ругается на метод... (myLBoxes - я их просто переименовал ранее...).
{quote}{login=Kindness}{date=08.10.2009 03:24}{thema=Re: }{post}{quote}{login=The_Prist}{date=08.10.2009 03:19}{thema=}{post}8 - это кол-во буковок в имени объекта TextBox + 1. Это чтоб выцепить номер TextBox-а. А ошибку выдает, скоре всего потому, что у Вас Textbox-ы расположены на объекте Frame, который является, так сказать, доминирующим и соответственно активным при обращении к любому TextBox-у(и не только) на нем. Кстати с объектами MultiPage такая же история. Чтобы это проверить можете вставить в код строку dim sControlName as string sControlName = Me.ActiveControl.Name И посмотрите, какой объект форма считает активным.{/post}{/quote}
Про Frame понял, действительно это так. Написал вот так: Me.Controls("myLBoxes" & Mid(Userform1.Frame1.ActiveControl.Name, 9)).List(0) = Me.ActiveControl.Value Все равно ругается на метод... (myLBoxes - я их просто переименовал ранее...).{/post}{/quote}
Работает вот так, но все время на первой строке листбокса(а как сослась на выделенную?): Me.Controls("myLBoxes" & Mid(Userform1.Frame1.ActiveControl.Name, 9)).List(0) = TextBox1
{quote}{login=Марчук}{date=08.10.2009 03:42}{thema=}{post}а параметр не передать ?
типа так :
.... mac1 data.value ....
sub mac1 (data as Date) .... peremennaya = data .... end sub{/post}{/quote}
Попробовал так: e.Controls("myLBoxes" & Mid(Userform1.Frame1.ActiveControl.Name, 9)).ListIndex = n
Me.Controls("myLBoxes" & Mid(Userform1.Frame1.ActiveControl.Name, 9)).List(n) = TextBox1 Не вышло... так что врядли поможет (я так понимаю, то, что Вы предлагаете и мой вариант - одно и тоже, да?)