Home > Back-end >  Getting only the values base on a list
Getting only the values base on a list

Time:07-06

My code below gives me a result with a unique customer codes base on Calculation sheet. However, I want to get my result base on the list that I have in Solution Sheet. Also want to run the macro within Solution Sheet. Any help will be appreciated.

Calculation Sheet

enter image description here

Solution Sheet

enter image description here

Sub cTotals()

Dim arr, arr2, arr3
Dim Calc As Worksheet: Set TS = Worksheets("Calculation")
Dim Sol As Worksheet: Set Sol = Worksheets("Solution")
Dim x As Long, i As Long, a As Long, c As Long, ct As Long
Dim GIVMM As Single, MSU As Double, Cases As Double
    
    
arr = Calc.Range("B2:H" & Cells(Rows.Count, 1).End(xlUp).Row)
arr2 = arr
With CreateObject("Scripting.Dictionary")
For x = LBound(arr) To UBound(arr)
    If Not IsMissing(arr(x, 1)) Then .Item(arr(x, 1)) = 1
Next
arr = .Keys
End With
ReDim arr3(1 To UBound(arr)   1, 1 To 7)
c = 1: ct = 1
For i = 0 To UBound(arr)
    For a = 1 To UBound(arr2)
        If arr2(a, 1) = arr(i) Then
            arr3(i   1, c) = arr(i)
            arr3(i   1, c   1) = ct
            ct = ct   1
            GIVMM = GIVMM   arr2(a, 5)
            arr3(i   1, c   2) = GIVMM
            MSU = MSU   arr2(a, 6)
            arr3(i   1, c   3) = MSU
            Cases = Cases   arr2(a, 7)
            arr3(i   1, c   4) = Cases
        End If
    Next
    ct = 1: GIVMM = 0: MSU = 0: Cases = 0
Next
Sol.Range("B6").Resize(UBound(arr3, 1), UBound(arr3, 2)) = arr3

End Sub

CodePudding user response:

Using Data Structures (Array, Collection, Dictionary)

Option Explicit

Sub CalculateData()
    
    ' Define constants.
    
    ' Source
    Const sName As String = "Calculation"
    Const scCol As Long = 2
    Dim sCols() As Variant: sCols = VBA.Array(4, 6, 7, 8)
    ' Destination
    Const dName As String = "Solution"
    Const dfRow As Long = 6
    Const dcCol As Long = 2
    Const dColumnOffset As Long = 1
    Dim dOffsets() As Variant: dOffsets = VBA.Array(1, 2, 3, 4)
    ' Reference the workbook ('wb').
    Dim wb As Workbook: Set wb = ThisWorkbook
    
    ' Write the values from the source range ('srg') to an array ('sData').
    Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
    Dim srg As Range: Set srg = sws.Range("A1").CurrentRegion
    Dim sData() As Variant: sData = srg.Value
    Dim srCount As Long: srCount = srg.Rows.Count
    
    ' Write the unique source values to the 'keys' ('sString')
    ' of a dictionary ('sDict'). Its 'items' ('sDict(sString)') will hold
    ' a collection of all the (source) rows ('r') where the 'key' appeared.
    
    Dim sDict As Object: Set sDict = CreateObject("Scripting.Dictionary")
    sDict.CompareMode = vbTextCompare
    
    Dim sString As String
    Dim r As Long
    
    For r = 2 To srCount
        sString = CStr(sData(r, scCol))
        If Len(sString) > 0 Then
            If Not sDict.Exists(sString) Then
                Set sDict(sString) = New Collection
            End If
            sDict(sString).Add r
        End If
    Next r
    
    ' Write the values from the destination lookup column range ('dlrg')
    ' to a 2D one-based (one-column) array ('dlData').
    
    Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
    Dim dlRow As Long: dlRow = dws.Cells(dws.Rows.Count, dcCol).End(xlUp).Row
    Dim drCount As Long: drCount = dlRow - dfRow   1
    
    If drCount < 1 Then
        MsgBox "No data in the destination column.", vbCritical
        Exit Sub
    End If
    
    Dim dlrg As Range: Set dlrg = dws.Cells(dfRow, dcCol).Resize(drCount)
    
    Dim dlData() As Variant
    
    If drCount = 1 Then ' one cell
        ReDim dlData(1 To 1, 1 To 1): dlData(1, 1) = dlrg.Value
    Else ' multiple cells
        dlData = dlrg.Value
    End If
    
    ' Write the results to the destination array ('dData').
    
    Dim cUpper As Long: cUpper = UBound(sCols)
    Dim cCount As Long: cCount = cUpper   1
    
    Dim dData As Variant: ReDim dData(1 To drCount, 1 To cCount)
    
    Dim dDict As Object: Set dDict = CreateObject("Scripting.Dictionary")
    dDict.CompareMode = vbTextCompare
    
    Dim sItem As Variant
    Dim sValue As Variant
    Dim dString As String
    Dim c As Long
    
    For r = 1 To drCount
        dString = CStr(dlData(r, 1))
        If Len(dString) > 0 Then
            If sDict.Exists(dString) Then ' found in the dictionary
                For Each sItem In sDict(dString) ' loop through the rows
                    For c = 0 To cUpper
                        If c = 0 Then ' unique count
                            sString = CStr(sData(sItem, sCols(c)))
                            dDict(sString) = Empty
                        Else ' sum
                            sValue = sData(sItem, sCols(c))
                            If VarType(sValue) = vbDouble Then ' is a number
                                dData(r, c   1) = dData(r, c   1)   sValue
                            'Else ' is not a number; do nothing
                            End If
                        End If
                    Next c
                Next sItem
                dData(r, 1) = dDict.Count
                dDict.RemoveAll
            ' Else ' not found in the dictionary; do nothing
            End If
        ' Else ' vbNullString ('""'); do nothing
        End If
    Next r
        
    ' Write the values from the destination array to the destination range.
        
    With dws.Cells(dfRow, dcCol).Offset(, dColumnOffset)
        .Resize(drCount, cCount).Value = dData
    End With
    
    ' Inform.
    MsgBox "Data calculated.", vbInformation
    
End Sub
  • Related