2

I am having trouble with this pesky error message (see title) I have seen it on a lot of posts on this site and others and it is usually some dumb mistake and try as I might I cannot see what dumb thing I am doing.

Public Property Get Contents() As Variant
    Contents() = pContents()
End Property

Public Property Let Contents(Values() As Variant)
    pContents = Values()
End Property

Public Property Get Content(Index As Integer) As String
    Content = pContents(Index)
End Property

Public Property Let Content(Index As Integer, Value As String)
...

The aim being that the pair of get, let two allow the entire array to be read/written and the second allows read/writing to individual elements of the array by index.

According to this: https://msdn.microsoft.com/en-us/library/office/gg251357.aspx

Let and Get property statement thingies (Yes, I am fairly new to this) for a class in a class module have to meet certain requirements (which I am curious as to why exactly?). As far as I can tell, mine meet those requirements:

My Let has one more parameter (2) than my Get (1) - I'm assuming here that the "as string" outside of the brackets doesn't count as an argument. Also I use the same types (integer and string) in both the Let and Get, I have no need for a Set so that shouldn't be a problem. I have also tried changing the names of the parameter variables to no avail.

So please help me, what is wrong and how can I avoid this mistake in the future?

Community
  • 1
  • 1
drmason13
  • 31
  • 6

1 Answers1

1

Well I seem to have resolved the issue myself, posting the answer here in case it helps others! :)

Precautions to make when setting class properties to arrays (and reading them)

1) be careful with brackets(): don't use them in the Let statement

Public Property Let ArrayProperty (newArray as variant)

as opposed to the tempting

Public Property Let ArrayProperty (newArray() as variant) 

Similarly, don't use them when using this property e.g:

Class1.ArrayProperty = myArray

no brackets after myArray

2) Check that your arrays are not empty in property (myArray) Let statements

Link here VBA: Don't go into loop when array is empty to the answer that helped me accomplish this, it seems you have to build your own function or use error handling to do it,

IsEmpty(myArray)

won't work.

and the code snippet adapted for my purposes (credit to original snippet goes to CreamyEgg):

Public Function IsEmptyArray(TestArray) As Boolean

Dim lngUboundTest As Long

lngUboundTest = -1
    On Error Resume Next
lngUboundTest = UBound(TestArray)
On Error GoTo 0

If lngUboundTest >= 0 Then    
IsEmptyArray = False
Else
IsEmptyArray = True
End If
End Function

3) remember that you might need to redim your property array to the Ubound(newArray), e.g.

Public Property Let Contents (newArray as variant)
'redim pArray to size of proposed array
ReDim pArray(1 To UBound(newArray))
'above line will throw an exception if newArray is empty
    pArray = newArray   
end Property

4) to deliberately make a class property an empty array, I used a temporary array variable, publicly declared outside of a sub at the start of a standard module

Public TempArray() As Variant
'outside of Sub ^^

Sub SetClass1ArrayToEmpty
    Erase TempArray
    class1.ArrayProperty = TempArray
End Sub

the erase method will make an array empty, i used it since I occasionally used TempArray to make arrays of size 1 and wanted to make sure it was empty

5) good news, setting a range to a class property seems to work the same way as setting a range to an array, I used application.transpose(myRange) to avoid problems with one column becoming a 2 dimensional array

class1.ArrayProperty = Application.Transpose(Range(myRange))

and there you have it, here is the class that works (no compile error)

Public Property Get Contents() As Variant
    Contents() = pContents()
End Property

Public Property Let Contents(Values As Variant)
'checks for an empty array being passed to it first
If IsEmptyArray(Values) Then
    Erase pContents
Else
'redim pContents to size of proposed array
    ReDim pContents(1 To UBound(Values))
        pContents = Values
End If
End Property

Public Property Get Content(Index As Integer) As String
    Content = pContents(Index)
End Property

Public Property Let Content(Index As Integer, Value As String)

Select Case Index
    Case Is < 0
        'Error Handling
    Case Is > UBound(pContents) + 1
        'Error Handling
    Case Is = UBound(pContents) + 1  'append to end of array
        ReDim Preserve pContents(UBound(pContents) + 1)
        pContents(Index) = Value
    Case Else                        'replace some middle part of array
        pContents(Index) = Value
End Select

End Property

Hope this helps some peeps!

Community
  • 1
  • 1
drmason13
  • 31
  • 6
  • Thank you - after a lot of googling, I eventually found this! Removing the () in the Let statement helped me out. – samb8s Jun 23 '16 at 13:08