1

I'm creating an array from a text file and want to create a "subarray" from the main one.

The main array has the form

enter image description here

And I want to extract the A and B.

I create the "sub array" by splitting the strings from each row

For n = LBound(MainArray) To UBound(MainArray)
    If Split(MainArray(n), " ")(0) = "Data" Then
        ReDim SubArray(X)
        SubArray(X) = Split(MainArray(n), " ")(1)
        X = X + 1
    End If
Next n

but doing this just returns the array (written as a vector now) (" ", B).

Why does A get overwritten by an empty space after the for loop finds the B?

Thanks and Happy Easter!

Note the example above is just a minimalist version of the real array.

3
  • Please, better specify which to be the processing result: Another (sub array) starting from the "Data B" string? So many arrays as "Data x" exists? Or what? Then, is your MainArray a 1D array? Or a 2D, having rows (and one column)? How this MainArray has been loaded? Commented Apr 18, 2022 at 12:41
  • I would also suggest you to say something about your "real array". If you need a solution for a specific task, at least describe it as accurate as possible. I did not understand two well your question in relation with the code you show, so at least, try answering the clarification questions... Nobody want working on a piece of code not being sure that they will only waste their time. Commented Apr 18, 2022 at 13:04
  • Along the lines of what @FaneDuru is saying, I'm not getting at all what your array structure is, and not even 100% confident how many arrays we are dealing with. If we had example code with arrays defined and populated with a small set of data then we could understand what they are and how to manipulate them. Commented Apr 18, 2022 at 13:27

2 Answers 2

1

This answer is predicated on Main array being a single dimension array.

The problem you are having is that you are nott creating new sub arrays each time tou get a new 'Data xxx" and consequently just keep overwriting the previous subarray.

You will be better served in you endeavour by using a dictionary of dictionaries.

To use dictionaries you either have to add a reference to the Microsoft Scripting Runtime or use 'CreateObject("Scripting.Dicitonary"). The first option is preferred when developing code or when you are a newbie because you get intellisense. You don't get intellisense when you use late bound objects (created by CreateObject).

Scripting.Dictionaries should be preferred over collections with keys because Dictionaries allow you to retreive the Keys or Items as arrays in their own right.

Here is your code modified to use scripting Dictionaries

Dim myD As Scripting.Dictionary
Set myD = New Scripting.Dictionary

Dim mySubDName As String
mySubDName = "Unknown"

Dim myItem As Variant

For Each myItem In MainArray

    If InStr(myItem, "Data") > 0 Then
    
        mySubDName = Trim(myItem)
        If Not myD.exists(SubDName) Then
            ' Create a new sub dictionary with key 'Data XXXX'
            myD.Add mySubDName, New Scripting.Dictionary
            
        End If
        
    Else
    
        Dim myArray As Variant
        myArray = Split(Trim(myItem), " ")
        myD.Item(mySubDName).Add myArray(0), myArray(1)

    End If
    
Next

Dictionary myD will have Keys of "Data A", Data B" etc.

You retrieve a sub dictionary using

'Where XXXX is A,B,C etc
set mySubD = myD.Item("Data XXXX")

The sub dictionary has the structure (using 00000007 700 as an example) of Key=00000007 and Item = 700

If you enumerate a Dictionary using for each it returns the Key as the control variable.

You can get an array of the Keys using the .Keys method you can Get an array of the Items using the .Items Method

E.g. myD.Keys gives the array ("Data A", "Data B", "Data C", ....."Data XXX"

myD.Item("Data B").Items will give the array ("0000005", "0000006",.....,"00000010, etc"

Please do take the ttime to read up on Scripting.Dictionaries as part of understanding the above.

Good luck with your coding.

Sign up to request clarification or add additional context in comments.

Comments

1

Since you do not answer the clarification questions, please try the next code, which processes a 2D array, resulting two 2D arrays, corresponding to 'Data A' and 'Data B':

Sub Split2DArray()
 Dim MainArray, arrA, arrB, n As Long, iA As Long, iB As Long, boolFirst As Boolean
 
 'for exemplification place the picture content in A:A column, then place it in a (2D) array:
 MainArray = Range("A1:A13").value
 
 ReDim arrA(1 To 1, 1 To UBound(MainArray)): iA = 1
 ReDim arrB(1 To 1, 1 To UBound(MainArray)): iB = 1
 For n = LBound(MainArray) To UBound(MainArray)
    If MainArray(n, 1) <> "" Then
        If Split(MainArray(n, 1), " ")(0) = "Data" Then
            If Not boolFirst Then
                boolFirst = True
                arrA(1, iA) = MainArray(n, 1): iA = iA + 1
           Else
                boolFirst = False
                arrB(1, iB) = MainArray(n, 1): iB = iB + 1
           End If
        ElseIf boolFirst Then
            arrA(1, iA) = MainArray(n, 1): iA = iA + 1
        Else
            arrB(1, iB) = MainArray(n, 1): iB = iB + 1
        End If
    End If
Next n
If iA > 1 Then ReDim Preserve arrA(1 To 1, 1 To iA - 1) 'only the second dimension can be preserved
If iB > 1 Then ReDim Preserve arrB(1 To 1, 1 To iB - 1)

Range("C1").Resize(UBound(arrA, 2), 1).value = Application.Transpose(arrA)
Range("D1").Resize(UBound(arrB, 2), 1).value = Application.Transpose(arrB)
End Sub

The code can be easily adapted to process 1D arrays. If this is the case I can show you how to proceed. If many such 'Data x' slices exist, you should use a Dictionary keeping each array.

The same processing way for 1D arrays. Using the same visual elocvent way of testing:

Sub Split1DArray()
 Dim MainArray, arrA, arrB, n As Long, iA As Long, iB As Long, boolFirst As Boolean
 
 'for exemplification place the picture content in A:A column, then place it in a (2D) array:
 MainArray = Application.Transpose(Range("A1:A13").value) 'obtaining a 1D array from the same reange...
 
 ReDim arrA(1 To UBound(MainArray)): iA = 1
 ReDim arrB(1 To UBound(MainArray)): iB = 1
 For n = LBound(MainArray) To UBound(MainArray)
    If MainArray(n) <> "" Then
        If Split(MainArray(n), " ")(0) = "Data" Then
            If Not boolFirst Then
                boolFirst = True
                arrA(iA) = MainArray(n): iA = iA + 1
           Else
                boolFirst = False
                arrB(iB) = MainArray(n): iB = iB + 1
           End If
        ElseIf boolFirst Then
            arrA(iA) = MainArray(n): iA = iA + 1
        Else
            arrB(iB) = MainArray(n): iB = iB + 1
        End If
    End If
Next n
If iA > 1 Then ReDim Preserve arrA(1 To iA - 1) 'only the second dimension can be preserved
If iB > 1 Then ReDim Preserve arrB(1 To iB - 1)

Range("C1").Resize(UBound(arrA), 1).value = Application.Transpose(arrA)
Range("D1").Resize(UBound(arrB), 1).value = Application.Transpose(arrB)
End Sub

And a version using a dictionary, processing as many as `Data x' slices exist:

Sub Split1DArrayDict()
 Dim MainArray, n As Long, x As Long, arrIt, dict As Object
 
 'for exemplification place the picture content in A:A column, then place it in a (2D) array:
 MainArray = Application.Transpose(Range("A1:A18").value) 'obtaining a 1D array from the same range...
 
 Set dict = CreateObject("Scripting.Dictionary")
 For n = LBound(MainArray) To UBound(MainArray)
    If MainArray(n) <> "" Then
        If Split(MainArray(n), " ")(0) = "Data" Then
            x = x + 1
            dict.Add x, Array(MainArray(n))
            arrIt = dict(x)
        Else
            ReDim Preserve arrIt(UBound(arrIt) + 1)
            arrIt(UBound(arrIt)) = MainArray(n)
            dict(x) = arrIt
        End If
    End If
Next n

For n = 0 To dict.count - 1
    cells(1, 3 + n).Resize(UBound(dict.items()(n)) + 1, 1).value = Application.Transpose(dict.items()(n))
Next n
End Sub

Comments

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.