Index column header where max count of values in columns occurs - excel-formula

I have a table with nine columns and twenty rows. I am trying to id which column header has the max count of fields below it where the values are greater than or equal to a specified number. The table range is J4:R23. The specified number is B6. J4:R4 contains the header that i am trying to match. Any thoughts on formula to obtain the appropriate column header? Thanks!

This thing barely fits, certainly not the best solution but should work jus fine:
=IF(SUMIFS($J$5:$J$23;">"&$B$6)=MAX(
SUMIFS($J$5:$J$23;">"&$B$6);
SUMIFS($K$5:$K$23;">"&$B$6);
SUMIFS($L$5:$L$23;">"&$B$6);
SUMIFS($M$5:$M$23;">"&$B$6);
SUMIFS($N$5:$N$23;">"&$B$6);
SUMIFS($O$5:$O$23;">"&$B$6);
SUMIFS($P$5:$P$23;">"&$B$6);
SUMIFS($Q$5:$Q$23;">"&$B$6);
SUMIFS($R$5:$R$23;">"&$B$6));$J$4;
IF(SUMIFS($K$5:$K$23;">"&$B$6)=MAX(
SUMIFS($J$5:$J$23;">"&$B$6);
SUMIFS($K$5:$K$23;">"&$B$6);
SUMIFS($L$5:$L$23;">"&$B$6);
SUMIFS($M$5:$M$23;">"&$B$6);
SUMIFS($N$5:$N$23;">"&$B$6);
SUMIFS($O$5:$O$23;">"&$B$6);
SUMIFS($P$5:$P$23;">"&$B$6);
SUMIFS($Q$5:$Q$23;">"&$B$6);
SUMIFS($R$5:$R$23;">"&$B$6));$K$4;
IF(SUMIFS($L$5:$L$23;">"&$B$6)=MAX(
SUMIFS($J$5:$J$23;">"&$B$6);
SUMIFS($K$5:$K$23;">"&$B$6);
SUMIFS($L$5:$L$23;">"&$B$6);
SUMIFS($M$5:$M$23;">"&$B$6);
SUMIFS($N$5:$N$23;">"&$B$6);
SUMIFS($O$5:$O$23;">"&$B$6);
SUMIFS($P$5:$P$23;">"&$B$6);
SUMIFS($Q$5:$Q$23;">"&$B$6);
SUMIFS($R$5:$R$23;">"&$B$6));$L$4;
IF(SUMIFS($M$5:$M$23;">"&$B$6)=MAX(
SUMIFS($J$5:$J$23;">"&$B$6);
SUMIFS($K$5:$K$23;">"&$B$6);
SUMIFS($L$5:$L$23;">"&$B$6);
SUMIFS($M$5:$M$23;">"&$B$6);
SUMIFS($N$5:$N$23;">"&$B$6);
SUMIFS($O$5:$O$23;">"&$B$6);
SUMIFS($P$5:$P$23;">"&$B$6);
SUMIFS($Q$5:$Q$23;">"&$B$6);
SUMIFS($R$5:$R$23;">"&$B$6));$M$4;
IF(SUMIFS($N$5:$N$23;">"&$B$6)=MAX(
SUMIFS($J$5:$J$23;">"&$B$6);
SUMIFS($K$5:$K$23;">"&$B$6);
SUMIFS($L$5:$L$23;">"&$B$6);
SUMIFS($M$5:$M$23;">"&$B$6);
SUMIFS($N$5:$N$23;">"&$B$6);
SUMIFS($O$5:$O$23;">"&$B$6);
SUMIFS($P$5:$P$23;">"&$B$6);
SUMIFS($Q$5:$Q$23;">"&$B$6);
SUMIFS($R$5:$R$23;">"&$B$6));$N$4;
IF(SUMIFS($O$5:$O$23;">"&$B$6)=MAX(
SUMIFS($J$5:$J$23;">"&$B$6);
SUMIFS($K$5:$K$23;">"&$B$6);
SUMIFS($L$5:$L$23;">"&$B$6);
SUMIFS($M$5:$M$23;">"&$B$6);
SUMIFS($N$5:$N$23;">"&$B$6);
SUMIFS($O$5:$O$23;">"&$B$6);
SUMIFS($P$5:$P$23;">"&$B$6);
SUMIFS($Q$5:$Q$23;">"&$B$6);
SUMIFS($R$5:$R$23;">"&$B$6));$O$4;
IF(SUMIFS($P$5:$P$23;">"&$B$6)=MAX(
SUMIFS($J$5:$J$23;">"&$B$6);
SUMIFS($K$5:$K$23;">"&$B$6);
SUMIFS($L$5:$L$23;">"&$B$6);
SUMIFS($M$5:$M$23;">"&$B$6);
SUMIFS($N$5:$N$23;">"&$B$6);
SUMIFS($O$5:$O$23;">"&$B$6);
SUMIFS($P$5:$P$23;">"&$B$6);
SUMIFS($Q$5:$Q$23;">"&$B$6);
SUMIFS($R$5:$R$23;">"&$B$6));$P$4;
IF(SUMIFS($Q$5:$Q$23;">"&$B$6)=MAX(
SUMIFS($J$5:$J$23;">"&$B$6);
SUMIFS($K$5:$K$23;">"&$B$6);
SUMIFS($L$5:$L$23;">"&$B$6);
SUMIFS($M$5:$M$23;">"&$B$6);
SUMIFS($N$5:$N$23;">"&$B$6);
SUMIFS($O$5:$O$23;">"&$B$6);
SUMIFS($P$5:$P$23;">"&$B$6);
SUMIFS($Q$5:$Q$23;">"&$B$6);
SUMIFS($R$5:$R$23;">"&$B$6));$Q$4;
IF(SUMIFS($Q$5:$Q$23;">"&$B$6)=MAX(
SUMIFS($J$5:$J$23;">"&$B$6);
SUMIFS($K$5:$K$23;">"&$B$6);
SUMIFS($L$5:$L$23;">"&$B$6);
SUMIFS($M$5:$M$23;">"&$B$6);
SUMIFS($N$5:$N$23;">"&$B$6);
SUMIFS($O$5:$O$23;">"&$B$6);
SUMIFS($P$5:$P$23;">"&$B$6);
SUMIFS($Q$5:$Q$23;">"&$B$6);
SUMIFS($R$5:$R$23;">"&$B$6));$R$4;
"Error in process"
)
)
)
)
)
)
)
)
)
See my attached file (replacing and copying may have corrupted the formula).

I made a VBA function too, it's redundant and so on but here it is:
Public Function FINDHEADERWHEREMAXCOUNTIFS(Target As Range, Condition As Double)
Dim rng As Range
NumCols = Target.Columns.Count 'counts how many header values we can choose of
Dim Headers() 'defines separate arrays for headers and values (turned out to be obsolete, see variable x)
ReDim Headers(1 To NumCols)
Dim ValuesArr()
ReDim ValuesArr(1 To NumCols)
HeaderRow = Target.Row 'row in which headers are located
LastRow = HeaderRow + Target.Rows.Count - 1 'last row with values
FirstColumn = Target.Column 'first column with values
LastColumn = FirstColumn + Target.Columns.Count - 1 'last column with values
For k = FirstColumn To LastColumn 'for each column
i = i + 1 'set array position
Headers(i) = Cells(HeaderRow, k).Value2 'set the corresponding header
For Each rng In Range(Cells(HeaderRow, k), Cells(LastRow, k)) 'for each value
If rng.Row <> HeaderRow Then 'I mean value, not header
If rng.Value2 > Condition Then ValuesArr(i) = ValuesArr(i) + 1 'if it's higher than the condition then count
End If
Next
Next
x = 1 'default is the first header
For j = 1 To NumCols 'for each header
If ValuesArr(j) > ValuesArr(x) Then x = j 'if the corresponding value is larger then standard then change the current one to standard
Next
FINDHEADERWHEREMAXCOUNTIFS = Headers(x) 'the standard value's corresponding header is the output
End Function

Related

Excel search and copy from more sheet

I have a file.xls with three sheets.
Sheet1, 2 columns, 3000 rows;
ColumnA: location_id
ColumnB: location_label
Sheet2, 2 columns, 5000 rows;
ColumnA: location_id
ColumnB: screen_id
Sheet3, 2 columns, 6000 rows;
ColumnA: screen_id
ColumnB: screen_name
how to group data into a new sheet4 with the following syntax (view image);
ColumnA: Location_label
ColumnB: screen_name
location_id get location_label name in sheet 1, location_id get screen_id value in sheet2, screen_id get screen_name value in sheet3 and in sheet4 result with location_label and screen_name.
#EDIT QUESTION WITH USE VLOOKUP;
I tried to use VLOOKUP but from error after the first id number 19 of sheet2...i have used this '
=VLOOKUP(Sheet2!A2;Sheet1!A2:B2133;2;)
i get
RED
GREEN
YELLOW
#N/D
#N/D
Public Sub pair_value()
'here i tried to deconstruct the code so it is easy to follow
'this type of paring would work much better with access
'you can use this code to start
Dim h1 As Integer 'row count in sheet1
Dim h2 As Integer 'row count in sheet2
Dim h3 As Integer 'row count in sheet3
Dim h4 As Integer 'row count in sheet4
Dim ar1() As Variant
Dim ar2() As Variant
Dim ar3() As Variant
Dim ar4() As Variant
Dim pair1() As Variant
Dim range1 As Range
Dim range2 As Range
Dim range3 As Range
Dim i As Integer
Dim j As Integer
'---------------------------------------------------
'This exercise would be so much easier using ACCESS
'---------------------------------------------------
'number of rows in each sheets
h1 = Worksheets(1).Cells(Rows.Count, 1).End(xlUp).Row
h2 = Worksheets(2).Cells(Rows.Count, 1).End(xlUp).Row
h3 = Worksheets(3).Cells(Rows.Count, 1).End(xlUp).Row
h4 = Worksheets(4).Cells(Rows.Count, 1).End(xlUp).Row
'define arrays
ReDim ar1(h1, 2)
ReDim ar2(h2, 2)
ReDim ar3(h3, 2)
ReDim pair1(h2, 2)
'set range
Set range1 = Worksheets(1).Range(Worksheets(1).Cells(2, 1), Worksheets(1).Cells(h1, 2))
Set range2 = Worksheets(2).Range(Worksheets(2).Cells(2, 1), Worksheets(2).Cells(h2, 2))
Set range3 = Worksheets(3).Range(Worksheets(3).Cells(1, 1), Worksheets(3).Cells(h3, 2))
'load range into arrays
ar1 = range1
ar2 = range2
ar3 = range3
'associate location_label to screen_id using location_id as primary key
For i = 1 To UBound(ar2)
For j = 1 To UBound(ar1)
If ar2(i, 1) = ar1(j, 1) Then
'load screen id + label in pair1 in pair1 array
pair1(i, 1) = ar2(i, 2)
pair1(i, 2) = ar1(j, 2)
End If
Next j
Next i
'associate location_label to screen_name using screen_id as primary key
For i = 1 To UBound(ar3)
For j = 1 To UBound(pair1)
If ar3(i, 1) = pair1(j, 1) Then
Debug.Print j
'past results in sheets(4)
h4 = Worksheets(4).Cells(Rows.Count, 1).End(xlUp).Row
Worksheets(4).Cells(h4 + 1, 1).Value = pair1(j, 2)
Worksheets(4).Cells(h4 + 1, 2).Value = ar3(i, 2)
End If
Next j
Next i
End Sub
Well I'm not the best with Excel and I do not fully understand what you want as an end result. But here is my guess what I think is the problem.
I suspect that in sheet 4 you type you code in A2 and use your mouse to drag the formula to the bottom of the column. If this is the case, your formula will not be exactly the same in every cell, because your matrix in the formula will change while you drag your mouse. Therefore the error #N/D
To prevent your matrix from changing while dragging your mouse you should use '$'.
So your formula would be:
=VLOOKUP(Sheet2!A2;Sheet1!$A$2:$B$2133;2;)
Possibly a tip:
I see you have the same columns in more than 1 sheet. You can put all you data in 1 sheet and then use filters to select the data you want. See this article.

VBA - How to use multiple criteria from a range with wildcards, for autofilter

I need to filter some values of a sheet, and these values that I need to filter is in a table, but this one is dynamic, sometimes there's only one value, or two,three... Ex: Today i'll be ' ABC - CBA - DDA ' , and tomorrow ' DNC - AB '. Here is my code of filters that I also need to use with this:
totrow = Range("A1").End(xlDown).Row
Range(Cells(1, 1), Cells(1, 9)).AutoFilter
Range(Cells(1, 6), Cells(totrow, 6)).Select
ActiveSheet.Range(Cells(1, 6), Cells(totrow, 6)).AutoFilter Field:=6, Criteria1:="816"
ActiveSheet.Range(Cells(1, 2), Cells(totrow, 2)).AutoFilter Field:=2, Criteria1:="RWK"
'**here goes the other filters**
Suppose we have set of data that we want to filter:
and we also have a column/range with values we want to use as filter (Column N).
If the values always are the same, we can use in our filtering a hard coded array:
.AutoFilter Field:=8, Criteria1:=Array("ABC - CBA - DDA", "DNC - AB")
However, if the values or range are changing, we need to create a dynamic array that loops through our range and store the values as an array.
'Create an array to store the values to filter on
ReDim aCritVal(0 To lrow_crit) As Variant 'Create an array variable "aCritVal" to store the Criteria Value we want to use as filter
i = 0 'Array index starts at 0
For Each CellVal In ws.Range(ws.Cells(3, "N"), ws.Cells(lrow_crit, "N")) 'Range to loop through where Criteria Values exists
'Debug.Print CellVal.Value 'Checks the cell value that will be stored in Array: aCritVal
aCritVal(i) = CellVal.Value 'Store the value in array
i = i + 1 'Add one to next loop
Next CellVal
ReDim Preserve aCritVal(i - 1) 'Resize the array to only contain the values we need
Then we can substitute the array from:
Criteria1:=Array("ABC - CBA - DDA", "DNC - AB") -> Criteria1:=aCritVal
We can also add additional filtering steps to our filter section.
With the code below, where we use 3 filtering (1 array + 2 additional criteria's) we will get:
Code:
Option Explicit
Sub auto_filter_from_critera_range()
Dim lrow_filter As Long
Dim lcol_filter As Long
Dim lrow_crit As Long
Dim i As Long
Dim CellVal As Variant
Dim MyRangeFilter As Range
Dim ws As Worksheet
Set ws = ActiveWorkbook.Worksheets("Sheet1") 'Set the worksheet name
lrow_crit = ws.Cells(Rows.Count, "N").End(xlUp).Row 'Find last row in criteria table, in Sheet1
lrow_filter = ws.Cells(Rows.Count, "A").End(xlUp).Row 'Find last row for filter, in Sheet1
lcol_filter = ws.Cells(1, Columns.Count).End(xlToLeft).Column 'Find last column for filter, Sheet1
'Create an array to store the values to filter on
ReDim aCritVal(0 To lrow_crit) As Variant 'Create an array variable "aCritVal" to store the Criteria Value we want to use as filter
i = 0 'Array index starts at 1
For Each CellVal In ws.Range(ws.Cells(3, "N"), ws.Cells(lrow_crit, "N")) 'Range to loop through where Criteria Values exists
'Debug.Print CellVal.Value 'Checks the cell value that will be stored in Array: aCritVal
aCritVal(i) = CellVal.Value 'Store the value in array
i = i + 1 'Add one to next loop
Next CellVal
ReDim Preserve aCritVal(i - 1) 'Resize the array to only contain the values we need
If ws.AutoFilterMode Then ws.AutoFilterMode = False 'If autofilter exists then remove autofilter
Set MyRangeFilter = ws.Range(ws.Cells(1, 1), ws.Cells(lrow_filter, lcol_filter)) 'Define the range to apply autofilter
' MyRangeFilter.Select 'Select the range to filter, might be needed in some instances
With MyRangeFilter
'.AutoFilter Field:=8, Criteria1:=Array("ABC - CBA - DDA", "DNC - AB"), Operator:=xlFilterValues '"Normal" array that can be used if we have fixed criteria values
.AutoFilter Field:=8, Criteria1:=aCritVal, Operator:=xlFilterValues 'Our array value that we crated in the above section, that will be used as filter
.AutoFilter Field:=6, Criteria1:="816" '"Regular" critera value
.AutoFilter Field:=2, Criteria1:="RWK"
End With
End Sub
The criteria range should only include the values for the criteria we want to filter. Please notice that I have used header for the filter criteria at row 2, as I use lcol_filter to find the last column to apply filter, therefore I put the filter table on row 2 and the first value will be in row 3.
For Each CellVal In ws.Range(ws.Cells(3, "N"), ws.Cells(lrow_crit, "N"))
'.......
Next CellVal
For wildcard in the array:
Criteria1:=Array("*CBA*", "*AB*")
Change the part of the code where we store the values and add asterix:
aCritVal(i) = CellVal.Value -> aCritVal(i) = "*" & CellVal.Value & "*"

How do I paste into a row based on the value of a column

It may be already on here and Ive missed it but I'm having trouble working out how to change my code from pasting into the last row to pasting into a specific row.
Each dataset has a unique number in column A.
I need to paste the Array into the row which matches the unique reference on the data entry Sheet.
So if the data entry sheet (Enter Action), has "123" in cell C3, I need it to look at the database (RAW DATA) and find the row with "123" in Column A and paste the Array into this row.
I have only ever pasted into the last row before and don't know how to change the below code to do what I need.
Dim vCopy, i As Long, rPaste As Range
vCopy = Array("C3", "C5", "Q26", "C7", "C9", "Q26", "C11", "C13", "C15", "G13", "G3", "C17", "G7", "G9", "K3", "G11", "K9")
Set rPaste = Sheets("RAW DATA").Cells(Rows.count, 1).End(xlUp)(2)
For i = LBound(vCopy) To UBound(vCopy)
rPaste.Value = Sheets("Enter Action").Range(vCopy(i)).Value
Set rPaste = rPaste.Offset(, 1)
Next i
You can use Find:
Dim vCopy, i As Long, f As Range, lookFor
vCopy = Array("C3", "C5", "Q26", "C7", "C9", "Q26", "C11", "C13", "C15", _
"G13", "G3", "C17", "G7", "G9", "K3", "G11", "K9")
lookFor = Sheets("Enter Action").range("c3").value
Set f = Sheets("RAW DATA").Columns(1).find(lookFor, lookat:=xlWhole)
If not f is nothing then
For i = LBound(vCopy) To UBound(vCopy)
f.Offset(0, i).Value = Sheets("Enter Action").Range(vCopy(i)).Value 'fixed#2
Next i
End If

Copy paste based on column header

The following piece of code works great for me except that it stops when it gets an empty row in the column.
I would like to modify it by determining to copy-paste until the last row in column A. I have made a LASTROW variable, but I can not figure out where to use it exactly.
LASTROW = Range("A" & Rows.Count).End(xlUp).Row
Sub CopyHeaders()
Dim header As Range, headers As Range
Set headers = Worksheets("ws1").Range("A1:Z1")
For Each header In headers
If GetHeaderColumn(header.Value) > 0 Then
Range(header.Offset(1, 0), header.End(xlDown)).Copy Destination:=Worksheets("ws2").Cells(2, GetHeaderColumn(header.Value))
End If
Next
End Sub
Function GetHeaderColumn(header As String) As Integer
Dim headers As Range
Set headers = Worksheets("ws2").Range("A1:Z1")
GetHeaderColumn = IIf(IsNumeric(Application.Match(header, headers, 0)), Application.Match(header, headers, 0), 0)
End Function
Thank you in advance !
Have you tryed this way?
For Each header In headers
If GetHeaderColumn(header.Value) > 0 Then
Range(header.Offset(1, 0).Address, Worksheets("ws1").Cells(Rows.Count, header.Column).End(xlUp).Address).Copy Destination:=Worksheets("ws2").Cells(2, GetHeaderColumn(header.Value))
End If
Next

Copy entire row from specific cell

I am relatively new to vba. I have a problem in copying a row from specific cell. That is if my cell position is at D5 then it should copy the entire row from that cell position into a single cell in sheet 2. And i need the count of the total cell copied.
Thanks in advance.
Assuming activecell as interested cell, to copy all cells on the row you can use:
StartCol = ActiveCell.End(xlToLeft).Column
EndCol = ActiveCell.End(xlToRight).Column
mRow = ActiveCell.Row
Set mRange = Range(Cells(mRow, StartCol), Cells(mRow, EndCol))
mRange.Copy Destination:=Range("A20") 'Insert your destination instead of "A20"
If you need to insert a specific cell value you can use Range("your address") or Cells(RowNumber, ColumnNuber) instead of ActiveCell.
You also can use a string variable containig an address into Range, so, for example:
mAddress = "D5"
StartCol = Range(mAddress).End(xlToLeft).Column
EndCol = Range(mAddress).End(xlToRight).Column
mRow = Range(mAddress).Row
Set mRange = Range(Cells(mRow, StartCol), Cells(mRow, EndCol))
mRange.Copy Destination:=Range("A20") 'Insert your destination instead of "A20"
Changing the value of mAddress you'll have what you need
Edit:
This is to copy from D4 to the end of row
mAddress = "D4"
StartCol = Range(mAddress).Column
EndCol = Range(mAddress).End(xlToRight).Column
mRow = Range(mAddress).Row
Set mRange = Range(Cells(mRow, StartCol), Cells(mRow, EndCol))
mRange.Copy Destination:=Range("A20")
Also, in your initial question you ask about cell count. In order to calculate this, you would just need to use this line:
cellCount = endCol - startCol + 1

Resources