0

I have a data set where I need to compare the first number in each transect against each other.

For example, in the below data set I need to compare cells D2, D7, D12 and D17 and assign a value based on which one is the smallest number, the next smallest and so on. This will be used to assign the transect numbers in column A.

data set

My issue is that the number of sections (in this example 4) and the number of transects (also 4 in this example) will vary. So the cells I need to compare will change. I have written the code that calculates the number of transects, which is:

Dim tlength As Worksheet
Dim tb As Long *'tb=transect break*

Sub tlength_start_stop_coords()

Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("sheet1")
Set tlength = ThisWorkbook.Worksheets("transect lengths") *' assigns the sheet to a variable 
 for efficient coding*

tb = 0 *'counter to calculate the number of transects*
j = 2 *'counter for row*
Lastrow = Lastrow + 1 *'add a row to last row so that the last row includes a blank line.*
*'the following for loop is used to calculate the number of transects*

For i = 2 To Lastrow
   If tlength.Range("D" & i) = vbNullString Then
     If tlength.Range("D" & i - 1) <> vbNullString Then
       tb = tb + 1 *'updates the counter*
     End If
   End If
Next i
tbtotal = tb *'stores the total counter in variable tbtotal for later use*

I think I may need to use a loop. But I am stuck trying to figure out how to manage the unknown number of comparisons in changing cell locations.

The desired result is in the below screenshot of the expected outcome, with results in column A. To begin with, I only need to get the number for the first row of each transect. Once I have that, I can copy using xldown. Expected outcome:

enter image description here

Another possible data set and outcome expected might be:

enter image description here with an expected outcome of:

enter image description here

GlennW
  • 1
  • 1
  • Could you share a screenshot that shows the expected output in column `A`? – VBasic2008 Aug 01 '22 at 10:06
  • In your `For` loop you have both `i` (as the loop counter), and `j` (which never changes) – Tim Williams Aug 01 '22 at 16:33
  • @VBasic2008 - I have added the expected outcome in the post. Hope it helps – GlennW Aug 02 '22 at 01:47
  • Thanks @TimWilliams . The above code so far only calculates how many transects I have. I still need to be able to assign each number 1 to tbtotal based on the first value (lowest to highest) in the Latitude column (column D) for each transect. – GlennW Aug 02 '22 at 02:13
  • "assign a value based on which one is the smallest number" - I don't see how that plays out in your results screenshot? – Tim Williams Aug 02 '22 at 02:33

1 Answers1

1

Worked for me using your second set of sample data:

Sub Tester()
    
    Dim tlength As Worksheet, i As Long, tNum As Long, v, vPrev, arr
    Dim col As New Collection, e, c As Range, rng As Range
    
    Set tlength = ThisWorkbook.Worksheets("transect lengths")
    
    'collect all the Section 1 Latitudes and row numbers
    For i = 2 To tlength.Cells(Rows.Count, "B").End(xlUp).Row
        If tlength.Cells(i, "B") = 1 Then
            col.Add Array(i, tlength.Cells(i, "D").Value) 'store start row and first Latitude
        End If
    Next i
    
    SortCollection col, 2 'sort collection by second element in each array
    
    tNum = 0
    'loop over the sorted collection and assign the order of the transects
    For Each e In col
        tNum = tNum + 1
        Set c = tlength.Cells(e(0), "B")
        'following assumes all transects have at least 2 sections...
        tlength.Range(c, c.End(xlDown)).Offset(0, -1).Value = tNum
    Next e
     
End Sub

'Sort a collection of 0-based arrays in ascending order by the n'th element of each array
'Adapted from https://stackoverflow.com/a/3588073/478884
Sub SortCollection(col As Collection, n As Long)
    Dim i As Long, j As Long, vTemp As Variant
    For i = 1 To col.Count - 1 'Two loops to bubble sort
        For j = i + 1 To col.Count
            If col(i)(n - 1) < col(j)(n - 1) Then  'change to > for ascending sort
                vTemp = col(j)                     'store the lesser item
                col.Remove j                       'remove the lesser item
                col.Add Item:=vTemp, before:=i     're-add the lesser item before the greater Item
            End If
        Next j
    Next i
End Sub
Tim Williams
  • 154,628
  • 8
  • 97
  • 125
  • Hi @TimWilliams , the code doesn't really do want I need it to do. Your code starts column A from 1 and then counts up. The number in column A needs to be based on the values in Column D, and rank the transect number based on lowest to highest for section 1 of each transect, which means cells A2 will not always be 1. Code needs to dynamic to compare cells in Latitude column for each section 1 of the transect. I have edit my original post to show an example of another possible data set with outcome. Regards, Glenn – GlennW Aug 02 '22 at 23:11
  • OK -see updated answer above – Tim Williams Aug 03 '22 at 00:13
  • Thanks @TimWilliams , the code works well. I tested it against various scenarios and it does exactly what is intended. I thought the solution may have required using an array, though I am new to VBA an not experienced with arrays as yet. I understand most of the steps in your code. I think I would be able to understand arrays better if I was able to see a visual of the array and the items stored in it as I Step Into the code. Thanks again. – GlennW Aug 03 '22 at 01:44
  • You can use the Watch window for that - put a Watch on `col` and you can look at its contents at any breakpoint. FYI you could also use a 2D array instead of a collection of arrays, but using the collection avoids the need to manage the array re-sizing as you fill the array. – Tim Williams Aug 03 '22 at 06:02