Looking for a function similar to SUMIFS - excel

In Excel, the SUMIFS function is great for creating a summation occurrences where multiple conditions on multiple ranges are met. However, I am looking for a similar function, that returns the first value where these conditions are met. For instance, a table contains a column with first names, a columns with surnames, and a column with User IDs. Given the first name and surname, I need to look up the person's User ID.
Is there a formula for this? I have tried searching all kinds of combinations with "if" and "ifs", but to no avail. I do not want to write a macro for something so simple.

Though you would prefer not to write a macro for something simple like this, in this case I would say that this is the simplest solution. A short function like this would be useful, if you decide to employ this type of technique down the road at some point:
Function FindRowIndex(firstName As String, lastName As String) As Integer
With ThisWorkbook.Sheet1
For j = 1 To NumLines
If .Cells(j, 1) = firstName And .Cells(j, 2) = lastName Then
FindRowIndex = j
Exit Function
End If
Next j
End With
End Function

this works...
=INDEX(C1:C9,SUMPRODUCT((A1:A9=A10)*(B1:B9=B10)*ROW(1:9)))
the following picture shows it in position... http://i.stack.imgur.com/VFaC9.png
this picture shows the result you require... http://i.stack.imgur.com/Id0BZ.png
obviously if you need more than 9 rows just adjust the 4 references within the formula.

Related

How to filter rows based on column value without using FILTER function in excel?

Hi all,
I want to use a formula to filter the rows based on the name chosen in cell D2. From what I searched in google, I only can see people using FILTER function which is very easy. However, FILTER function is only available if we subscribe to 365 office. May I know is there any way to achieve what I want for non 365 office user? Any help will be greatly appreciated!
As far as I understand, hiding the values different than D2 will take care of your need. I am using a similar macro for this task and below I modified it for you to hide the values different than D2. It will start checking values from active cell and loop through until it finds a null value. You can try it and modify it according to your needs. Then you can assign a keyboard shortcut or put a button for it into quick access toolbar, if you are going to use this frequently.
Sub hideByD2()
Dim i, j
i = ActiveCell.Row
j = ActiveCell.Column
k = Cells(2, 4).Value
Do Until Cells(i, j) = ""
If Cells(i, j) <> k Then
Rows(i).Select
Selection.EntireRow.Hidden = True
Else
End If
i = i + 1
Loop
MsgBox "hide process completed successfully"
End Sub
Manage to find the solution.
Formula:
G5 = =IFERROR(INDEX($C$5:$C$14,AGGREGATE(15,6,1/($C$5:$C$14=$D$2)*(ROW($C$5:$C$14)-ROW($C$4)),ROW()-ROW($C$4))),"")
H5 = =IFERROR(INDEX($D$5:$D$14,AGGREGATE(15,6,1/($C$5:$C$14=$D$2)*(ROW($C$5:$C$14)-ROW($C$4)),ROW()-ROW($C$4))),"")
I5 = =IFERROR(INDEX($E$5:$E$14,AGGREGATE(15,6,1/($C$5:$C$14=$D$2)*(ROW($C$5:$C$14)-ROW($C$4)),ROW()-ROW($C$4))),"")
Drag down these 3 formula to the cells below and should work.
Say you have this layout (just the first two columns of your data, moved to a1). Here are two formulas, one that contains FALSES (if you don't care) and one that removes them (because you probably do):
=IF(A4:A13=B1,B4:B13)
=IFERROR(SMALL(IF(A4:A13=B1,B4:B13), ROW(A4:A13)-3), "")
The first one is pretty straightforward. The second one is very similar. It just passes those results to SMALL, which will return the kth smallest value form the array ignoring FALSE values. To get it to evaluate the entire array, you also send it an array of 1 to n, generated with ROW(), and since the range starts in A4 you have to adjust by -3 to make the array start at 1. If you didn't want to have to figure out the offset, you could do this, but we're rapidly losing readability:
=IFERROR(SMALL(IF(A4:A13=B1,B4:B13), ROW(A4:A13)-MIN(ROW(A4:A13))+1), "")
When SMALL gets your list of matching values (with the falses), it will a match for each number in the ROW array you send it, and if it runs out of actual numbers it will start returning errors, which is why you wrap the whole thing in IFERROR.
This will work for numeric values. If you have to support any value, you can still do it:
=IFERROR(
INDEX(
B:B,
SMALL(
IF(A4:A13=B1, ROW(A4:A13)),
ROW(INDIRECT("1:"&ROWS(A4:A13)))
),
0
),
"")
In this case, instead of returning the matching values with SMALL, you will return the matching row numbers, then you will pass those to INDEX, wrapping the whole thing in IFERROR. I used a slightly different method to generate the dynamic indexes:
ROW(INDIRECT("1:"&ROWS(A4:A13)))
which will return an array from 1 to the number of rows in the passed range, but any of the methods to generate the sequence will work.

In Excel, how can I avoid repeating a big part of the formula just to check if the return value is blank?

I have a situation where I am referencing cells in a different worksheet and returning the values of cells from that worksheet. Although it works, I find my current method inefficient because I have to repeat the formula in the logical test part of the IF statement:
=IF(**EXTREMELY LONG COMPLICATED FORMULA** <> "", **EXTREMELY LONG COMPLICATED FORMULA**, "")
As you can see, I must repeat the main part of the formula just to check if it is blank first. If I do not do this, I get a zero in the cell (for blank values in the referenced worksheet). I'm looking for something more like:
=IF(**EXTREMELY LONG COMPLICATED FORMULA** <> "", **RETURN VALUE**, "")
This looks cleaner to me because I won't have to repeat myself. Also, if we ever have to update the formula, I won't have to duplicate my changes to the repeated parts. Is there a way to do this?
The above is actually a simplified version of my problem, but the answer should get me where I need to go. My actual formula has nested IF statements checking along the way for blanks. For reference, here it is:
=IFERROR(IF(SMALL(IF(ImportedData!$H$2:$H$1000>=DataFilters!$A$1,IF(ImportedData!$G$2:$G$1000=DataFilters!$A$15,ROW(ImportedData!A$2:A$1000)-ROW(ImportedData!A$2)+1)),ROWS(ImportedData!A$2:ImportedData!A2))<>"",IF(INDEX(ImportedData!A$2:A$1000,SMALL(IF(ImportedData!$H$2:$H$1000>=DataFilters!$A$1,IF(ImportedData!$G$2:$G$1000=DataFilters!$A$15,ROW(ImportedData!A$2:A$1000)-ROW(ImportedData!A$2)+1)),ROWS(ImportedData!A$2:ImportedData!A2)))<>"",INDEX(ImportedData!A$2:A$1000,SMALL(IF(ImportedData!$H$2:$H$1000>=DataFilters!$A$1,IF(ImportedData!$G$2:$G$1000=DataFilters!$A$15,ROW(ImportedData!A$2:A$1000)-ROW(ImportedData!A$2)+1)),ROWS(ImportedData!A$2:ImportedData!A2))),""),""),"")
The most obvious solution is to use a helper column or cell. Just put EXTREMELY LONG COMPLICATED FORMULA somewhere in your spreadsheet, then refer to that cell in your IF formula.
Edit
To avoid a helper column, here is a trick I've used on occasion:
=IFERROR(VALUE(long_formula&""),"")
What this does is, concatenate the result of long formula with an empty string (which converts it to a string), then take the value of all that (which converts it back to a number if possible), then substitute any errors with a blank. (An error would occur if you attempt to take the value of something that's not numerical.)
This will only work if you either have a numerical result or an empty result. It will fail if you have a text result.
As of March 2020, Excel includes the LET function. You can write:
=LET(ELCF,**EXTREMELY LONG COMPLICATED FORMULA**,IF(ELCF <> "", ELCF, ""))
Where the three parameters are:
the name you will use to refer to your calculation,
the calculation itself, and
the final formula using the calculation.
The function also allows for multiple names to be defined. The general syntax is:
=LET(name1, name_value1, calculation_or_name2, [name_value2, calculation_or_name3...])
https://support.microsoft.com/en-us/office/let-function-34842dd8-b92b-4d3f-b325-b8b8f9908999
Do you need the blank in the cell for further calulations or if-functions or Do you just dont want to see the 0s?
Second case:
Just use a number format for the column like
0,00;-0,00;"";#
First case:
Put the following code in a module:
Option Explicit
Public Function IfEmpty(LongFormula As String) As String
If LongFormula = "" Then
IfEmpty = ""
Else
IfEmpty = LongFormula
End If
End Function
And use it in your worksheet like
=IfEmpty(**EXTREMELY LONG COMPLICATED FORMULA**)

Non-consecutive range in excel function

I have an excel table were A1 = "YES", B1 = "YES" and C1 = "YES". I want to know how many "YES" are in my table, which is easily solved with =COUNTIF(A1:C1,"YES") and it will accurately give me the answer of 3.
A B C
1 YES YES YES
But if want to know how many "YES" are in A1 and C1 and ignore whatever B1 has it becomes tricky. The same function gives me 3 while I want it to give me 2 as an answer since I want to count only A1 and C1.
I want to know if there is a way to manage data so I can work only with that kind of non-consecutive cells? I found that a solution would be using something like =if(A1="YES",1)+if(C1="YES",1) and it works like a charm since it will always give me the right answer; however, that is not a satisfying solution because despite the simplicity in my example, my real situation requires to write around 100 cells from a 500 range for several different combinations which can become somewhat heavy.
I tried using name ranges but it seems the if functions doesn't let me use them the way I want. So any help will be apreciated, thanks.
If VBA is an option and "non-consecutive ranges in excel functions" is the question, then you could create a User Defined Function which takes a ParamArray and returns an array out of all given parameters.
Example
Public Function getMatrix(ParamArray aValues() As Variant) As Variant
Dim i As Long
Dim aReturnValues() As Variant
For Each vValue In aValues
For Each vSingleValue In vValue ' possible the vValue is also an array
ReDim Preserve aReturnValues(i)
aReturnValues(i) = vSingleValue
i = i + 1
Next
Next
getMatrix = aReturnValues
End Function
This could then be used like:
Formula in A4:
=SUMPRODUCT(--(getMatrix(A1,C1,E1:G1,D2:E3)="Yes"))
Note, the UDF is returning an array, not a Range. Thats why we cannot use COUNTIF. COUNTIF needs a Range as first parameter.
Why looking for a formula when you have other features in Excel? Add a row (#2), and have A2=1, B2=0, C2=1 till the last column [Drag it to populate, Make sure to Copy Cells]. Then select row and see the Sum in Status Bar.
Have a look at this thread. Basically what you need is something like this:
=SUM(COUNTIF(INDIRECT({"A1:A10","C1:c10"}),"a"))
Or just use multiple COUNTIFs, and add them. (Countif(...) + countif(...) etc.)

SumIf with Strings?

This may be a stupid question, and if it is, I apologise. I have a table in excel:
Column a...........Column b
1 property1.......problem x
2 property2.......problemy
3 property3.......problemz
4 property1......problem a
I was wondering if I could use sumif (or any similar formula) to add the problems, referring to a certain property, in one cell. for ex:
I would have
Column a...........Column b
1 property1.......problem x problem a
The problem is I can't figure out where to start. I tried using sumif but I get an error. Probably because I'm trying to add strings. I tried to mix a vlookup with sumif but that didn't produce anything too. Im stuck here. Thanks for any help!
I am not 100 % sure, but I think you might need to use VBA for this. You could try to create the following custom function:
Create named ranges properties and problems in your sheet.
Click ALT+F11 to open VBA editor.
Press Insert --> Module
Write code
'
Function ConcatIF(Property As String, PropertyRange As Range, ProblemRange As Range) As String
Dim counter As Integer
Dim result As String
result = ""
Dim row As Range
counter = 1
For Each row In PropertyRange.Rows
If (Property = row.Cells(1,1).Value) Then
result = result + ProblemRange.Cells(counter,1).Value + " "
End If
counter = counter +1
Next row
ConcatIF = result
End Function
As I do not have excel on the machine I am writing this on, I could only test it on another machine, and therefore there could be spelling mistakes in this code.
Ensure that you write the code in the module you created, it cannot be written in a Sheet's code, must be module.
This function can then be called as a regular function, like sum, average and if. Create a unique list of all your properties on another sheet. Properties in column A, and then in column B you can call the cuntion. Assume row 1 is used for headings, write the following and copy down.
=ConcatIF(A2,properties,problems)
NOTE!!!! This code gets out of hand very quickly. It needs to do (number of properties) x (number of property/problem pairs) comparisons, so if this number is huge, it could slow down your sheet.
There could be faster methods, but this was from the top of my head.

Excel - Convert String with if condition to a formula

I'd like to use something like the EVALUATE-Function in Excel for if-statements.
I've got the following issue: I'd like to use Excel to validate my data. I've got three sheets:
the real data I'd like to check. Each row represents a customer and each column some data. The columns have specific names like “age”, “name”, …
the description of the checks I’d like to perform. Each row represents one check and I’ve got 3 columns: 1 check_id – an identifier of each check; 2 check_desc – a description of the check that every normal person can understand like “Age below 18”; 3 rule – the Excel Formula as a string like If(age<18, “error”, “no error”)
the place where sheet 1 and 2 should come together. Each row should represent one customer and each column one check.
Now, if I’ve got for example check_1 “If(age<18, “error”, “no error”)” and the customer data 10 and 20, then the check for the first customer should fire and the check for the second shouldn’t.
If the data is changed, and the age is set from 10 to 18, then everything should be fine, or if the rule is changes to “If(age<21, “error”, “no error”)” then the new condition should be applied to all data.
Is something like this possible?
With the evaluate function only ‘simple’ formulas work.
Thanks in advance,
Martin
Attached you can find the
Excel-Sample File
You will definitely need some VBA here. Make a custom EVAL function:
Public Function EVAL(ByRef Rng As Range, Formula As String) As Variant
Dim RngAddress As String
RngAddress = "'" & Rng.Parent.Name & "'!" & Rng.Address(External:=False)
EVAL = Evaluate(Replace(Formula, "$", RngAddress))
End Function
Then you can easily evaluate your values with formulas passed as text ($ is for parameter):
=EVAL(A1, "IF($<21,""error"",""no error"")")
(note the escaped double quotes). But you would rather pass formula from another cell - then you can specify formula in cell with single quotes:
IF($<21,"error","no error")
=EVAL(A1, B1)
I personally would rename check_desc!B2 to "Check_1" (named range) and then refer to that. You can use the INDIRECT function as well once you've renamed your column header "Check_1" as well.
Note: the value in this case should be "18" instead of "age below 18". You can of course change the number format to "age below "0.
If the relations are changing too I would insert a table that would have uniform formulae changing in each cell when changed in one cell.
The only issue you would then face is the non-expanding nature of your table. You can use VBA for this, but maintaining formulae increases your accountability even if it would be slightly easier not to deal with nasty nested functions.

Resources