2

IS it possible to look for an array of strings and/or integers inside an array of strings and/or integers? If so, then how?

To find a string in an array of strings I use code like:

If IsInArray(LowerFilmWidthArray, LowerFilmWidth) then
'Dos tuff
end if

And a function is:

Function IsInArray(arr As Variant, myVal As Variant) As Boolean

IsInArray = Not IsError(Application.Match(myVal, arr, 0))
Debug.Print (IsInArray)

End Function

As a result example, imagine you have an array of integers (1-10) and You are looking if your array (1,5,6) are inside that previous array (all items of it) and then return True. In my case I am getting all my to look for values in columns from 3rd to last column with data, which would make up my array that I try to find ALL items of in another array and return true or false.

An actual example:

Dim LowerFilmWidthArray
LowerFilmWidthArray = Application.Transpose(Evaluate("row(320:420)"))

Dim LowerFilmWidth As Integer
LowerFilmWidth = Array(ThisWorkbook.Worksheets("Machine Specification").Cells(320, 400,400,620)
'I get theese from a range and they might as well be strings and an undefined number of defined by 3 to last column with data

if isinarray(LowerFilmWidthArray,LowerFilmWidth) then
msgbox("Great Success!")
end if

Result in this one would be false because of that last "620" which is not inside the LowerFilmWidthArray.

EDITED:

Still can't get this to work and my gut says that there's way too many unnecessary things in the answers when I simply need to take each item from an array and try to find it in another and get "TRUE" only if all items I was looking for are present in a big array.

I have converted my to look for array (smaller one) to get the values from a set range that will always be a row from 3 to lastcolumn.

Dim LowerFilmWidth
LowerFilmWidth = ThisWorkbook.Worksheets("Machine Specification").Range(Cells(Cells.Find("Lower Film Width (mm)").Row, 3), Cells(Cells.Find("Lower Film Width (mm)").Row, LastColumn))

And I expect this part to make an array of all the values in cells in that range. Now I need to see if all those items / elements are present in:

Dim LowerFilmWidthArray
LowerFilmWidthArray = Application.Transpose(Evaluate("row(320:420)"))

So I use the suggested function:

Function arrElemInArray(arr As Variant, arrX As Variant) As Boolean
   Dim i As Long, j As Long, boolFound As Boolean
   For i = LBound(arrX) To UBound(arrX)
        For j = LBound(arr) To UBound(arr)
            If CStr(arr(j)) = CStr(arrX(i)) Then
                boolFound = True: Exit For
            End If
            If Not boolFound Then arrElemInArray = False: Exit Function
        Next j
   Next i
   arrElemInArray = True
   
  Debug.Print (arrElemInArray)
End Function

and engage it using

If arrElemInArray(LowerFilmWidthArray, LowerFilmWidth) Then
msgbox("Great success!")
End If

The solution has to work both with integers and strings. I still can't get it to work as expected. Often it returns "True" no matter what, but it seems that it only checks the first item in smaller array against the big array.

This code in the edit returns "subscript out of range" error on "CStr(arrX(i))".

But the values in the sheet are as in the image enter image description here

The full subroutine looks like this:

Sub Testing()

Dim LastColumn As Long
LastColumn = Cells(Cells.Find("Parameters", lookat:=xlWhole).Row, Columns.Count).End(xlToLeft).Column

Dim LowerFilmWidth
LowerFilmWidth = ThisWorkbook.Worksheets("Machine Specification").Range(Cells(Cells.Find("Lower Film Width (mm)").Row, 3), Cells(Cells.Find("Lower Film Width (mm)").Row, LastColumn))

Dim LowerFilmWidthArray
LowerFilmWidthArray = Application.Transpose(Evaluate("row(320:420)"))

If arrElemInArray(LowerFilmWidthArray, LowerFilmWidth) Then
MsgBox ("Great success!")
End If

End Sub

Workbook: enter link description here

15
  • What do you mean? I can't really loop through my columns using to look for value as a single string. That's what my question occurred Commented Jan 24, 2022 at 14:09
  • 3
    Would this be a practical example: 1.) Data = Range("A3:A20").Value and 2.) Arr = Array(1, 5, 6) i.e. return true if all elements of Arr are found in Data? Please share more detail because the efficiency of a solution will depend on it. Commented Jan 24, 2022 at 14:13
  • 1
    Ok Adding an example. The code I provide as an example is just an example and obviously doesn't work, otherwise I wouldn't have a question here Commented Jan 24, 2022 at 14:18
  • 1
    @VBasic2008 it's the other way around I am looking for a range values to be inside a filter array (filter as in let it through if the whole range is inside the Arr) Commented Jan 24, 2022 at 14:24
  • What do you expect from LowerFilmWidth = Array(ThisWorkbook.Worksheets("Machine Specification").Cells(320, 400,400,620)? LowerFilmWidth being an Integer... Commented Jan 24, 2022 at 14:28

2 Answers 2

2

Please, look at the next example. Is this what you try accomplishing?

Sub testArrInArr()
  Dim arr(), arr1(), arr2(), arr3(), arr4()
  arr1 = Array(1, 2, 3): arr2 = Array(2, 3, 4)
  arr3 = Array(3, 6, 5, 4): arr4 = Array(4, 5, 6)
  
  arr = Array(arr1, arr2, arr3)
  Debug.Print arrIsInArray(arr, arr2)
End Sub

Function arrIsInArray(arr As Variant, arrX As Variant) As Boolean
   Dim i As Long, jArr As String
    For i = LBound(arr) To UBound(arr)
        If Join(arr(i)) = Join(arrX) Then arrIsInArray = True: Exit Function
    Next i
End Function

Edited:

In order to test each array element if exists in another array, plese try the next way:

Sub tst2CheckArrElements()
  Dim arr, arr1, arr2
  arr = Split("1,2,3,4,5", ","): arr1 = Split("Sausage,Dog,Ship", ","): arr2 = Split("1,3,2", ",")
  
  Debug.Print arrElemInArray(arr, arr1)
  Debug.Print arrElemInArray(arr, arr2)
End Sub

Function arrElemInArray(arr As Variant, arrX As Variant) As Boolean
   Dim i As Long, j As Long, boolFound As Boolean, mtch

   If Not IsArray(arrX) Then
         For j = LBound(arr) To UBound(arr)
            If CStr(arr(j)) = CStr(arrX) Then arrElemInArray = True: Exit For
        Next j
        Exit Function
   End If
   For i = LBound(arrX) To UBound(arrX, 2)
        For j = LBound(arr) To UBound(arr)
            If CStr(arr(j)) = CStr(arrX(1, i)) Then
                boolFound = True: Exit For
            End If
        Next j
        If Not boolFound Then arrElemInArray = False: Exit Function
        boolFound = False
   Next i
   arrElemInArray = True   
End Function
Sign up to request clarification or add additional context in comments.

15 Comments

Comments are not for extended discussion; this conversation has been moved to chat.
@Eduards Yes, you mentioned about using the solution for strings, too! But it doesn't work with strings DOES NOT SAY ANYTHING! Are you able to accurately describe what you try (the involved strings, please) and what doesn't work means? Does the code return an error? If yes, what error on which line? If not, what wrong is happening? I suppose you know that StringA = stringA is false. It is case sensitive! Please, show what strings do you try comparing!
@Faneduru Nothing is helpful in the way you pseudo explain the 'problem'... How do you imagine I can solve a problem without explaining it accurately? Should I test all possible strings? Please, share the 'problematic' workbook. It looks that we cannot understand well only speaking, in terms of what is happening and what is to be done...
@Eduards Since we are not able to understand each other only in words, please share the workbook. I explained very clearly, on my tase, what is wrong: You called the function with a not existing parameter! Where in the code you show is LowerFilmWidthArray declaration and the way of lading it?
Please, check the updated code here. It is also not case sensitive, if you like it more in this variant...
|
1

Is Array In Array

Personalized Study

  • Change the number format of the cells containing the values to general or to a numeric format to make it work.
Option Explicit

Sub Testing()

    Const sHeader As String = "Parameters"
    Const sProperty As String = "Lower Film Width (mm)"
    
    Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
    Dim ws As Worksheet: Set ws = wb.Worksheets("Machine Specification")

    ' Reference the last cell of the used range.
    Dim LastCell As Range
    With ws.UsedRange
        Set LastCell = .Cells(.Rows.Count, .Columns.Count)
        Debug.Print "UsedRange:        " & .Address(0, 0)
        Debug.Print "LastCell:         " & LastCell.Address(0, 0)
    End With
    
    ' Reference the header cell.
    Dim HeaderCell As Range
    Set HeaderCell = ws.Cells.Find(sHeader, LastCell, xlFormulas, xlWhole)
    If HeaderCell Is Nothing Then Exit Sub ' header not found
    Debug.Print "HeaderCell:       " & HeaderCell.Address(0, 0)
    
    ' Calculate the first column number.
    Dim FirstColumn As Long: FirstColumn = HeaderCell.Column + 1
    Debug.Print "FirstColumn:      " & FirstColumn
    
    ' Calculate the last column number.
    Dim LastColumn As Long: LastColumn = _
        ws.Cells(HeaderCell.Row, ws.Columns.Count).End(xlToLeft).Column
    If LastColumn < FirstColumn Then Exit Sub ' no data to the right of header
    Debug.Print "LastColumn:       " & LastColumn
    
    ' Reference the column range below the header cell
    ' to search for the property.
    Dim sDataColumnRange As Range ' below the header
    Set sDataColumnRange _
        = HeaderCell.Resize(LastCell.Row - HeaderCell.Row).Offset(1)
    Debug.Print "sDataColumnRange: " & sDataColumnRange.Address(0, 0); ""
    
    ' Reference the property cell.
    Dim sPropertyCell As Range
    With sDataColumnRange
        Set sPropertyCell _
            = .Find(sProperty, .Cells(.Rows.Count), xlFormulas, xlWhole)
        If sPropertyCell Is Nothing Then Exit Sub ' property not found
        Debug.Print "sPropertyCell:    " & sPropertyCell.Address(0, 0)
    End With
    
    ' Reference the property (values) row range (first to last column).
    Dim PropertyRowRange As Range
    Set PropertyRowRange = ws.Range(ws.Cells(sPropertyCell.Row, FirstColumn), _
        ws.Cells(sPropertyCell.Row, LastColumn))
    Debug.Print "PropertyRowRange: " & PropertyRowRange.Address(0, 0)
    Debug.Print "PropertyRowRange Values" & vbLf & Join(Application.Transpose( _
        Application.Transpose(PropertyRowRange.Value)), ", ")
    
    ' Populate the property values array.
    Dim PropertyValuesArray As Variant
    PropertyValuesArray = Application.Transpose(Evaluate("Row(320:420)"))
    Debug.Print "PropertyValuesArray Values"
    Debug.Print Join(PropertyValuesArray, ", ")
    
    ' Return the result whether all values of the property row range
    ' are found in the property values array.
    If IsRowInArr(PropertyValuesArray, PropertyRowRange) Then
        MsgBox "All matching.", vbInformation
        Debug.Print "All matching."
    Else
        MsgBox "Not all matching.", vbCritical
        Debug.Print "Not all matching."
    End If

End Sub


''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose:      Returns a boolean indicating whether a 1D array ('InArr')
'               contains all values in a row ('RowIndex')
'               of a range ('IsRange').
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function IsRowInArr( _
    ByVal InArr As Variant, _
    ByVal IsRange As Range, _
    Optional ByVal RowIndex As Long = 1) _
As Boolean
    Const ProcName As String = "IsRowInArr"
    On Error GoTo ClearError
    
    With IsRange.Rows(RowIndex)
        Dim cCount As Long: cCount = .Columns.Count
        If cCount = 1 Then
            IsRowInArr = IsNumeric(Application.Match(.Value, InArr, 0))
        Else
            Dim IsRow As Variant: IsRow = .Value
            IsRowInArr = Application.Count(Application.Match( _
                IsRow, InArr, 0)) = cCount
        End If
    End With

ProcExit:
    Exit Function
ClearError:
    Debug.Print "'" & ProcName & "' Run-time error '" _
        & Err.Number & "':" & vbLf & "    " & Err.Description
    Resume ProcExit
End Function

Initial Answer

  • The function will return true if all the elements of an array (IsArr) are found in another array (InArr).
Option Explicit

Sub IsArrayInArrayTEST()
    
    Dim InArr As Variant: InArr = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    
    Dim IsArr As Variant
    
    IsArr = Array(1)
    Debug.Print IsArrayInArray(IsArr, InArr) ' True
    
    IsArr = Array(1, 5, 11)
    Debug.Print IsArrayInArray(IsArr, InArr) ' False

End Sub

Function IsArrayInArray( _
    ByVal IsArr As Variant, _
    ByVal InArr As Variant) _
As Boolean
    
    Dim IsCount As Long: IsCount = UBound(IsArr) - LBound(IsArr) + 1
    Dim rArr As Variant: rArr = Application.Match(IsArr, InArr, 0)
    Dim rCount As Long: rCount = Application.Count(rArr)
    'Debug.Print rCount, IsCount
    If rCount = IsCount Then
        IsArrayInArray = True
    End If
    
End Function

10 Comments

Why is that function so complex now? That's what I started from when trying to look for just one item in an array, and it didn't work correctly in each occasion, so it got reduced to what I provided in OP
The complexity is to make it readable (understandable). You can always use the one-liner: IsArrayInArray = Application.Count(Application.Match(IsArr, InArr, 0)) = UBound(IsArr) - LBound(IsArr) + 1.
Solution doesn't work
Could you share an example when it doesn't work (if the arrays are 2D, the solutions can easily be rewritten)?
Two issues: 1.) You have switched the arrays, it should be e.g. Debug.Print IsArrayInArray(LowerFilmWidth, LowerFilmWidthArray). 2.) You are writing the numbers as strings to LowerFilmWidth and comparing them to numbers in the other array: rather use LowerFilmWidth = Array(320, 420, 620).
|

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.