Search code examples
excelvba

Do Until Object is Nothing assigns Something


i have a program in vba, that loops through an array of objects and does this until it finds one set to nothing,then it assigns an object to that index. But when i run this code somehow instead of Checking the condition it assigns something to that index in the array?

Here is the code:

    ' Inserts a Range into the DrawRange Array
    Public Sub Insert(ByVal ScreenObject As AL_ScreenObject)
        If IsInitialized = True Then
            Dim i As Integer
            
            i = 0
            Do Until p_ScreenObjects(i) Is Nothing
            i = i + 1
                If i > 1024 Then
                    AL_Error_Print 1, 5, LongValue
                    AL_Error_Show 1, 5, LongValue
                    End
                End If
            Loop
            Set p_ScreenObjects(i) = ScreenObject
        End If
    End Sub

The first If statement just checks if the object is properly initialized. The second If statement is an Errorhandler for Value overflow and doesnt contradict with the upper Condition.

I tried changing it from a Do Until statement to an if statement and i read the wiki about the nothing data type, but nothing suggests in this constellation that this would assign "nothing" to the index, let alone "something"


Solution

  • I am not sure if I understand your problem. Also, you missed to show some important pieces of your code, especially the definition of p_ScreenObjects. From your comment, I assume that the definition looks somehow like

    Dim p_ScreenObjects(1024) As New AL_ScreenObject 
    

    With this statement you
    a) define an array (of size 1025). The array doesn't contain 1025 objects (index from 0 to 1024), it contains 1025 object references.
    b) With the keyword new you create 1025 new objects (of type AL_ScreenObject) and assign the references to the array.

    Therefore, the array is already "full" and the condition p_ScreenObjects(i) Is Nothing will never be true.

    You probably just need to remove the New keyword:

    Dim p_ScreenObjects(1024) As AL_ScreenObject 
    

    This will create an array (as before), but all the references will be initialized with Nothing which reflects the fact that they don't point to an existing object. Now the first time you call your routine, it will fill the first element (0) as it is Nothing at that moment. The next time, element (1) will be filled and so on.

    Some remarks:
    (o) It is a good idea to specify the lower and upper bound of an array:

    Dim p_ScreenObjects(0 to 1024) As AL_ScreenObject 
    

    (or maybe 1 to 1024, but then you need to start with i = 1)

    (o) When you want to loop over an array, usually it is better to use the functions LBound and UBound and a For-Loop:

    Dim i As Long
    For i = LBound(p_ScreenObjects) to UBound(p_ScreenObjects)
        If p_ScreenObjects(i) Is Nothing Then
            Set p_ScreenObjects(i) = ScreenObject
            Exit For
        End If
    Next i
    
    If i > UBound(p_ScreenObjects) Then
        AL_Error_Print 1, 5, LongValue
        AL_Error_Show 1, 5, LongValue
    End If
    

    (o) I don't know the idea of your code, but instead of using an array, you are probably better of with a Collection:

    Dim p_ScreenObjects As New Collection
    
    Public Sub Insert(ScreenObject As AL_ScreenObject)
        If Not initialized Then Exit Sub   ' Don't know if this is needed.
        p_ScreenObjects.Add ScreenObject 
    End Sub
    

    If you need to ensure that the collection doesn't get too large:

    Const MaxSize = 1024
    Dim p_ScreenObjects As New Collection
    
    Public Sub Insert(ScreenObject As AL_ScreenObject)
        If Not initialized Then Exit Sub 
        If p_ScreenObjects.Count >= MaxSize Then
            AL_Error_Print 1, 5, LongValue
            AL_Error_Show 1, 5, LongValue
            Exit Sub
        End If 
        p_ScreenObjects.Add ScreenObject 
    End Sub
           
    

    (o) Defining the parameter ScreenObject with ByVal is useless - objects are always passed by Reference.

    (o) Make it a habit to use Option Explicit. Always. No exception.

    (o) Forget about the existance of type Integer. Use Long instead.