Вопрос по работе с коллекцией
Public Property Get Item(vntIndexKey As Variant) As ClsFixControls
'used when referencing an element in the collection
'vntIndexKey contains either the Index or Key to the collection,
'this is why it is declared as a Variant
'Syntax: Set foo = x.Item(xyz) or Set foo = x.Item(5)
On Error GoTo ErrHnd
If mCol(vntIndexKey) Is Empty Then
Item = 28121978
Exit Property
End If
If IsNull(mCol(vntIndexKey)) Then
Item = 28121978
Exit Property
End If
Set Item = mCol(vntIndexKey)
Exit Property
ErrHnd:
Item = 28121978
End Property
Идея была следующей: Если есть в коллекции, которая является родительской для класса с описанием определённых фиксированных контролов, контрол, то всё окей, инате, проперти должно вернуть некие данные, по которым я определю отсутствие контрола. Естественно, эта штука не раьботает, так как возвращаемый объект должен являться классом. Кто посоветует, как это переделать? Поменять тип возвращаемых данных нельзя, сразу говорю, как логически, так и в соответствии с алгоритмом.
Не помогает даже вариант:
Public Property Get Item(vntIndexKey As Variant) As ClsFixControls
'used when referencing an element in the collection
'vntIndexKey contains either the Index or Key to the collection,
'this is why it is declared as a Variant
'Syntax: Set foo = x.Item(xyz) or Set foo = x.Item(5)
On Error GoTo ErrHnd
Set Item = mCol(vntIndexKey)
Exit Property
ErrHnd:
mCol.Add 28121978, "28121978_"
vntIndexKey = "28121978_"
Set Item = mCol(vntIndexKey)
mCol.Remove "28121978_"
End Property
Но, опять-таки, это, по-моему, кривой способ. Если у кого есть идеи, буду очень благодарен за совет.:)
Народ, в коде коллекции есть следующее:
Public Property Get Item(vntIndexKey As Variant) As ClsFixControls
'used when referencing an element in the collection
'vntIndexKey contains either the Index or Key to the collection,
'this is why it is declared as a Variant
'Syntax: Set foo = x.Item(xyz) or Set foo = x.Item(5)
On Error GoTo ErrHnd
If mCol(vntIndexKey) Is Empty Then
Item = 28121978
Exit Property
End If
If IsNull(mCol(vntIndexKey)) Then
Item = 28121978
Exit Property
End If
Set Item = mCol(vntIndexKey)
Exit Property
ErrHnd:
Item = 28121978
End Property
...а может проверить is Nothing...?
...а может проверить is Nothing...?
Нет, увы...:{ Пробовал проверку - не помогает.:{ P( Потом, в принципе, проверка-то и не нужна. Если возникает ошибка, просто переходим в область обработки ошибок... А вот как Item присвоить... Не получается даже, когда я пытаюсь внести в коллекцию "нулевой" элемент, присвоить его (на этом валится) и удалить потом. В принципе, можно и в месте обращения к коллекции делать проверку на ошибку, но это очень грубо, неудобно, да и вообще неправильно. Хочется, чтобы при обращении к элементу коллекции автоматом обходилась именно одна ошибка, т.е. отсутствие айтема, чтобы я мог об этом как-то узнать, но без возникновения в стеке ошибок ещё одного элемента, так сказать...
Вот такие пироги...
Пока я нашёл только одно решение (с внесением контрольного значения при заполнении коллекции. Т.е. если в коллекции нет элемента, то в области обработки ошибок присваиваем это контрольное значение). Самое интересное, что я ВИДЕЛ на предыдущейработе пример кода, решающего эту проблему, но я его просмотрел мимолётом и уже забыл алгоритм.:{
Нет, увы...:{ Пробовал проверку - не помогает.:{ P(
А при обращении к несуществующему эл-ту ошибку выдает???
на это не ругается???
...если нету этого эл-та???
А при обращении к несуществующему эл-ту ошибку выдает???
Естественно... И, в принципе, слава Богу, тотому как на этой внутренней ошибке коллекции по её номеру я могу ловить обращение к "левому" элементу. Токмо как его обработать... :{ Пока обрабатываю, присваивая возвращаемому объекту занчение элемента контрольного, который прописываю в момент заполнения коллекции, но как вот без этого обойтись?
Set Item = mCol(vntIndexKey)
на это не ругается???
...если нету этого эл-та???
Ругается только тогда, когда пытаюсь "подцепить" несуществуцющий элемент.
Самый прикол. Код области обработки ошибок:
mCol.Add 28121978, "28121978_"
Set Item = mCol("28121978_")
mCol.Remove("28121978_")
валится на Set Item = mCol("28121978_") (только на этом. Добавление и удаление работают!).
Вот такая беда:{
...потом, если последовательно посты почитать, создается впечатление, что до меня доходит раза с двадцатого...:D
Ругается только тогда, когда пытаюсь "подцепить" несуществуцющий элемент.
Самый прикол. Код области обработки ошибок:
mCol.Add 28121978, "28121978_"
Set Item = mCol("28121978_")
mCol.Remove("28121978_")
валится на Set Item = mCol("28121978_") (только на этом. Добавление и удаление работают!).
Вот такая беда:{
А у тебя коллекция чего???
mCol.Add 28121978, "28121978_"
...или ты число туда для примера добавляешь???
попробуй без Set...
...просто Item = mCol("28121978_")
Ругается только тогда, когда пытаюсь "подцепить" несуществуцющий элемент.
Самый прикол. Код области обработки ошибок:
mCol.Add 28121978, "28121978_"
Set Item = mCol("28121978_")
mCol.Remove("28121978_")
валится на Set Item = mCol("28121978_") (только на этом. Добавление и удаление работают!).
Вот такая беда:{
Проверил щас твой код...
...с Set - Tipe mismatch
...без Set усе у порядку:)
Проверил щас твой код...
...с Set - Tipe mismatch
...без Set усе у порядку:)
Да нет, у меня и без Set валилось. Видимо, ты тестировал не коллекцию, т.е. не проперти коллекции, а оторваннное проперти типа Variant.
Спасибо тебе огромное, что тоже озадачился:) .
Но, блин, без Set у меня тоже не прёт....:{
Да нет, у меня и без Set валилось. Видимо, ты тестировал не коллекцию, т.е. не проперти коллекции, а оторваннное проперти типа Variant.
Спасибо тебе огромное, что тоже озадачился:) .
Но, блин, без Set у меня тоже не прёт....:{
Так что тебе VB говорит на:
Set Item = mCol("28121978_")?????
А у тебя коллекция чего???
mCol.Add 28121978, "28121978_"
...или ты число туда для примера добавляешь???
попробуй без Set...
...просто Item = mCol("28121978_")
Давай я подробно распишу, что у меня и как:
1. На форму динамически подгружаются некие контролы, которые я сам написал. Вобщем, это один и тот же контрол, но он отображается по-разному и выполняет немного разные функции, в зависимости от типов, устанавливаемых для него извне.
2. В базе данных у меня есть таблица вопросов, которая по определённым прринципам связана с таблицей стран. В от в этой связке каждому вопросу проставляются определённые свойства, как то: способ отображения подей для ответа на вопрос (толи это текстовое поле, толи это комбобокс, толи это отдельный мой контрол типа кастирированнгого грида, толи это массив чекбоксов), флаг отображать этот вопрос в анкете для страны, или нет. ну и т.д.
3. Есть некие вопросы, связанные друг с другом. Например, если человек указывает организацию, которая его встречает в стране, то сразу же на автомате можно заполнить поле с указанием гостиницы, куда его поселят. У таких связанных вопросов есть определённые типы свойст втображения, несмотря на то, что они внешне могут выглядеть как угодно.
4. Когда я формирую анкету для нужной страны, у меня автоматически при подгрузке контрола с интересующими меня свойствами, его индекс заносится в коллекцию. дабы потом при необходимости не бегать по всем контролам, а "дергать" индекс из коллекции. Например, поле Принимающая сторона, в БД имеет флаг 11, а поле "Отель" имеет флаг 12. При подгрузке контролов, для которых стиль (свойство контрола) устанавливается в 11 и 12 в коллекцию записываются их индексы, а ключём ставлю, соответственно "11_" и "12_".
5. Затем, когда пользователь указывает принимающую сторону, из коллекции вытаскивается элемент с индексом "12_" и в контрол с индексом этого элемента пишется название отеля.
6. НО для некоторых стран, например, в анкете не надо указывать название отеля. Тогда элемента "12_" в коллекции не будет. Чтобы сделать единый алгоритм, я решил считать, что если при обращении к элементу коллекции с индексом "ХХ_" возвращается некое определённое число (у меня 28121978, так как это дала моего рождения, и контрола с таким индексом никак не может быть), значит, такого поля нет в данной анкете, иначе - см. выше.
И вот как раз на определении несуществующего поля я запнулся.
Сейчас я искуственно приписываю на стадии заполнения в коллекцию элемент 28121978 и ключём "28121978_". В случае ошибки, вытягиваю его. но хочется делать всё это "на лету", так сказать.
Так что тебе VB говорит на:
Set Item = mCol("28121978_")?????
Либо несоответствие типов, либо не найдено...
...Сейчас я искуственно приписываю на стадии заполнения в коллекцию элемент 28121978 и ключём "28121978_". В случае ошибки, вытягиваю его. но хочется делать всё это "на лету", так сказать.
Так у тебя коллекция контролов или их индексов???
Если таки я тебя правильно понял, и в коллекции содержатся индексы (Integer), то зачем ты их присваиваешь через "Set"???
Допустим:
mCol.add myControl.Index, myControl.Index _ & "_"
Set Item = mCol.Item(myControl.Index _ & "_")
'Type mismatch!!!!!!
'mCol.Item(myControl.Index _ & "_") - не объект, а число...
или mCol.Item(myControl.Index _ & "_") возвращает число, или я где то протупил и чего то не понял...
mCol.add Me.Controls.Item(myControl.Index), _
myControl.Index & "_"
Set Item = mCol.Item(myControl.Index _
& "_")
'Type mismatch!!!!!!
'mCol.Item(myControl.Index _
'& "_") - не объект, а число...
mCol.add Me.Controls.Item(myControl.Index), _
myControl.Index & "_"
Set Item = mCol.Item(myControl.Index _
& "_")
'Уже не Type mismatch!!!!!!
'mCol.Item(myControl.Index _
'& "_") - теперь объект, а не число...
Так у тебя коллекция контролов или их индексов???
Если таки я тебя правильно понял, и в коллекции содержатся индексы (Integer), то зачем ты их присваиваешь через "Set"???
Допустим:
mCol.add myControl.Index, myControl.Index _ & "_"
Set Item = mCol.Item(myControl.Index _ & "_")
'Type mismatch!!!!!!
'mCol.Item(myControl.Index _ & "_") - не объект, а число...
или mCol.Item(myControl.Index _ & "_") возвращает число, или я где то протупил и чего то не понял...
Да, в коллекции индексы. Вернее, коллекция содержит в себе класс по-моему, ContrlsInd, ну или что-то там такое (см. выше), который включает в себя индекс (лонг) и ключь (стринг),
Да, в коллекции индексы. Вернее, коллекция содержит в себе класс по-моему, ContrlsInd, ну или что-то там такое (см. выше), который включает в себя индекс (лонг) и ключь (стринг),
Что возвращает mCol("28121978_")?????
Что возвращает mCol("28121978_")?????
mhaturov имеет ввиду наверное вот что:
при добавлении в коллекцию ссылки на объект(а только ссылки можно в коллекцию сувать, никаких integer) в ачестве второго параметра можно указать буквенно-цифровой ключ, по которому потом и ссылаться через .Item(), иначе остается только индексы, но в совю очередь будут меняться при добавлении/удалении новых элеметов в коллекцию
а вот дальше, по сути проблемы, я не очень понял, то ли у mhaturov идет обращение к элементу коллекции, которого нет, и ему надо вернуть при этом определенный "тип".... причем так жестко все завязано, что ничего не поменяешь и от этого приходится плясать.... с другой стороны, если функция возвращает коллекцию (или элемент коллекции или... я так и не понял что именно), но вообщем если надо что это самое вернулось из коллекции, то пока его туда не положишь, оно от туда и не вылезет, так что - КОНЕЧНО же надо тогда вручную добавлять и конечно не само число, а ссылку на объект, т.е. тебе понадобится какая-то пустышка, добавляя которую в коллекцию ты укажешь свой любимый ключ 28121978
Что возвращает mCol("28121978_")?????
Нет элемента
mhaturov имеет ввиду наверное вот что:
при добавлении в коллекцию ссылки на объект(а только ссылки можно в коллекцию сувать, никаких integer) в ачестве второго параметра можно указать буквенно-цифровой ключ, по которому потом и ссылаться через .Item(), иначе остается только индексы, но в совю очередь будут меняться при добавлении/удалении новых элеметов в коллекцию
а вот дальше, по сути проблемы, я не очень понял, то ли у mhaturov идет обращение к элементу коллекции, которого нет, и ему надо вернуть при этом определенный "тип".... причем так жестко все завязано, что ничего не поменяешь и от этого приходится плясать.... с другой стороны, если функция возвращает коллекцию (или элемент коллекции или... я так и не понял что именно), но вообщем если надо что это самое вернулось из коллекции, то пока его туда не положишь, оно от туда и не вылезет, так что - КОНЕЧНО же надо тогда вручную добавлять и конечно не само число, а ссылку на объект, т.е. тебе понадобится какая-то пустышка, добавляя которую в коллекцию ты укажешь свой любимый ключ 28121978
Ну я сейчас примерно тоже самое и делаю. тоесть, зараее прописываю в коллекцию один дополнительный "пустой" элемент, который потом вытягиваю, если не находу элемент по ключу. А хочется делать это "на лету", заранее ничего не добавляя.
Структура примерно следующая:
Коллекция описаний контролов. Включает:
--
--
Класс описания контролов: ID контрола, Ключ
--
--
Где -- - разные классы и т.д. Нас интересует только класс описания контрола. Остальное я думаю вообще сейчас посносить.
Ну я сейчас примерно тоже самое и делаю. тоесть, зараее прописываю в коллекцию один дополнительный "пустой" элемент, который потом вытягиваю, если не находу элемент по ключу. А хочется делать это "на лету", заранее ничего не добавляя.
Ну так а что же ты хочешь вернуть когда не находишь элемент по ключу??? ... может, ты хочешь когда наступает это радостное событие быстренька добавить пустышку и ее вернуть что-ли?, но тут вроде проблем нет, ты же вроде и так спокойно добавляешь свою пустышку....
Ну так а что же ты хочешь вернуть когда не находишь элемент по ключу??? ... может, ты хочешь когда наступает это радостное событие быстренька добавить пустышку и ее вернуть что-ли?, но тут вроде проблем нет, ты же вроде и так спокойно добавляешь свою пустышку....
Блин, мы опять друг друга не поняли.
Я отлично понимаю, что, если в коллекции нет элемента, то его никак и не вытянешь оттудова. НО у меня была следующая идея:
1. Если элемент не найден в коллекции, возвращать вместо него какое-либо фиксированное значение.
2. Сделать я это хотел следующим образом:
On Error Goto ErrHnd
В случае ошибки перейти в область обработки ошибок
Set Item = mCol(vntIndex)
Exit Property
ErrHnd:
Это как раз код, который работает, если есть элемент в коллекции
В области обработчика ошибок я пишу:
ErrHnd:
mCol.Add 28121978, "28121978_"
Тоесть, искуственно добавляю элемент в коллекцию
Затем
Set Item = mCol("28121978_")
(Изначально пытался обойтись Set Item = 28121978, но быстро понял, что туплю)
После этого удаляю элемент из коллекции
mCol.Remove "28121978_"
End Property
Так вот, на Set Item = mCol("28121978_") код "затыкался", выдавая, по моему, несоответствие типов, или "не найден элемент в коллекции".
Красивый вариант не прокатил :{ ...
Вобщем, сейчас делаю так, как описал выше... Не красиво, но работает P( . Пытаюсь найти красивое решение, но пока обламываюсь...
Set Item=Nothing не покатит???
Я об этом думал, но тогда на "вызывающей" стороне, т.е. там, откуда обращаюсь к коллекции, нужно писать дополнительный обработчик этого варианта, что даже менее удобно. чем тот вариант, который я реализовал.:{ Поэтому это я даже и не стал пробовать...
или долго будет?
А что, если реально создать какой-нибудь Лабел, обработать что тебе надо, а в конце удалить???
или долго будет?
Если ты имеешь в виду контрол, то это нереально, а вот создание элемента "на лету", это то, что я пытался сделать... Увы... Мой мозг для этого слаб...:{
Блин, мы опять друг друга не поняли.
Я отлично понимаю, что, если в коллекции нет элемента, то его никак и не вытянешь оттудова. НО у меня была следующая идея:
1. Если элемент не найден в коллекции, возвращать вместо него какое-либо фиксированное значение.
ну так и что же твоя функция должна возвращать, какой тип данных? вот что меня интересует, потому как от этого и нужно плясать
а то что я пока вижу, так это то, что какой-то код, который добавляет в коллекцию какое-то значение (кстати, как ты это делаешь, как у тебя обычное число залезает в коллекцию?), потом его пытаются вернуть и еще тут же удалить из коллекции - это что, попытку вернуть битую ссылку, ссылку на ничто...
ну так и что же твоя функция должна возвращать, какой тип данных? вот что меня интересует, потому как от этого и нужно плясать
а то что я пока вижу, так это то, что какой-то код, который добавляет в коллекцию какое-то значение (кстати, как ты это делаешь, как у тебя обычное число залезает в коллекцию?), потом его пытаются вернуть и еще тут же удалить из коллекции - это что, попытку вернуть битую ссылку, ссылку на ничто...
Да, именно нужно вернуть ссылку ниначто, но с известным значением, так сказать, а уж в коде. вызывающем это проперти, я его обработаю.
Теперь по поводу типов.
Само проперти имеет тип ClsControls, ну, короче, ссылка на объект класса описания контролов (я создавал это ради большей скорости в Class Bilder'е). А вот класс имеет всего 1 проперти IDContril типя Long. Вот в случае, если нет в коллекции элемента с ключём ХХ_, возвращалось число, заранее известное (28121978 ).
Вобщем, вот полные коды и класса, и коллекции:
Класс:
'local variable(s) to hold property value(s)
Private mvarIDContril As Long 'local copy
Public Property Let IDContril(ByVal vData As Long)
'used when assigning a value to the property, on the left side of an assignment.
'Syntax: X.IDContril = 5
mvarIDContril = vData
End Property
Public Property Get IDContril() As Long
'used when retrieving value of a property, on the right side of an assignment.
'Syntax: Debug.Print X.IDContril
IDContril = mvarIDContril
End Property
Коллекция:
'local variable to hold collection
Private mCol As Collection
Public Function Add(IDContril As Long, Optional sKey As String) As ClsFixControls
'create a new object
Dim objNewMember As ClsFixControls
Set objNewMember = New ClsFixControls
'set the properties passed into the method
objNewMember.IDContril = IDContril
If Len(sKey) = 0 Then
mCol.Add objNewMember
Else
mCol.Add objNewMember, sKey
End If
'return the object created
Set Add = objNewMember
Set objNewMember = Nothing
End Function
Public Property Get Item(vntIndexKey As Variant) As ClsFixControls
'used when referencing an element in the collection
'vntIndexKey contains either the Index or Key to the collection,
'this is why it is declared as a Variant
'Syntax: Set foo = x.Item(xyz) or Set foo = x.Item(5)
On Error GoTo ErrHnd
Set Item = mCol(vntIndexKey)
Exit Property
ErrHnd:
vntIndexKey = "28121978_"
Set Item = mCol(vntIndexKey)
End Property
Public Property Get Count() As Long
'used when retrieving the number of elements in the
'collection. Syntax: Debug.Print x.Count
Count = mCol.Count
End Property
Public Sub Remove(vntIndexKey As Variant)
'used when removing an element from the collection
'vntIndexKey contains either the Index or Key, which is why
'it is declared as a Variant
'Syntax: x.Remove(xyz)
mCol.Remove vntIndexKey
End Sub
Public Sub Clear()
'МАХ очистка коллекции
While mCol.Count > 0
mCol.Remove mCol.Count
Wend
End Sub
Public Property Get NewEnum() As IUnknown
'this property allows you to enumerate
'this collection with the For...Each syntax
Set NewEnum = mCol.[_NewEnum]
End Property
Private Sub Class_Initialize()
'creates the collection when this class is created
Set mCol = New Collection
End Sub
Private Sub Class_Terminate()
'destroys collection when this class is terminated
Set mCol = Nothing
End Sub
Борюсь с пропертёй:
Public Property Get Item(vntIndexKey As Variant) As ClsFixControls
'used when referencing an element in the collection
'vntIndexKey contains either the Index or Key to the collection,
'this is why it is declared as a Variant
'Syntax: Set foo = x.Item(xyz) or Set foo = x.Item(5)
On Error GoTo ErrHnd
Set Item = mCol(vntIndexKey)
Exit Property
ErrHnd:
vntIndexKey = "28121978_"
Set Item = mCol(vntIndexKey)
End Property
У тебя есть класс. В нем объявлена коллекция mCol. К ней ты обращаешься через проперти. Проперти класса Item должно возвращать по уник. ключу vntIndexKey объект типа ClsFixControls, ссылка на которого храниться в mCol. Тут вроде бы все понятно. Дальше. Если коллекция mCol пустая, то не знаешь что вернуть в проперти Item!?
По идее, проперти возвращает тип ClsFixControls - это может быть либо реальный объект или Nothing. Все, других вариантов нет. Либо меняем возвращаемый тип на Variant, и тоды возвращаем все что душе угодно.
Если тип не меняем, то остается токо создавать пустышку типа ClsFixControls и возвращать ее, токо ее конечно нельзя не лету удалять.
Так, т.е., если по простому:
У тебя есть класс. В нем объявлена коллекция mCol. К ней ты обращаешься через проперти. Проперти класса Item должно возвращать по уник. ключу vntIndexKey объект типа ClsFixControls, ссылка на которого храниться в mCol. Тут вроде бы все понятно. Дальше. Если коллекция mCol пустая, то не знаешь что вернуть в проперти Item!?
По идее, проперти возвращает тип ClsFixControls - это может быть либо реальный объект или Nothing. Все, других вариантов нет. Либо меняем возвращаемый тип на Variant, и тоды возвращаем все что душе угодно.
Если тип не меняем, то остается токо создавать пустышку типа ClsFixControls и возвращать ее, токо ее конечно нельзя не лету удалять.
Да, да, да!!!
Но вариант с "пустышкой" не проходит. Создать и удалить VB её даёт, а вот получти значение - нет.
Но зато я понял главное. Уважаемый XtreamAll был прав. Тут остаётся только вернуть Nothing и проверку делать по нему.
Огромное всем спасибо!!!:D
Бегу переделывать код!:P
Огромнейшее спасибо!!!
P.S. Извиняюсь, не уследил. Тот код, что я сюда выложил, рабочий, так как я на момент его выполнения априорно имею в коллекции элемент с ключём "28121978_" - я его туда принудительно вношу при первичном заполнении коллекции.
Слушай, так для себя, небольшие уточнения, а ClsFixControls который возвращает проперти Item это какой класс, в котором находится Item и mCol и все, все. Т.е. проблема получается в том - можно или нельзя в проперти класса создать объект этого же класса в нем самом... так я ни разу не делал, даже трудно сказать, вот так вот, с налета, интересно самому посмотреть...
Да, именно так.