0

How to write a vba function which delete all elements from an array with a given value. I believe the funciton definition would look like this:

Function removeAllFromArray(element as Variant, myArray as Variant) as Boolean

...

removeAllFromArray = ? 
- True if all removed with the given value (element)
- Else it's False
End Function 

Function removeAllFromArray(ByRef element As Variant, ByRef a As Variant) As Boolean
    Dim i As Integer
    Dim iter As Variant
    For Each iter In a
        If iter = element Then
            a.Remove (iter)
        End If
    Next iter
    removeAllFromArray = arrayContainsA(a, element)
End Function

Where the arrayContainsA function is looks like this:

Function arrayContainsA(ByRef arrayOfSearch As Variant, ByRef searchedElement As Variant) As Boolean
    Dim element As Variant
    For Each element In arrayOfSearch
        If element = searchedElement Then
            arrayContainsA = True
            Exit Function
        End If
    Next element
    arrayContainsA = False
    Exit Function
End Function

It doesn't work at all.

1
  • By "doesn't work at all" I'm guessing you mean "this gives an error on a.Remove and the error is Run-time error '424' 'Object required'" - always give full details of your problem. There is no Remove method on an arrary - see stackoverflow.com/questions/7000334/… Commented Apr 10, 2024 at 10:39

2 Answers 2

0

The array is not a collection and does not have a Remove method.
You also can't modify the elements of an array by using a For Each loop, you have to refer to the elements of the array explicitly. And for that, you need to know how many dimensions the array has.
If the array has no more than 2 dimensions, you can use the following code, if the array could have more dimensions (a rare case) the code would need to be extended.

Function removeAllFromArray(ByRef element As Variant, ByRef a As Variant) As Boolean
    Dim i As Integer, j As Integer, s As Long
    If IsArray(a) Then
        On Error Resume Next
        s = UBound(a, 2)
        s = Err <> 0 ' 1 dim
        On Error GoTo 0
        If s = 0 Then
            For i = LBound(a) To UBound(a)
                For j = LBound(a, 2) To UBound(a, 2)
                    If a(i, j) = element Then a(i, j) = Empty
            Next j, i
        Else
            For i = LBound(a) To UBound(a)
                If a(i) = element Then a(i) = Empty
            Next i
        End If
    Else
        If a = element Then a = Empty
    End If
    removeAllFromArray = arrayContainsA(a, element)
End Function

Function arrayContainsA(ByRef arrayOfSearch As Variant, _
                        ByRef searchedElement As Variant) As Boolean
    Dim element As Variant
    For Each element In arrayOfSearch
        If element = searchedElement Then
            arrayContainsA = True
            Exit Function
        End If
    Next element
End Function

Sub Test()
    Dim MyArr(1 To 5) As Long
    Dim i As Long
    For i = 1 To 5
        MyArr(i) = i
    Next i
    Debug.Print removeAllFromArray(2, MyArr)
    Dim MyArr2(1 To 5, 1 To 1) As Long
    For i = 1 To 5
        MyArr2(i, 1) = i
    Next i
    Debug.Print removeAllFromArray(2, MyArr2)
    
End Sub
Sign up to request clarification or add additional context in comments.

Comments

0

Well, the arrays in VBA do not have such a Remove property...

The arrays field is large and rather complicated. In the next code I will try explaining how you can remove elements from 1D arrays without iteration.

You will see each code sequence return in Immediate Window. It can be seen pressing Ctrl + G, being in Visual Basic for Application Editor (VBE):


Sub PlayWith1DArrays()
  Dim arr, i As Long
  ReDim arr(5) '(0 To 5) = 6 elements...
  For i = 0 To 5
    arr(i) = i
  Next i
  Debug.Print Join(arr, "|")  'just tp see the loaded aray
  arr = filter(arr, 1, False) 'remove the 1 element
  Debug.Print Join(arr, "|")  'it returns 0|2|3|4|5
  
  'But loading the array in a similar way, WITH MORE ELEMENTS,
  'making it to load MORE elements CONTAINING 1:
  ReDim arr(1 To 15)
  For i = 1 To UBound(arr)
    arr(i) = i
  Next i
  Debug.Print Join(arr, "|") 'the loaded array
  arr = filter(arr, 1, False)
  Debug.Print Join(arr, "|") 'it returns 2|3|4|5|6|7|8|9
                             'it performs a textual comparison...
                             'removing elements containing 1 character.
                             
  'But you can use a TRICK to remove the EXACT (string) element:
  ReDim arr(1 To 15)
  For i = 1 To UBound(arr)
    arr(i) = "arr " & i
  Next i
  Debug.Print Join(arr, "|") 'the loaded array by iteration
  Dim elToRemove As String: elToRemove = "Arr 1" 'the element to be removed (no case sensitive...)
  Dim mtch
  Const strangeString As String = "xx$_$##" 'a strimg extremely improbable to be
                                            'contained by that array elements
  mtch = Application.match(elToRemove, arr, 0)
  If IsNumeric(mtch) Then  'if it exists in the array
    arr(mtch) = strangeString
    arr = filter(arr, strangeString, False)
  End If
  Debug.Print Join(arr, "|") 'it returns the array without its first element...
                             'arr 2|arr 3|arr 4|arr 5|arr 6|arr 7|arr 8|arr 9|arr 10|arr 11|arr 12|arr 13|arr 14|arr 15
                             'ReDim arr(1 To 15)...
                             
  'But this is happening when the LBound of the array is 1...
  'Otherwise, you need to check it and adapt:
  ReDim arr(14) ' (0 to 14)...
  For i = LBound(arr) To UBound(arr)
    arr(i) = "arr " & i
  Next i
  Debug.Print Join(arr, "|") 'the loaded array by iteration
  Debug.Print "LBound of arr = " & LBound(arr) 'LBound of the array declared as ReDim arr(14) is zero...
  mtch = Application.match(elToRemove, arr, 0)
  If IsNumeric(mtch) Then  'if it exists in the array
    arr(IIf(LBound(arr) = 0, mtch - 1, 1)) = strangeString 'match returns 1 for the first array element
                                                           'in a 1D array, without Option Base 1 or without
                                                           'ReDim with LBound different than 0, is zero!
    arr = filter(arr, strangeString, False)
  End If
  Debug.Print Join(arr, "|") 'it returns the array without its second element...
                             'arr 0|arr 2|arr 3|arr 4|arr 5|arr 6|arr 7|arr 8|arr 9|arr 10|arr 11|arr 12|arr 13|arr 14
  
  'A 2D array with a single column and a single row can be easily transformed in a 1D type and use the above
  'explained rules:
  ReDim arr(1 To 11, 1 To 1) 'a single column...
  For i = 1 To UBound(arr)
    arr(i, 1) = "arr " & i
  Next i
  arr = Application.Transpose(arr) 'transform it in 1D array by transposing...
  Debug.Print Join(arr, "|")       'the loaded array by iteration
  
  ReDim arr(1 To 1, 1 To 11) 'a single row...
  For i = 1 To UBound(arr, 2) 'the columns number
    arr(1, i) = "arr " & i
  Next i
  arr = Application.Transpose(Application.Transpose(arr)) 'transform it in 1D array by DOUBLE transposing...
  Debug.Print Join(arr, "|")       'the loaded array by iteration
  
  'proceed as above to filter it...
End Sub

I used Join function only to visually see the processing/filtering/removing return against the array loaded by iteration...

In the 2D arrays it is much more complicated to filter elements by rows or by columns... Basically, it can be done by iteration.

If something is not clear enough, please do not hesitate to specifically ask for clarifications.

Please, send some feedback after testing it.

2 Comments

Two comments. 1) I think better version of arr(IIf(LBound(arr) = 0, mtch - 1, 1)) = strangeString will be arr(LBound(arr) + mtch - 1) = strangeString, 2) Instead of arr = Application.Transpose(Application.Transpose(arr)) you can use arr = Application.Index(arr, 0)
@MGonet Yes, they can be used. Shorter variants...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.