-
Feb 14th, 2020, 02:58 AM
#1
Thread Starter
PowerPoster
[RESOLVED] Is it possible to add an enumerator to an array?
I wonder if there is a way to add an enumerator to a VB array, for example:
Code:
For Each vArrayItem In vArray
'Do something
Next
Class1
Code:
Option Explicit
Private mItems() As Variant
Public Property Get Item(ByVal Index As Long) As Variant
Item = mItems(Index)
End Property
Public Property Let Item(ByVal Index As Long, NewVal As Variant)
mItems(Index) = NewVal
End Property
Public Function NewEnum() As IUnknown
Set NewEnum = mItems.[_NewEnum]
End Function
Private Sub Class_Initialize()
mItems = Array(10)
End Sub
Thanks.
-
Feb 14th, 2020, 05:09 AM
#2
Re: Is it possible to add an enumerator to an array?
IIRC, it is possible, but as a Property Get not a Function
I think it was something like this:
Tools|Procedure Attributes then click Advanced
Select NewEnum
Set Procedure ID to -4
Last edited by Zvoni; Tomorrow at 31:69 PM.
----------------------------------------------------------------------------------------
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------------------
People call me crazy because i'm jumping out of perfectly fine airplanes.
---------------------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad
-
Feb 14th, 2020, 06:49 AM
#3
Thread Starter
PowerPoster
Re: Is it possible to add an enumerator to an array?
Hi Zvoni, I tried your method and it still doesn't seem to work. The system prompts "Object required"
-
Feb 14th, 2020, 07:03 AM
#4
Re: Is it possible to add an enumerator to an array?
It only works for collections isn't it? Doesn't work for arrays in the class.
-
Feb 14th, 2020, 07:06 AM
#5
Re: Is it possible to add an enumerator to an array?
Originally Posted by Arnoutdv
It only works for collections isn't it? Doesn't work for arrays in the class.
IIRC, it works for your own "Collection"-Classes, too (independent if internally it's a collection or an array)
I remember doing something like that some 15 years ago, but i don't have the source-code anymore (at least i haven't seen it in 15 years).
Bruce McKinney had an example in his HVB-Book
EDIT: Found Bruce's Source-Code from HVB
Code:
Public Function NewEnum() As IEnumVARIANT
Attribute NewEnum.VB_UserMemId = -4
Last edited by Zvoni; Feb 14th, 2020 at 07:18 AM.
Last edited by Zvoni; Tomorrow at 31:69 PM.
----------------------------------------------------------------------------------------
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------------------
People call me crazy because i'm jumping out of perfectly fine airplanes.
---------------------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad
-
Feb 14th, 2020, 07:16 AM
#6
Re: Is it possible to add an enumerator to an array?
I know it works for looping thru an array.
I never saw a sample for the NewEnum on a variant array in a class.
Did some searching, maybe this can be used as a skeleton:
http://www.mvps.org/vbvision/Super_Collections.htm
-
Feb 14th, 2020, 07:37 AM
#7
Re: Is it possible to add an enumerator to an array?
Arnout,
yeah, kind looks familiar with the mentioned hacks
Last edited by Zvoni; Tomorrow at 31:69 PM.
----------------------------------------------------------------------------------------
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------------------
People call me crazy because i'm jumping out of perfectly fine airplanes.
---------------------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad
-
Feb 14th, 2020, 10:53 AM
#8
Thread Starter
PowerPoster
Re: Is it possible to add an enumerator to an array?
Originally Posted by Arnoutdv
Hi Arnoutdv, I downloaded and read the code from the link you provided, it's too complicated, I decided to give up adding an enumerator to the VB array. Thank you, Arnoutdv. Thank Zvoni too.
-
Feb 14th, 2020, 02:31 PM
#9
Re: Is it possible to add an enumerator to an array?
Originally Posted by dreammanor
I decided to give up adding an enumerator to the VB array.
One easy way is, to return the "Array itself" via an Items-Property (since VB can enumerate on its own SafeArrays).
Class1-Code:
Code:
Option Explicit
Private mItems() As Variant
Private Sub Class_Initialize()
mItems = Array() 'inits the array (though still with no members)
End Sub
Public Sub push(Item)
ReDim Preserve mItems(0 To UBound(mItems) + 1): mItems(UBound(mItems)) = Item
End Sub
Public Property Get length() As Long
length = UBound(mItems) + 1
End Property
Public Property Get Item(ByVal Index As Long) As Variant '<- usually with Default-Attribute set
Item = mItems(Index)
End Property
Public Property Let Item(ByVal Index As Long, RHS As Variant)
mItems(Index) = RHS
End Property
Public Property Get Items() As Variant()
Items = mItems
End Property
And Test-Form-Code:
Code:
Private Sub Form_Load()
Dim Arr As New Class1, V
Arr.push 1
Arr.push 2
Arr.push 3
Debug.Print "Arr-length: "; Arr.length
For Each V In Arr.Items '<- but Items needs to be specified explicitely then
Debug.Print V
Next
End Sub
Another variant for "easy enumerations" would be, to use an RC5-Helper for that,
(in conjunction with "flagging" the Enumerator-method of the Class with AttributeID= -4)
Class1-Code:
Code:
Option Explicit
Implements IEnumerable 'we implement the IEnumerable-Interface from RC5
Private mItems() As Variant
Private Sub Class_Initialize()
mItems = Array() 'inits the array (though still with no members)
End Sub
Public Sub push(Item)
ReDim Preserve mItems(0 To UBound(mItems) + 1): mItems(UBound(mItems)) = Item
End Sub
Public Property Get length() As Long
length = UBound(mItems) + 1
End Property
Public Property Get Item(ByVal Index As Long) As Variant '<- usually with Default-Attribute set
Item = mItems(Index)
End Property
Public Property Let Item(ByVal Index As Long, RHS As Variant)
mItems(Index) = RHS
End Property
Public Property Get Items() As Variant()
Items = mItems
End Property
Public Function NewEnum() As IUnknown '<- needs Enumerable-ProcAttribute: -4
Set NewEnum = New_c.EnumerateOn(Me, UBound(mItems) + 1)
End Function
Private Function IEnumerable_NextItem(Idx As Long) As Variant 'this is the IEnumerable-Callback
IEnumerable_NextItem = mItems(Idx)
End Function
And Test-Form-Code again:
Code:
Private Sub Form_Load()
Dim Arr As New Class1, V
Arr.push 1
Arr.push 2
Arr.push 3
Debug.Print "Arr-length: "; Arr.length
For Each V In Arr.Items '<- but Items needs to be specified explicitely then
Debug.Print V
Next
For Each V In Arr '<- now one can also directly enumerate on Arr
Debug.Print V
Next
End Sub
HTH
Olaf
-
Feb 15th, 2020, 12:13 PM
#10
Re: [RESOLVED] Is it possible to add an enumerator to an array?
http://www.vbforums.com/showthread.p...hout-a-typelib
Here is a "raw" implementation of a handy IEnumVARIANT light-weight object. It just forwards IEnumVARIANT::Next to parent object's default method with some code like this
VariantCopyToPtr rgVar, .Enumerable(.Index)
. . . so this trades the need to implement a custom IEnumerable interface for a bit of speed.
Of course RC5's solution is probably a lot more stable in the IDE as first it's a compiled DLL and second it's been excercised a bit more in the wild for some years now.
cheers,
</wqw>
Last edited by wqweto; Feb 15th, 2020 at 12:22 PM.
-
Feb 16th, 2020, 01:39 AM
#11
Thread Starter
PowerPoster
Re: Is it possible to add an enumerator to an array?
Originally Posted by Schmidt
One easy way is, to return the "Array itself" via an Items-Property (since VB can enumerate on its own SafeArrays).
Class1-Code:
Code:
Option Explicit
Private mItems() As Variant
Private Sub Class_Initialize()
mItems = Array() 'inits the array (though still with no members)
End Sub
Public Sub push(Item)
ReDim Preserve mItems(0 To UBound(mItems) + 1): mItems(UBound(mItems)) = Item
End Sub
Public Property Get length() As Long
length = UBound(mItems) + 1
End Property
Public Property Get Item(ByVal Index As Long) As Variant '<- usually with Default-Attribute set
Item = mItems(Index)
End Property
Public Property Let Item(ByVal Index As Long, RHS As Variant)
mItems(Index) = RHS
End Property
Public Property Get Items() As Variant()
Items = mItems
End Property
And Test-Form-Code:
Code:
Private Sub Form_Load()
Dim Arr As New Class1, V
Arr.push 1
Arr.push 2
Arr.push 3
Debug.Print "Arr-length: "; Arr.length
For Each V In Arr.Items '<- but Items needs to be specified explicitely then
Debug.Print V
Next
End Sub
Another variant for "easy enumerations" would be, to use an RC5-Helper for that,
(in conjunction with "flagging" the Enumerator-method of the Class with AttributeID= -4)
Class1-Code:
Code:
Option Explicit
Implements IEnumerable 'we implement the IEnumerable-Interface from RC5
Private mItems() As Variant
Private Sub Class_Initialize()
mItems = Array() 'inits the array (though still with no members)
End Sub
Public Sub push(Item)
ReDim Preserve mItems(0 To UBound(mItems) + 1): mItems(UBound(mItems)) = Item
End Sub
Public Property Get length() As Long
length = UBound(mItems) + 1
End Property
Public Property Get Item(ByVal Index As Long) As Variant '<- usually with Default-Attribute set
Item = mItems(Index)
End Property
Public Property Let Item(ByVal Index As Long, RHS As Variant)
mItems(Index) = RHS
End Property
Public Property Get Items() As Variant()
Items = mItems
End Property
Public Function NewEnum() As IUnknown '<- needs Enumerable-ProcAttribute: -4
Set NewEnum = New_c.EnumerateOn(Me, UBound(mItems) + 1)
End Function
Private Function IEnumerable_NextItem(Idx As Long) As Variant 'this is the IEnumerable-Callback
IEnumerable_NextItem = mItems(Idx)
End Function
And Test-Form-Code again:
Code:
Private Sub Form_Load()
Dim Arr As New Class1, V
Arr.push 1
Arr.push 2
Arr.push 3
Debug.Print "Arr-length: "; Arr.length
For Each V In Arr.Items '<- but Items needs to be specified explicitely then
Debug.Print V
Next
For Each V In Arr '<- now one can also directly enumerate on Arr
Debug.Print V
Next
End Sub
HTH
Olaf
The above two solutions are exactly what I need, especially the second solution using RC5.IEnumerable, which is perfect. Olaf, you are like a magician, you can always pull something amazing out of your hat. Much appreciated!
-
Feb 16th, 2020, 01:44 AM
#12
Thread Starter
PowerPoster
Re: [RESOLVED] Is it possible to add an enumerator to an array?
Originally Posted by wqweto
http://www.vbforums.com/showthread.p...hout-a-typelib
Here is a "raw" implementation of a handy IEnumVARIANT light-weight object. It just forwards IEnumVARIANT::Next to parent object's default method with some code like this
VariantCopyToPtr rgVar, .Enumerable(.Index)
. . . so this trades the need to implement a custom IEnumerable interface for a bit of speed.
Of course RC5's solution is probably a lot more stable in the IDE as first it's a compiled DLL and second it's been excercised a bit more in the wild for some years now.
cheers,
</wqw>
Hi wqweto, the information you provided is very useful. At present, I'll use Olaf's method, and the DEXWERX's solution will be put into my database for future learning materials. Thank you very much, wqweto.
-
Feb 16th, 2020, 06:04 AM
#13
Re: [RESOLVED] Is it possible to add an enumerator to an array?
@Olaf: Just fiddled a bit with the RC5 enumerator impl and found that the following line brings the IDE down
Debug.Print TypeName(Arr.NewEnum)
While you at it investigating QI impl can you bolt a simple IDispatch tear-off object that handles DISPID_NEWENUM only so that this code works
Code:
For Each V In Arr.NewEnum '<- has an IDispatch that returns itself on DISPID_NEWENUM
Debug.Print V
Next
The idea is for a dictionary replacement to be able to use separate enumerators for both keys and values like this
Code:
For Each V In oDict.Keys
Debug.Print "Key=" & V
Next
For Each V In oDict.Items
Debug.Print "Item=" & V
Next
For Each V In oDict
Debug.Print "Tuple=(" & V(0) & ", " & V(1) & ")"
Next
cheers,
</wqw>
-
Feb 16th, 2020, 06:06 PM
#14
Re: [RESOLVED] Is it possible to add an enumerator to an array?
Originally Posted by wqweto
Just fiddled a bit with the RC5 enumerator impl and found that the following line brings the IDE down
Debug.Print TypeName(Arr.NewEnum)
Thanks, should be fixed now, in new version 5.0.75
...(when you download - please re-register on your dev-machines despite being BinCompatible, because of new Interface- and Class-additions in RC5)
Originally Posted by wqweto
While you at it investigating QI impl can you bolt a simple IDispatch tear-off object that handles DISPID_NEWENUM ...
Ok, done...
New version 5.0.75 now contains the complete functionality (+ a few extra-helpers) of what was shown here.
http://www.vbforums.com/showthread.p...BaseInterfaces
(the above line offers the Sources for a Dll which supports Base-Interface-SubClassing in a VB-Friendly manner).
An RC5-adapted Tutorial-Folder-Stack which demonstrates that functionality, is now available here:
TutorialApps_RC5.VBI.zip
For your outlined usecase, the Tutorial-Folder: 4 - MultiEnumerations per vbIEnumerable
should offer appropriate code...
@dreammanor
FWIW... cArrayList now got For Each support built-in as well...
HTH
Olaf
-
Feb 16th, 2020, 11:50 PM
#15
Re: [RESOLVED] Is it possible to add an enumerator to an array?
Nice work Olaf - There's been a couple of times I wished the cArrayList was enumerable, and now it is
-
Feb 17th, 2020, 03:32 AM
#16
Re: [RESOLVED] Is it possible to add an enumerator to an array?
Originally Posted by Schmidt
For your outlined usecase, the Tutorial-Folder: 4 - MultiEnumerations per vbIEnumerable
Using vbIEnumerable now both
For Each V In Arr
. . . and
For Each V In Arr.NewEnum
. . . work. Great!
cheers,
</wqw>
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|