Vba Add Collection into object property - vba

How can I add collection into the object.property ? It keeps giving me an error. What am I doing wrong?
I wanna get a tree structure, I mean inside one property(for example value) would be a collection which has another objects with collections...
Option Explicit
Public name As String
Public value As Variant
Public ValueType As String
Public valueHelp As Collection
Function addColl()
Dim i As Long
For i = 1 To 5
Dim nextCollection As Collection
Set nextCollection = New Collection
Dim obj1 As JsonElement
Set obj1 = New JsonElement
obj1.name = "City" & i
obj1.value = "type"
obj1.ValueType = nextCollection
nextCollection.Add obj1
'obj1.valueHelp = nextCollection
'nextCollection.Add nextCollection
Next
End Function

I guess you just have to replace this line:
obj1.ValueType = nextCollection
with this line:
Set obj1.ValueType = nextCollection
since the object type of the property you are trying to store a value in (type Collection) cannot implicitly call the Set keyword as it does with strings or integers.

Related

Nested VBA collection of classes returning "Argument not optional" error

I am trying to represent the idea of nested classes with collections of child classes with the natural example of Grandmother - Married Daughters - Little kids case, so I have 3 classes as following:
' Class GrandMother:
Private pMarriedDaughter As Collection
Public Property Get MarriedDaughter() As Collection
MarriedDaughter = pMarriedDaughter
End Property
Public Property Set MarriedDaughter(C As Collection)
Set pMarriedDaughter = C
End Property
' Class MarriedMom:
Private pChildren As Collection
Public Property Get Children() As Collection ' ERROR HERE!
Children = pChildren
End Property
Public Property Set Children(C As Collection)
Set pChildren = C
End Property
' Child Class:
Private pName As String
Public Property Get Name() As String
Name = pName
End Property
Public Property Let Name(s As String)
Let pName = s
End Property
And the Main Routine that tries to populate the classes:
Sub TestGrandMother()
' Create 3 Childs
Dim Child_1a As New Child: Child_1a.Name = "Bill"
Dim Child_1b As New Child: Child_1b.Name = "Sam"
Dim Child_2a As New Child: Child_2a.Name = "Sahar"
' Create 2 Married Daughters:
Dim Mamy1 As New MarriedMom
Dim Mamy2 As New MarriedMom
' Add the the children to the married daughters
Set Mamy1.Children = New Collection
Mamy1.Children.Add Child_1a
Mamy1.Children.Add Child_1b
Set Mamy2.Children = New Collection
Mamy2.Children.Add Child_2a
' Create Grandmother
Dim GrandMa As GrandMother: Set GrandMa = New GrandMother
Set GrandMa.MarriedDaughter = New Collection
GrandMa.MarriedDaughter.Add Mamy1
GrandMa.MarriedDaughter.Add Mamy2
' Now cycle childs Name and debug:
Dim aChild As New Child
For Each aChild In GrandMa.MarriedDaughter.Children
Debug.Print GrandMa.MarriedDaughter.Children.Name
Next aChild
End Sub
In both cases where that error occurs you need to use the Set keyword as working with an object. That is just for the error type you comment on.
e.g.
Set Children = pChildren
Set MarriedDaughter = pMarriedDaughter
The following GrandMa.MarriedDaughter does not expose a .Children btw.
Perhaps
Dim aChild As MarriedMom, nextChild As Child
For Each aChild In GrandMa.MarriedDaughter
For Each nextChild In aChild.Children
Debug.Print nextChild.Name
Next
Next aChild

How to find blank value from all member of class in vb.net

I have third party object which contain so many member with integer, string and Boolean. I want to update that record whose value is not null or blank
You can use reflection to achieve what you want:
Sub Main()
Dim obj As Test = new Test()
Dim type As Type = GetType(Test)
Dim info As PropertyInfo() = type.GetProperties()
For Each propertyInfo As PropertyInfo In info
Dim value As String = propertyInfo.GetValue(obj)
If propertyInfo.PropertyType = GetType(String) And String.IsNullOrEmpty(value)
' empty value for this string property
End If
Next
End Sub
public Class Test
Public Property Test As String
End Class

Merge two PropertyInfo

I've two structures and one class in my namespace Dimension. These structures are Dimension.Derived and Dimension.Basis. The class was called Exponent. I had overrided the Function ToString() of my class to get the DisplayNameAttribute of properties in my structure Dimension.Derived.
Public Overrides Function ToString() As String
Dim oType As Type
oType = GetType(Dimension.Derived)
Dim colMemberInfo() As PropertyInfo = oType.GetProperties
For Each oMemberInfo In colMemberInfo
If Me = oMemberInfo.GetValue(oMemberInfo) Then
Dim de As New Dimension.Exponent
de = oMemberInfo.GetValue(oType)
Dim attr() As DisplayNameAttribute = DirectCast(oMemberInfo.GetCustomAttributes(GetType(DisplayNameAttribute), False), DisplayNameAttribute())
If attr.Length > 0 Then
Return attr(0).DisplayName
Else
Exit For
End If
End If
Next
Return Nothing
End Function
That works fine, but it should search through both structures. Therefore, I changed the first lines into
Dim oType1, oType2 As Type
oType1 = GetType(Dimension.Derived)
oType2 = GetType(Dimension.Basis)
Dim colMemberInfo() As PropertyInfo = oType1.GetProperties And oType2.GetProperties
But this throws an exception that the And-Operator is not declared for PropertyInfo. Surely I can repeat the For-Each-loop for the another structure, but that's not the intention. What should I do to merge these PropertyInfos?
And is a boolean operator. It's for True/False values. You want to get a list of PropertyInfo from the two types, so try:
Dim properties as List(Of PropertyInfo) = New List(Of PropertyInfo)
properties.AddRange(oType1.GetProperties())
properties.AddRange(oType2.GetProperties())

VBA assigning to array

In the code snippet I create an array of string and want to assign it to another.
Dim rfms(0) As String
rfms(0) = "X"
The next line is not working
Me.SelectedRfms = rfms
But when I created the next function:
Function ReturnTheArrayInParamter(p() As String) As String()
ReturnTheArrayInParamter = p
End Function
This is working:
Me.SelectedRfms = ReturnTheArrayInParamter(rfms)
The definition of Me.SelectedRfms is the next:
Private pSelectedRfms() As String
''''''''''''''''''''''
' SelectedRfms property
''''''''''''''''''''''
Public Property Get SelectedRfms() As String()
SelectedRfms = pSelectedRfms
End Property
Public Property Let SelectedRfms(value() As String)
pSelectedRfms = value
End Property
Can you explain why the first one is not working and why the second is working.
You cannot assign an array declared with a fixed size to a property, use:
ReDim rfms(0) As String
(The indirect function does not use a fixed size array)

Infinite amount of Collection VBA

Here is the screen of my problem which is infinite amount of collections.
I want the collection be added to object property just once. Not like this:
http://postimg.org/image/o6da95j0f/
(screen showing the problem with "watch" of collection in VBA
Public Sub testCollections()
Dim index As Long
index = 1
Dim OJsonElement As JsonElement
Dim newColl As New Collection
Dim str As String
Call addColl(OJsonElement, newColl)
For Each OJsonElement In newColl
Debug.Print "THE NAME IS:" & OJsonElement.name
Next OJsonElement
End Sub
Function addColl(obj1 As JsonElement, nextCollection As Collection)
Dim i As Long
Set nextCollection = New Collection
Set obj1 = New JsonElement
Set obj1.valueCollection = nextCollection
obj1.name = "CityName"
obj1.value = "type"
nextCollection.Add obj1
'obj1.ValueType = nextCollection
'nextCollection.Add nextCollection
End Function
Class:
Public name As String
Public nameCollection As Collection
Public value As Variant
Public ValueType As String
Public valueCollection As Collection
I don't really understand well your code, but I will limit to explain you why it happens what you see in your watcher. The line:
Set obj1.valueCollection = nextCollection
is adding the new collection into the obj1 property valueCollection. Then, two lines after, you say:
nextCollection.Add obj1
which means you're adding the obj1 into its own property, so creating an infinite nesting. I'd like to help you but for that I'd need to understand what you want to reach with your code. But sticking to your request I want the collection be added to object property just once, I would just suggest you to remove the line nextCollection.Add obj1, which (at least from the perspective of who doesn't know the project purpose) does not seem to do anything useful but an infinite nesting.