Ranking code with system reserved numbers (upgraded version needed) - VBA

kelly mort

Well-known Member
Joined
Apr 10, 2017
Messages
2,169
Office Version
  1. 2016
Platform
  1. Windows
This request is following the solution provided by @Akuini in post #35 at:


I just run into a problem and I will require your help to fix it.

I was previously dealing with whole numbers but now I am using both whole numbers and decimals.
Then when I run the code, it fails to give me the ranks for the floating point numbers. It produces blanks for all the decimal numbers.

So I changed the types of the variables z& to z# and Rnk& to Rnk# but the issue is still not resolved.

I have been staring at the screen since – but I can’t seem to fix it.
How do I get around with that?

This part of the code is storing the various numbers to be used like 100, 90, 75 etc.

Code:
ary = Split(Trim(SysScore))

The rest of the code is below. And this is the full code that I have been using for the ranking.
Code:
Sub RankSystem()
    Dim d As Object, m&, qr&, qq&, hh&, xq&, xz&, ary, i&
    
    Application.ScreenUpdating = False
    With Sheets("Data")
        qq = .Range("C" & Rows.Count).End(xlUp).Row
        For qr = 7 To qq
            m = WorksheetFunction.CountIf(.Range("C7:C" & qq), .Range("C" & qr))
           
                    ary = Split(Trim(SysScore))
                    ary = Application.Transpose(Application.Transpose(ary))
                    Set d = CreateObject("scripting.dictionary")
                    For i = 1 To UBound(ary)
                        d(CLng(ary(i))) = Empty
                    Next i
                    
                    Call toRank(qr, m, d, 4, 13, ary)
        
                    hh = 0
                    For xq = qr To qr + m - 1
                        xz = WorksheetFunction.CountA(.Range("D" & xq & ":" & "M" & xq))
                        If xz > hh Then hh = xz
                    Next xq
    
                    ary = Split(Trim(SysScore))
                    
                    For i = 0 To UBound(ary)
                        ary(i) = ary(i) * hh
                    Next i
                    
                    ary = Application.Transpose(Application.Transpose(ary))
                    Set d = CreateObject("scripting.dictionary")
                    For i = 1 To UBound(ary)
                        d(CLng(ary(i))) = Empty
                    Next i
                    Call toRank(qr, m, d, 14, 14, ary)
               
            qr = qr + m - 1
        Next qr
    End With
    Application.ScreenUpdating = True
End Sub

Code:
Sub toRank(qr&, m&, d As Object, a&, b&, ary)
    Dim i&, z#, N&, yy&, g&, arz, arb
    Dim e As Object, f As Object, c As Range, r As Range, ra As Range
    
    With Sheets("Data")
        For g = a To b
            Set r = .Cells(qr, g).Resize(m)
            yy = WorksheetFunction.CountA(r)
            i = 0
            If yy > 0 Then
                ReDim arb(1 To yy)
                For Each ra In r
                    If Len(ra) > 0 Then
                        i = i + 1
                        arb(i) = ra
                    End If
                Next ra
            Else
                GoTo skip:
            End If
        
            ReDim arz(1 To UBound(arb))
            For i = 1 To UBound(arb)
                arz(i) = WorksheetFunction.Large(arb, i)
            Next i
            N = arz(UBound(arz))
            Set e = CreateObject("scripting.dictionary")
            For i = 1 To UBound(arz)
                e(arz(i)) = e(arz(i)) + 1
            Next i
    
            Set f = CreateObject("scripting.dictionary")
            z = 1
            For i = ary(1) To N Step -1
                If d.exists(i) And Not e.exists(i) Then
                    z = z + 1
                End If
'
                If e.exists(i) Then
                    f(i) = z & GetSuffix(z)
                    z = z + e(i)
                End If
            Next i
    
            For Each c In .Cells(qr, g).Resize(m)
                If f.exists(c.Value) Then c.Offset(, 14) = f(c.Value)
            Next c
skip:
        Next g
    End With
End Sub

Function GetSuffix(Rnk#) As String
Dim sSuffix$
If Rnk Mod 100 >= 11 And Rnk Mod 100 <= 20 Then
sSuffix = " th"
Else
Select Case (Rnk Mod 10)
Case 1: sSuffix = " st"
Case 2: sSuffix = " nd"
Case 3: sSuffix = " rd"
Case Else: sSuffix = " th"
End Select
End If
GetSuffix = sSuffix
End Function
 

Excel Facts

Why does 9 mean SUM in SUBTOTAL?
It is because Sum is the 9th alphabetically in Average, Count, CountA, Max, Min, Product, StDev.S, StDev.P, Sum, VAR.S, VAR.P.
except those 3rd ranks which should have been 4th instead and the subsequent ones adjusted as well.
SysScore= "90 89 87"

1. Why 85.33 is rank 8, in syscore there is 87, so shouldn't it be rank 9?
2. There's 90 in SysScore and three 90 in the data, should we count there are four 90, so 89 get rank 8 not 7?

demo_workbook_for_ranking_code_amendment 1.xlsm
BCDEF
6N1RESULT
71931 st
82912 nd
92912 nd
104904 th
114904 th
124904 th
137897 th
14885.339 th
15983.510 th
16108311 th
171178.512 th
Sheet2
 
Upvote 0
Are you answering yes to both question?
Try this one:
VBA Code:
Sub RankSystem()
    Dim scA As Object, va, vb, vc, x
    Dim v As Long
    Application.ScreenUpdating = False
        SysScore = "90 89 87"
        qq = Range("C" & Rows.Count).End(xlUp).Row
        va = Range("C7", Cells(Rows.Count, "C").End(xlUp))
        
        Set scA = CreateObject("System.Collections.ArrayList")
    
        For Each x In va
            scA.Add CDbl(x)
        Next

        For Each x In Split((SysScore))
            scA.Add CDbl(x)
        Next
        
        scA.Sort
        scA.Reverse
        
        ReDim vb(1 To scA.Count, 1 To 2)
        i = 0
        
        For Each x In scA
            i = i + 1
            vb(i, 1) = x
        Next
        
        vb(1, 2) = 1 & " " & "st"
        v = 1
        For i = 2 To UBound(vb, 1)
            v = v + 1
            If vb(i, 1) = vb(i - 1, 1) Then
                vb(i, 2) = vb(i - 1, 2)
            Else
                vb(i, 2) = v & " " & GetSuffix(v)
                
            End If
        Next
                
        ReDim vc(1 To UBound(va, 1), 1 To 1)
        
        For i = 1 To UBound(va, 1)
            For j = 1 To UBound(vb, 1)
                If va(i, 1) = vb(j, 1) Then
                    vc(i, 1) = vb(j, 2)
                    Exit For
                End If
            Next
        Next
                
        Range("F7").Resize(UBound(vc, 1), 1) = vc
 
    Application.ScreenUpdating = True
End Sub

demo_workbook_for_ranking_code_amendment 1.xlsm
CDEF
6N1RESULT
7931 st
8912 nd
9912 nd
10904 th
11904 th
12904 th
13898 th
1485.3311 th
1583.512 th
168313 th
1778.514 th
187815 th
197716 th
2076.517 th
2176.517 th
227619 th
237619 th
245821 st
Sheet2
 
Upvote 0
2. There's 90 in SysScore and three 90 in the data, should we count there are four 90, so 89 get rank 8 not 7?
I want the 89 counted as 7 not 8 (only if it's possible that way)
 
Upvote 0
I want the 89 counted as 7 not 8 (only if it's possible that way)
Try:

Rich (BB code):
Sub RankSystem()
    Dim scA As Object, va, vb, vc, x
    Dim v As Long
    Application.ScreenUpdating = False
        SysScore = "90 89 87"
        qq = Range("C" & Rows.Count).End(xlUp).Row
        va = Range("C7", Cells(Rows.Count, "C").End(xlUp))
        
        Set scA = CreateObject("System.Collections.ArrayList")
    
        For Each x In va
            scA.Add CDbl(x)
        Next

        For Each x In Split((SysScore))
            If Not scA.contains(CDbl(x)) Then scA.Add CDbl(x)
        Next
        
        scA.Sort
        scA.Reverse
        
        ReDim vb(1 To scA.Count, 1 To 2)
        i = 0
        
        For Each x In scA
            i = i + 1
            vb(i, 1) = x
        Next
        
        vb(1, 2) = 1 & " " & "st"
        v = 1
        For i = 2 To UBound(vb, 1)
            v = v + 1
            If vb(i, 1) = vb(i - 1, 1) Then
                vb(i, 2) = vb(i - 1, 2)
            Else
                vb(i, 2) = v & " " & GetSuffix(v)
                
            End If
        Next
                
        ReDim vc(1 To UBound(va, 1), 1 To 1)
        
        For i = 1 To UBound(va, 1)
            For j = 1 To UBound(vb, 1)
                If va(i, 1) = vb(j, 1) Then
                    vc(i, 1) = vb(j, 2)
                    Exit For
                End If
            Next
        Next
                
        Range("F7").Resize(UBound(vc, 1), 1) = vc
 
    Application.ScreenUpdating = True
End Sub

demo_workbook_for_ranking_code_amendment 1.xlsm
CDEF
6N1RESULT
7931 st
8912 nd
9912 nd
10904 th
11904 th
12904 th
13897 th
1485.339 th
1583.510 th
168311 th
1778.512 th
187813 th
197714 th
2076.515 th
2176.515 th
227617 th
237617 th
245819 th
Sheet2
 
Upvote 0
Okay we are cool to move on with the switches x y z in column C.
 
Upvote 0
I am very grateful. Have wonderful time.

Tomorrow it is then.
 
Upvote 0
Ok, try this:
Note: Use this and "Function GetSuffix", you don't need "Sub toRank" anymore,
VBA Code:
Sub RankSystem()
    Dim scA As Object, d As Object
    Dim va, vb, vc, x, z
    Dim i As Long, a1 As Long, a2 As Long, h As Long, j As Long
    Dim SysScore

Application.ScreenUpdating = False
   
SysScore = "90 89 87"
Range("R5") = "SysScore: " & SysScore

va = Range("C7", Cells(Rows.Count, "C").End(xlUp))
    Set d = CreateObject("scripting.dictionary")

    For i = 1 To UBound(va, 1)

        z = va(i, 1)
        If Not d.Exists(z) Then
            d(z) = 1
            d(z & ":") = i
        Else
            d(z) = d(z) + 1
        End If
    Next
    
       
For Each z In d.keys
    
    If InStr(z, ":") = 0 Then
        a1 = d(z & ":") 'row as start of category, 7 is 1
        a2 = d(z)       'length
    End If
    
    For h = 4 To 14 'col D:N
        'if column has data
        If Columns(h).Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row > 6 Then
            va = Cells(6 + a1, h).Resize(a2)
            Set scA = CreateObject("System.Collections.ArrayList")
        
            For Each x In va
                If x <> "" Then scA.Add CDbl(x)
            Next
            
            For Each x In Split((SysScore))
                If IsNumeric(x) Then
                    If Not scA.contains(CDbl(x)) Then scA.Add CDbl(x)
                End If
            Next
            
            scA.Sort
            scA.Reverse
            
            ReDim vb(1 To scA.Count, 1 To 2)
            i = 0
            
            For Each x In scA
                i = i + 1
                vb(i, 1) = x
            Next
            
            vb(1, 2) = 1 & " " & "st"
            
            For i = 2 To UBound(vb, 1)
                If vb(i, 1) = vb(i - 1, 1) Then
                    vb(i, 2) = vb(i - 1, 2)
                Else
                    vb(i, 2) = i & " " & GetSuffix(i)
                End If
            Next
                    
            ReDim vc(1 To UBound(va, 1), 1 To 1)
            
            For i = 1 To UBound(va, 1)
                For j = 1 To UBound(vb, 1)
                    If va(i, 1) = vb(j, 1) Then
                        vc(i, 1) = vb(j, 2)
                        Exit For
                    End If
                Next
            Next
                    
            Cells(6 + a1, h + 14).Resize(UBound(vc, 1), 1) = vc
        
        End If
    Next
Next
    Application.ScreenUpdating = True
End Sub

Example:
demo_workbook_for_ranking_code_amendment 1.xlsm
ABCDEFGHIJKLMN
6IDNAMECATN1N2N3N4N5N6N7N8N9N10TOTAL
7354X9381838980.5886873655.5
8336X915937.55751.547.5646225494.5
9338X89675273.558786941.564.5592.5
10356X8569517257.5828053.566.5616.5
11339X76.55155.57260.570.57553.563.5578
1223X6484.5738779838765.576699
13361X6490909383.590908684.5771
14362X62.570.562.57468387465.571.5586.5
15341Y86776785.577768571.570.5695.5
16342Y7677.558.575.574.589795265647
17363Y8984.589838591856282750.5
18364Y918279.58675.581856277.5719.5
1930Z83.5747878.574836072603
20365Z7760657563.581754462602.5
2127Z76.577.566.58476.580.5814073655.5
2225Z7877.586.583.57978.58171.571.5707
23343Z7661.5558267.587776868642
2424a594938.556.551.567.5635466.5505.5
25366a88.57865.57074347253.573.5609
26344a67554962.551.562.56425436.5
Sheet5


RESULT:
demo_workbook_for_ranking_code_amendment 1.xlsm
RSTUVWXYZAAAB
5SysScore: 90 89 87
6RNK1RNK2RNK3RNK4RNK5RNK6RNK7RNK8RNK9RNK10RNK T
71 st5 th4 th3 rd5 th3 rd5 th6 th3 rd
82 nd9 th10 th9 th11 th8 th9 th8 th11 th8 th
94 th8 th8 th6 th9 th6 th8 th11 th9 th5 th
106 th7 th9 th7 th10 th5 th5 th9 th8 th4 th
117 th10 th7 th7 th8 th7 th6 th9 th10 th7 th
128 th4 th5 th4 th6 th4 th4 th6 th5 th2 nd
138 th1 st1 st1 st4 th1 st1 st4 th4 th1 st
1410 th6 th6 th5 th7 th9 th7 th6 th7 th6 th
155 th7 th5 th5 th5 th6 th4 th4 th6 th3 rd
166 th6 th6 th7 th7 th3 rd7 th7 th7 th4 th
173 rd4 th2 nd6 th4 th1 st4 th5 th4 th1 st
181 st5 th4 th4 th6 th5 th4 th5 th5 th2 nd
194 th6 th5 th5 th7 th4 th6 th5 th4 th
206 th8 th7 th7 th8 th4 th8 th7 th8 th5 th
217 th4 th6 th4 th6 th5 th5 th8 th4 th2 nd
225 th4 th4 th5 th4 th6 th5 th4 th6 th1 st
238 th7 th8 th6 th7 th3 rd7 th5 th7 th3 rd
246 th6 th6 th6 th5 th4 th6 th4 th5 th2 nd
253 rd4 th4 th4 th4 th6 th4 th5 th4 th1 st
265 th5 th5 th5 th5 th5 th5 th6 th3 rd
Sheet5
 
Upvote 0

Forum statistics

Threads
1,223,893
Messages
6,175,240
Members
452,621
Latest member
Laura_PinksBTHFT

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top