Search code examples
arraysvbams-accessrecordset

Implementing Excel VBA code utilising Arrays into Access VBA code utilising Recordsets


to prefix, I am incredibly new to VBA (around 1 month on/off experience). I managed to write some code to aggregate lines in an array based on certain conditions, which would then be implemented into some code in an access database. Much to my demise, when trying to implement, I quickly learned that Excel VBA and Access VBA do not work the same way, and I am having trouble trying to replace the array reference with a recordset reference. Any help would be appreciated.

Here is a snippet of my placeholder data, which will then be fed from access with the same columns: Placeholder Dataset

Below is the code in excel VBA I used to filter for unqiue portfolio numbers and aggregating all lines with the same portfolio number. Currently the output has one line with the correct "Min" (the "Max" is set to 100), and a second line with the correct "Max" (the "Min" is set to 0). These need to be combined, to have one line with the correct min and max, deleting any other lines with the same portfolio number:

Sub RemDup()

    Dim raw_array, unq_array, temp, min_wght, max_wght, temp2, site_name, asset_class, neutral, class_weight, min_raw, max_raw As Variant
    Dim c_row, c_row2, r_length, c_length, unq_row, unq_row2 As Long
    
    'Placeholder. The data for raw_array should come from an acces recordset.
    raw_array = ThisWorkbook.Sheets("Sheet1").Range("A1").CurrentRegion.Value
    unq_array = ThisWorkbook.Sheets("Sheet1").Range("A1:G1").Value

    'Main part 1 of code. Filter unique values and place into second array
    For c_row = LBound(raw_array, 1) To UBound(raw_array, 1)
        site_name = raw_array(c_row, 1)
        temp = raw_array(c_row, 2)
        asset_class = raw_array(c_row, 3)
        min_wght = raw_array(c_row, 4)
        max_wght = raw_array(c_row, 5)
        neutral = raw_array(c_row, 6)
        class_weight = raw_array(c_row, 7)
        
        For c_row2 = LBound(unq_array, 1) To UBound(unq_array, 1)
            If Not temp = unq_array(c_row2, 2) Then
                GoTo skipsubloop
            Else
                GoTo skiploop
            End If
skipsubloop:
        Next c_row2
        r_length = UBound(unq_array, 1)
        c_length = UBound(unq_array, 2)
        unq_array = Application.Transpose(unq_array)
        ReDim Preserve unq_array(1 To c_length, 1 To r_length + 1)
        unq_array = Application.Transpose(unq_array)
        unq_array(r_length + 1, 1) = site_name
        unq_array(r_length + 1, 2) = temp
        unq_array(r_length + 1, 3) = asset_class
        unq_array(r_length + 1, 4) = min_wght
        unq_array(r_length + 1, 5) = max_wght
        unq_array(r_length + 1, 6) = neutral
        unq_array(r_length + 1, 7) = class_weight
skiploop:
    Next c_row

    'Main part 2 of code. Use unique values to aggregate rows according to certain condition.
    For unq_row = LBound(unq_array, 1) + 1 To UBound(unq_array, 1)
        temp2 = unq_array(unq_row, 2)
        
        For unq_row2 = LBound(raw_array, 1) + 1 To UBound(raw_array, 1)
            If temp2 = raw_array(unq_row2, 2) Then
                min_raw = raw_array(unq_row2, 4)
                max_raw = raw_array(unq_row2, 5)
                unq_array(unq_row, 4) = WorksheetFunction.Max(min_raw, unq_array(unq_row, 4))
                unq_array(unq_row, 5) = WorksheetFunction.Min(max_raw, unq_array(unq_row, 5))
            End If
        Next unq_row2
    Next unq_row
    
End Sub

the then looks something like this: Output data

I know effectively nothing about SQL and Access. I'm not looking for someone to translate the whole code for me, I'm just struggling to see where to even start with the process, or if my approach is completely wrong. Even some pointers would be appreciated, or perhaps even knowing if this is out of the scope for a beginner would help.

Thank everyone in advance!


Solution

  • Added - since your source data is in Access you can just use SQL for the rollup. Something like:

    select sitename, portfolio, assetclass, Min([Min]) as minVal,
           Max([Max]) as maxVal, Neutral, Weight 
    from tablename 
    group by  sitename, portfolio, assetclass, Neutral, Weight
    

    Without really addressing the bigger picture of what it means to move from Excel to Access...

    Since you're only using Transpose as a workaround so you can resize unq_array, you can instead do that directly using a Function:

    Sub tester()
        Dim arr
        arr = Range("A1:D5").Value 'Testing this in excel...
        Debug.Print UBound(arr, 1) '5
        arr = AddRows(arr)
        Debug.Print UBound(arr, 1) '6
    End Sub
    
    'Resize first dimension of 2D array `arr` by `numrows`
    Function AddRows(arr, Optional numrows As Long = 1)
        Dim newArr, r As Long, c As Long
        ReDim newArr(1 To UBound(arr, 1) + numrows, 1 To UBound(arr, 2))
        For r = 1 To UBound(arr, 1)
            For c = 1 To UBound(arr, 2)
                newArr(r, c) = arr(r, c)
            Next c
        Next r
        AddRows = newArr
    End Function
    

    Transpose:

    'transpose a 2D array
    Function MyTranspose(arr)
        Dim newArr, r As Long, c As Long, lbc As Long, lbr As Long, ubc As Long, ubr As Long
        lbr = LBound(arr, 1): ubr = UBound(arr, 1)
        lbc = LBound(arr, 2): ubc = UBound(arr, 2)
        ReDim newArr(lbc To ubc, lbr To ubr)
        For r = lbr To ubr
            For c = lbc To ubc
                newArr(c, r) = arr(r, c) 'transpose
            Next c
        Next r
        MyTranspose = newArr
    End Function