问题
I have a VBA code to return a Crew ID for a job completed, the total number of jobs that crew did, how many days that crew was working, and then return the average number of jobs per day. They are in no particular order and all of these categories are adjacent to each other in the excel spreadsheet. In a column next to these other categories, I want to write a VBA code to assign each row a value (1 to 10, since there are 10 crews) based on who has the highest number of jobs per day.
I have looked at other code and suggestions but all I can find is sorting. I don't want to sort them since I can easily do that in Excel and if I sort the values in VBA for that specific column, they will not line up with the rest of the information about them. Any suggestions on how I can "rank" these columns by printing the numbers 1 through 10 in the column adjacent based on who has the highest to lowest jobs per day average?
Thank you all for your help!
回答1:
I ripped this code out of Accounting Accrual - Invoicing true up Excel Application, it is one of many sorts on a data "field".
You can do something similar. To make this more clear for you to apply: wsBuild is a named sheet (in developer, you can call it directly regardless of worksheet name or position). "twb" just indicates that it is working in thisworkbook, as I am consolidating data from several workbooks (data exports, 3 in this case).
twbNameCol is the col number for the vendor name found in a different function
twbJobNumberCol is the col number for the sales order found in a different function
twbTot1Col is the col number for the sales amount found in a different function
If you want to find the headers dynamically just choose a number higher than your import template in a manner like this, this one accommodates for having 2 total column headers one for accrual and one for invoices, you may not to need to do something like this, since I export from a system I know the header names, or you can make your own, diff accrual is the last column I am looking to find the position on so I break the loop at that point:
twbTot1Col = 0
twbTot2Col = 0
'First let's define the column positions
For j = 1 To 50
If InStr(wsBuild.Cells(1, j), "Totals") > 0 And twbTot1Col = twbTot2Col Then
'It is the first time
twbTot1Col = j
ElseIf InStr(wsBuild.Cells(1, j), "Totals") > 0 And twbTot1Col <> twbTot2Col Then
twbTot2Col = j
ElseIf InStr(wsBuild.Cells(1, j), "JobNumber") > 0 Then
twbJobNumCol = j
ElseIf InStr(wsBuild.Cells(1, j), "New VAP") > 0 Then
twbNewVAPCol = j
ElseIf InStr(wsBuild.Cells(1, j), "New AP") > 0 Then
twbNewAPCol = j
ElseIf InStr(wsBuild.Cells(1, j), "Name") > 0 Then
twbNameCol = j
ElseIf InStr(wsBuild.Cells(1, j), "Diff Accrual") > 0 Then
twbDiffCol = j
j = 100 'Break loop
Else
'Do nothing
End If
Next j
twbLastRow is the last row in the data range (data range is 2 to LastRow)
It is found like this:
twbLastRow = wsBuild.Cells(Rows.Count, 1).End(xlUp).Row
Here is an example of the sort code, there are some column insertion steps prior to this 1, 2, 3, so I only copied the sort
With wsBuild
'4) Perform 3 line sort
.Sort.SortFields.Clear
.Sort.SortFields.Add Key:=.Range(.Cells(2, twbNameCol), .Cells(twbLastRow, twbNameCol)), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.Sort.SortFields.Add Key:=.Range(.Cells(2, twbJobNumCol), .Cells(twbLastRow, twbJobNumCol)), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.Sort.SortFields.Add Key:=.Range(.Cells(2, twbTot1Col), .Cells(twbLastRow, twbTot1Col)), _
SortOn:=xlSortOnValues, Order:=xlDescending, DataOption:=xlSortNormal
.Sort.SetRange .Range(.Cells(1, 1), .Cells(twbLastRow, twbDiffCol + 2))
.Sort.Header = xlYes
.Sort.MatchCase = False
.Sort.Orientation = xlTopToBottom
.Sort.SortMethod = xlPinYin
.Sort.Apply
End With
If you take a look at this, you can "rank" your data in any which way you would like. This sort is 1. vendor then 2. job number then 3. accrual amount then the funs begins to match up invoice import against the accruals. If you define your sort range properly you will not lose or mismtach any data in adjacent columns. I guess I am lobbying for you to use sort.
If you provide some code the answer could actually be a sort of your data, insert a rank column, put the ranks in, then unsort your data back to the way it was. Rather than running a function to "rank" based on a specific attribute (longer ..... but doable). Cheers, WWC
来源:https://stackoverflow.com/questions/50492674/rank-a-list-of-values-largest-to-smallest-using-vba