Страницы: 1
RSS
Событие на листе для переменной OLEObject
 
Всем здравствуйте,  
 
По событию SelectionChange cоздаю на листе элемент управления ComboBox. После завершения использования ComboBox необходимо удалить его с листа. Событие листа Change не подходит, так как  ComboBox связан с ячейкой и изменение листа начинается с первой буквы. Нужно еще событие по которому можно удалить ComboBox. Для этого попытался присвоить ComboBox переменной и создать события для нее:  
 
Public WithEvents oleObj As OLEObject  
Private Sub oleObj_LostFocus()  
   oleObj.Delete  
End Sub  
 
Но VBA ругается Выдавая ошибку 459 "Object or class does not support the set of events"  
Где-то вычитал, что если объект на листе один можно воспользоваться зарезервированным именем переменной newCtl, но тоже не работает  
 
Private Sub newCtl_LostFocus()  
Me.OLEObjects("newCtl").Delete  
End Sub  
 
Вопрос есть ли возможность создать события для переменной объекта OLE.  
 
Спасибо,  
 
Владимир.
 
а если объект 1, то может просто написать в модуле листа для него обработку?  
вот так, например:
Живи и дай жить..
 
> По событию SelectionChange cоздаю на листе элемент управления ComboBox.  
> Нужно еще событие по которому можно удалить ComboBox.  
 
Я в таких случаях поступаю проще: не создаю\удаляю элемент управления, а изменяю размеры и положение ЗАРАНЕЕ созданного элемента управления  
(когда комбобокс не нужен, я уменьшаю его размеры до минимума, и помещаю его в левый верхний угол листа)  
 
Пример есть здесь: http://www.programmersforum.ru/showpost.php?p=274701&postcount=2
 
Спасибо ребята,  
 
Игорь, как вариант подумаю, но с удалением код проще. Там привязка к ячейкам уже при создании, а тут его бедного нужно будет постоянно переназначать на Target.  
Но мысль интересная, будет время попробую написать...
 
{quote}{login=VovaK}{date=19.10.2009 01:19}{thema=}{post}Спасибо ребята,  
 
Там привязка к ячейкам уже при создании, а тут его бедного нужно будет постоянно переназначать на Target.{/post}{/quote}  
Не надо ничего переназначать...  
 
Ключевая фраза - "По событию SelectionChange cоздаю на листе элемент управления ComboBox"  
 
Зачем какие-то TARGET-ы...  
 
Назначаем этому комбобоксу макрос.  
Макрос определяет выделенный диапазон через Selection  
Как-то так. Не знаю, что именно требуется, но в любом случае это будет проще, чем Public WithEvents oleObj As OLEObject  
 
Впрочем, дело Ваше...
 
Полностью согласен с Игорем (EF).  
 
Динамическое добавление контролов на лист или на форму – это прямые утечки памяти.  
С каждым добавлением/удалением, например, комбобокса Excel отъедает все больше и больше своего буфера памяти (проверьте сами), что может привести к сбою и/или торможению Excel.  
 
Кроме того, после добавления или удаления контрола все глобальные переменные разинициализируются, что редко учитывается.  
Пример для проверки этого малоизвестного факта.  
 
Dim GlobalVariable As Long  
 
' Сначала запустить этот макрос добавления комбобокса  
Sub AddControl()  
 GlobalVariable = 1  
 Test  ' выдаст:  1 True  
 ActiveSheet.OLEObjects.Add _  
   ClassType:="Forms.ComboBox.1", _  
   Link:=False, DisplayAsIcon:=False, Left:=0, Top:=0, Width:=180, Height:=14  
End Sub  
 
' Затем запустить этот макрос для проверки, что глобальная переменная обнулилась  
Sub Test()  
 ' Если запустить этот макрос после AddControl  
 ' или после DelControl (с удалением контрола),  
 ' то выдаст: 0 False  
 Debug.Print GlobalVariable, GlobalVariable = 1  
End Sub  
 
Sub Del()  
 ' Удаление контрола  
 On Error Resume Next  
 ActiveSheet.OLEObjects(1).Delete  
End Sub
 
> Кроме того, после добавления или удаления контрола все глобальные переменные разинициализируются...  
 
Здравствуйте, Владимир.  
Очень интересный факт Вы сообщили... никогда бы не подумал, что такое может происходить, иначе как в случае вылета кода с ошибкой...  
 
А есть ещё какие-нибудь случаи, когда глобальные переменные теряют свои значения?  
Это касается любых глобальных переменных (уровня листа, книги, проекта)?
 
да, точно. Мало того, иксель отказывается входить в пошаговую отладку, пока не "перезагрузится" проект(т.е. не отработает полностью макрос)
Живи и дай жить..
 
Ребята соглашусь, что память начинает расти (с 26512 до ~26980), но потом стабилизируется  не доходя до 27000К, вот пример http://www.planetaexcel.ru/docs/forum_upload/post_69682.xls - так это не критично для таких задачек. А из плюсов - нет потери фокуса, и просто реализовать связь с текущей ячейкой (из-за потери фокуса .LinkedCell = Target.Address не работает). Глобальные переменные - не ощутил - проверьте на календаре ("B25").  
 
Единственный и ОЧЕНЬ минус - отсутствие отладки, но это характерно для всех OLE объектов.
 
{quote}{login=EducatedFool}{date=20.10.2009 06:09}{thema=}{post}...  
А есть ещё какие-нибудь случаи, когда глобальные переменные теряют свои значения?  
Это касается любых глобальных переменных (уровня листа, книги, проекта)?{/post}{/quote}  
Пропустил вопрос - извиняюсь. К счастью, другие случаи мне не попадались :-)  
 
Значения теряют все статические переменные, все переменные, объявленные как Public на всех уровнях проекта, и все объявленные посредством Dim на уровне всех модулей. Другими словами,  вообще все переменные проекта теряют свои значения, потому что остаются еще только локальные, для которых потеря "памяти" по выходу из процедуры/функции является нормой.  
Но с глобальными это происходит только после того, как код отработает. То есть, если в конце процедуры AddControl() добавить Test(), то видно, что переменная GlobalVariable пока еще не потеряла своё значение. Но после завершения процедуры у неё наступает амнезия.  
 
В подобных случаях нужно либо избегать глобальных и статических переменных, либо временно запоминать их значения в именах книги или ячейках до удаления/добавления контролов, а затем глобально восстанавливать эти глобальные переменные, например, дописав в конце AddControl() строку:  
Application.OnTime Now, "RecoveryGlobalVars"  
где "RecoveryGlobalVars" - имя процедуры восстановления значений переменных их имён или ячеек.  
 
По поводу утечек памяти при каждом добавлении ActiveX (OLEObject) контрола на лист Excel была соответствующая информация  от MS: на каждый контрол требуется не менее 20 байт ограниченного буфера памяти Excel. Этот буфер становится фрагментированным и со временем может просто не хватить непрерывной области памяти для каких-то других действий Excel. И даже закрытие книги не освобождает эту память – помогает только закрытие Excel. Нигде мне не попадалась информация, что проблема была окончательно устранена в последующих версиях, была лишь информацию о временных хот-фиксах. Впрочем, с учетом того, что менеджер встроенного буфера памяти Excel модернизировался (особенно в Excel 2003), а сам буфер увеличивался от версии к версии,  вероятность сбоя из-за такого рода утечек памяти уменьшилась.
 
Спасибо Владимир. Очень полезная информация.
Страницы: 1
Читают тему
Наверх