COLLECTION - ITEM E KEY

TUNUSAT 27/08/2007 11:19:26
#232813
PessoALL,

Sem pressa ...
Estou fuçando em "collection" e achei aqui um codigo muito bom que ordena a collection.

Está em:
-----------
Título: CLASSIFICANDO UMA COLLECTION
Categoria: VB / VBA :: Dicas :: Tecnicas avancadas de programacao
-----------

Só tem um problema:
Ele não ordena por "key"?

Parece-me que para adicionar esta funcionalidade é preciso adicionar mais uma linha em baixo desta linha:

-----------
ArrayItems(EachItem - 1) = ColToSort(EachItem)
-----------

Seria colocada na Array ao invés do "item" da collection a "key" da collection. Talvez passando paâmetro de escolha pelo usuário se ele deseja que ordene por "item" ou por "key".

A pergunta é:
Como pegar a Key da collection?

[]'s,
Tunusat.
TUNUSAT 27/08/2007 17:23:24
#232963
PessoALL,

Descobri ...
Na verdade não era como eu pensava.
Eu explico! Vamos supor:

=========================
Dim obj As Collection

obj.Add "Melancia", "6"
obj.Add "Banana", "5"
obj.Add "Maçã", "1"
obj.Add "Pera", "4"
obj.Add "Mexirica", "3"
obj.Add "Laranja", "2"
=========================

Se vc colocar em "strItem" ...

=========================
Dim strItem As String
strItem = "3"

txtRecupera.Text = obj.Item(strItem)
=========================

Voltará o valor "Mexerica".
Se vc colocar 3 em "bytKey" ...

=========================
Dim bytKey As Byte

bytKey = 3
txtRecupera.Text = obj.Item(bytKey)
=========================

Voltará o valor "Maçã"! Pois é o terceiro valor cadastrado na lista!!!
Já se você colocar:

=========================
strTexto = "Pera"

txtRecupera.Text = obj.Item(strTexto)
=========================

Irá dar erro!!!
Impressionante, não?

- Conclusão: Impossível ordenar o valor pela 'key' pois estou passando a collection e não tem como recuperar o valor da 'key'.

- Contra-Conclusão: Isto derruba a 1ê diretiva do programador: "- Tudo é possível fazer na programação!"

- ÃÅ¡nica resposta encontrada: ... Apelar pra GAMBIWARE!

- Gambiware: Montar uma array paralela com a ordem da key e passar junto com a collection ... mas não dá para passar como parâmetro uma array! Bom ... a array será 'global' então.

Bom ... o código abaixo a função "SortCollection" está no mesmo 'form' que a array ...

=========================
Option Explicit
Dim obj As Collection
Dim obj2 As Collection
Dim obj3 As Collection
Dim clsCol As clsCollection
Dim arrString() As String

Private Sub cmdCarrega_Click()
Dim I As Byte

arrString = Split("I6,I5,I1,I4,I3,I2", ",")

obj.Add "Melancia", "I6"
obj.Add "Banana", "I5"
obj.Add "Maçã", "I1"
obj.Add "Pera", "I4"
obj.Add "Mexirica", "I3"
obj.Add "Laranja", "I2"
Debug.Print "----- Inicio"

For I = 1 To obj.Count
Debug.Print obj.Item(I)
Next

Set obj2 = clsCol.SortCollection(obj)
Set obj3 = SortCollection(obj)

Debug.Print "----- Ordenado por Index:"

For I = 1 To obj3.Count
Debug.Print obj.Item(obj3.Item(I))
Next

Debug.Print "----- Ordenado por Nome:"

For I = 1 To obj2.Count
Debug.Print obj2.Item(I)
Next

Debug.Print "----- Fim"
End Sub


Private Sub Form_Load()
Set obj = New Collection
Set obj2 = New Collection
Set obj3 = New Collection
Set clsCol = New clsCollection
End Sub


Private Sub Form_Unload(Cancel As Integer)
Set obj = Nothing
Set obj2 = Nothing
Set obj3 = Nothing
Set clsCol = Nothing
End Sub


Public Function SortCollection(ByVal ColToSort As Collection, Optional ByVal ColSortType As VbCompareMethod = vbTextCompare) As Collection
Dim EachItem As Long
Dim ColTemp As New Collection
Dim OrderNotChanged As Boolean
Dim ArrayItems() As String
Dim FirstStringInArray As String
Dim NumberOfItems As Long

NumberOfItems = ColToSort.Count

If NumberOfItems = 0 Then
Exit Function
End If

ReDim ArrayItems(NumberOfItems - 1)

For EachItem = 1 To NumberOfItems
'ArrayItems(EachItem - 1) = ColToSort.Item(EachItem)
ArrayItems(EachItem - 1) = arrString(EachItem - 1)
Next EachItem

Do
OrderNotChanged = True

For EachItem = 1 To NumberOfItems - 1

If Strings.StrComp(ArrayItems(EachItem - 1), ArrayItems(EachItem), ColSortType) = 1 Then
FirstStringInArray = ArrayItems(EachItem - 1)
ArrayItems(EachItem - 1) = ArrayItems(EachItem)
ArrayItems(EachItem) = FirstStringInArray
OrderNotChanged = False
End If

Next EachItem

Loop Until OrderNotChanged

For EachItem = 0 To NumberOfItems - 1
ColTemp.Add ArrayItems(EachItem)
Next EachItem

Set SortCollection = ColTemp
End Function

=========================

Funcionou ... pena que ficou horrível ... detesto isto!
E que Array muleta descarada, heim? KKKKK!
1ê Diretiva respeitada. (Obs.: Na marra).

Por favor, se vc tiver uma idéia melhor me envie.

[]'s,
Tunusat.
USUARIO.EXCLUIDOS 27/08/2007 17:44:13
#232970
Resposta escolhida
Tunusat!
Discordooo de algumas coisas daí de cima!

Citação:

- Conclusão: Impossível ordenar o valor pela 'key' pois estou passando a collection e não tem como recuperar o valor da 'key'.


Tem como recuperar o valor da Key, é meio gambi também, mas tem como! Olhe a função abaixo!

Public Function getKeyCollection(obj As Collection, texto As String) As String
For i = 1 To obj.Count
If UCase(obj.Item(i)) = UCase(texto) Then
getKeyCollection = i
End If
Next
End Function


Citação:


- Gambiware: Montar uma array paralela com a ordem da key e passar junto com a collection ... mas não dá para passar como parâmetro uma array! Bom ... a array será 'global' então.


Dá pra passar Array por parâmetro sim!!!

De uma olhada na função abaixo:
Public Function PassandoParametroArray(arTeste As Variant)
For i = 0 To UBound(arTeste)
MsgBox arTeste(i)
Next
End Function

Passe um array de strings para a função, veja o resultado. Algo deste tipo
    Dim a() As String

ReDim a(5)
For i = 0 To 5
a(i) = i
Next

PassandoParametroArray a



Bom... creio que com isto talvez vc consiga melhorar sua forma de ordenar a collection!



Abs!
TUNUSAT 28/08/2007 09:39:34
#233014
MARCELOHF,


1º) A parte da array ficou melhor. Obrigado!
Consegui colocar a "SortCollection" dentro de uma classe externa.

Modificações para passagem da array:

=========================
Public Function SortCollection(ByVal ColToSort As Collection, ByVal arrCol As Variant, ByVal blnItemKey, Optional ByVal ColSortType As VbCompareMethod = vbTextCompare) As Collection
=========================
If blnItemKey Then 'Trabalha por Item
ArrayItems(EachItem - 1) = ColToSort.Item(EachItem)
Else 'Trabalha por Key
ArrayItems(EachItem - 1) = arrCol(EachItem - 1)
End If
=========================

O retorno da array será o INDEX. Então precisa acertar isto também no código:

=========================
For i = 1 To obj3.Count
Debug.Print obj.Item(obj3.Item(i))
Next
=========================


2º) Mas a "getKeyCollection" não é bem isto ... eu explico!

Veja esta linha:
=========================
obj.Add "Melancia", "I6"
=========================

O retorno dela no "getKeyCollection" é "1" ... este valor é da posição de gravação na variável. O que eu quero de retorno é o valor da "key" que no caso é "I6", para depois pegar o "item" ("Melancia") e colocar na ordem.


[]'s,
Tunusat.
USUARIO.EXCLUIDOS 28/08/2007 10:58:38
#233037
Etendi... vc tem razão! Confundi Key com Index... hehe
Realmente não consegui retornar o Key, maaaas... vou tentar, gostei do desafio! hehe

Qualquer coisa posto novamente.
TUNUSAT 28/08/2007 13:01:36
#233081
MARCELOHF,

Fui eu que coloquei "index" no lugar de "key" ... desculpe a confusão.

---------------------------------------
Debug.Print "----- Ordenado por Index:"
---------------------------------------

O certo seria:

---------------------------------------
Debug.Print "----- Ordenado por Key:"
---------------------------------------

Valew!
[]'s,
Tunusat.
Tópico encerrado , respostas não são mais permitidas