Mode Text 2nd most common text value - excel

IFERROR(INDEX($I$7:$I,MODE(IF($I$7:$I<>"",MATCH($I$7:$I,$I$7:$I,0)))),"No data")
With this formula, which calculates the most common text value, I need to have the 2nd most common.
Column I content:
Apple
Orange
Apple
Apple
Orange
In this example, I need to get Orange. How is that possible? I can't figure how.

A PivotTable might suit:
and copes with ties for rank.

You can extract the most frequent item in the list with an array formula.
=INDEX(MyList,MATCH(MAX(COUNTIF(MyList,MyList)),COUNTIF(MyList,MyList),0))
Note that an array formula must be confirmed with Shift+Ctl+Enter instead of the customary singular Enter required for normal formulas. When entered wrongly it will display a #NUM! error.
For simplicity's sake I have used a named range MyList in the formula. However, if you prefer, you can replace the name with something like $I$7:$I$1000.
To extract the second-most frequent expression in the list you could use a formula constructed analogue to the above.
=INDEX(MyList,MATCH(LARGE(COUNTIF(MyList,MyList),MAX(COUNTIF(MyList,MyList))+1),COUNTIF(MyList,MyList),0))
This formula is built on the logic that n equals the highest number of occurrences. Therefore the second highest must rank as n + 1, being MAX(COUNTIF(MyList,MyList))+1) in the above formula. By the same method the third ranked could be extracted.
You can embed these formulas in an IFERROR() function.

I found this on Mr Excel
Return most common, 2nd most common, 3rd most common, etc. text string in an array
Spreadsheet Formulas
Cell ___ Formula 'Notice that the cells are B2, D2, E2. Column C is blank
B2 =IF(A2="","",IF(COUNTIF(A$2:A2,A2)=COUNTIF($A$2:$A$100,A2),COUNTIF($A$2:$A$100,A2)+(ROW()/1000),""))
D2 =IF(ROWS($1:1)>COUNT(B:B),"",INDEX(A:A,MATCH(LARGE(B:B,ROWS($1:1)),B:B,0)))
E2 =IF(D2="","",COUNTIF($A$2:$A$100,D2))<br><br>
Results
___ A ________ B ___C ___D _________E
1 Data Set:___Helper ____ Name ____ Occurrences
2 Harmon _____________ Williams ______4
3 Smith _______________ Smith ________3
4 Smith _______________ Harmon ______2
5 Harmon_____ 2.005
6 Williams
7 Williams
8 Smith _______3.008
9 Williams
10 Williams ____4.010

you can try to tie this all together in a single formula but it's simpler and more agile in a spreadsheet environment to just break out the problem in a few separate steps.
take a given column of values you're wanting to count/rank - i'll call it RankList in examples below.
if you're not setting named ranges (do yourself a favor and use named ranges) you'll want this to be your column range - i.e. A:A
now in another column use
=unique(RankList)
there's your list of unique values, now we just need to count the instances of each unique value in the original RankList - this is simple - in the next column over simply use
=countif(RankList,B1)
B1 above represents the cell adjacent to the formula, wherever that might be on your sheet. now autofill the formula in with the relative cell value for each item. now all of your items are counted by instance.
now we want to sort them by value, highest to lowest. create another named range, selecting the two columns containing the =unique(RankList) and =countif(RankList,B1) formulas that were just created, i'll refer to it as UniqueCount
use the following
=sort(UniqueCount, 2, false)
that's it. again you can accomplish this by stacking formulas like in the above examples, but in practice i've found that you won't know what you'll want to do additionally with your data/sheet later on. keeping it broken up in discrete steps like this makes it much easier to make adjustments.

Related

Convert an Array Formula's Text Results into a Usable Format

When the results of an Array Formula are numbers, I find it generally easy to find an appropriate method to collapse the array into a single result. However when the results of an Array Formula are text, I find it difficult to manipulate the formula in a way which provides a single desired result. In short, is there a method of manipulating an Array of text results which I have overlooked? See the bottom of this question for the final desired formula which doesn't work, and request for solutions.
*Edit - after reading through this again, I can alternately summarize my question as: is there a way to access multiple text elements from a 'Formula Array result', without individually selecting (eg: with INDEX)?
Examples where Array Formulas work, where the Result Array is number values
(1) Example 1: Assume column A rows 1-500 is a list of product ID's in the format of xyz123, and column B rows 1-500 shows total sales for that product. If I want to find the sales for the product with the highest sales, where the last 3 digits of an ID are above 400, I could use an Array Formula like so (confirmed with CTRL + SHIFT + ENTER instead of just ENTER):
=MAX(IF(VALUE(RIGHT(A1:A500,3))>400,B1:B500,""))
(2) Example 2 Now assume that column B contains product names, instead of Sales. I now want to simply return the first name which matches criteria of the last 3 digits of the product ID being > 400. This could be done as follows:
=INDEX(B1:B500,MIN(IF(VALUE(RIGHT(A1:A500,3))>400,ROW(A1:A500),"")))
Here, I have done a little manipulation, so that the actual Array part of the formula [IF(RIGHT(A1:A500,3...] returns a value result [the ROWs of the cellsA1:A500 where the last 3 digits are above 400]; I can therefore use MIN to show only the first ROW # which matches, and then I can use that collapsed result in a regular INDEX function.
(3) Example 3 For a final example, see the discussion on a similar question here [Goes more in-depth than my summarized example below, in a way not directly relevant to this question]: https://stackoverflow.com/a/31325935/5090027
Assume now that you want a list of all product names, where the last 3 digits of the product ID >400. To my knowledge, this cannot really be done in a single Cell, it would have to be done by placing each individual result on a subsequent cell. The following formula could be placed, for example, in C1 and dragged down 10 rows, and would then show the first 10 product names with the product ID's having last 3 digits > 400.
=INDEX($B$1:$B$500,SMALL(IF(VALUE(RIGHT($A$1:$A$500,3))>400,ROW($A$1:$A$500),""),ROW()))
Example where Array Formulas will not work, where the result array is text values
Now assume that I want to take the results in Example 3, and perform some text manipulation on them. For example, assume I want to concatenate them all into a single string of text. The below doesn't work, because concatenate won't take an array of results like this as acceptable arguments.
=CONCATENATE((IF(VALUE(RIGHT($A$1:$A$500,3))>400,ROW($B$1:$B$500),"")))
So the question is: does anyone know how to get this last formula to work? Or, how to get a formula to work which takes an array of text results, and either converts it into a 'usable range' [so it can be plugged into Concatenate above], or can be manipulated with text arguments immediately [such as mid, search, substitute, etc.]? Right now the only method I can see would be using example 3 above, and then going further and saying, for example, Concatenate(C1,C2,C3...C10).
As stated previously, there is no native function which can do what you want in a single cell. If you absolutely cannot use VBA, then you could use a helper column (can hide the column if preferred) and then have the cell where you want the result simply show the last cell of the helper column.
Example:
Produce Name Type
Apple Fruit
Broccoli Vegetable
Carrot Vegetable
Orange Fruit
Say you want a single cell to show all Fruit results. You could use another column to host this formula. You will be hiding the column later, so let's use one out of the way, like column Z. We also want to easily be able to change what you're looking for, so we'll put the condition in cell D2. In cell Z2 and copied down, you would use this formula:
=IF(B2=$D$2,IF(Z1="",A2,Z1&", "&A2),IF(Z1="","",Z1))
That would result in the following:
Produce Name Type Search For (other columns until you get to Z)
Apple Fruit Fruit Apple
Broccoli Vegetable Apple
Carrot Vegetable Apple
Orange Fruit Apple, Orange
Then in wherever you want your result cell, we'll say D3, simply use this formula to get the last result from your helper column, and then hide the helper column.
=Z5
Which results in the following:
Produce Name Type Search For
Apple Fruit Fruit
Broccoli Vegetable Apple, Orange
Carrot Vegetable
Orange Fruit
You could use a dynamic named range instead of simply =Z5 to make sure you're always getting the last cell in your helper column so that your data can grow or shrink and you'll still get the correct result. But now you can change the contents of cell D2 from Fruit to be Vegetable and now the result cell will show Broccoli, Carrot. Hopefully something like this can be adapted to your needs.
To reiterate other responses, I did not find a way to use the concatenate function on an array. However, I did find a way to concatenate the "product names" using only one array function and no so-called "helper column." Although it is rather long and tedious, I think this may add to the discussion. For one, if you are actually going to use a formula like this for some valid purpose or to overcome a specific barrier, it can be easily used via copying and pasting of the formula (that is, it is actually relatively adaptable). On the other hand, if your interest is more a curiosity, my answer may be more banal than you might like.
In my simulation of your problem, I also had two columns, but shortened the row count to 40. The leftmost column ("C") contains sequences of three letters and three numbers, while the right column ("D") contains random sequences of letters and numbers that simulate your "product names."
I used a combination of nested replace and concatenate functions. The function below is chopped to focus on the "base unit" of the agglomerated function.
Base Unit
REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),1)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),1))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),1)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),2)))=TRUE,””,
The above formula essentially looks at the first product name with a corresponding product ID with numerical sequence > 400, then replaces it with a concatenation, given that there exists another product meeting the same product ID criteria. This can be thought of as a "accumulating" concatenation, starting at the innermost parentheses. This "base unit" of the formula can be repeated to an arbitrary extent. That is, if you believe that there are anywhere from 200 to 280 products in the list meeting the product ID criteria you set, you can repeat this base code 280 times. As you see, if the formula attempts to concatenate product names that do not exist (you have 280 formula base units and only 275 products meeting the criteria), the formula self-terminates...in a sense. It actually begins to concatenate nothing over and over again until all base units are enacted. The result will be all desired product names concatenated in one cell, with a period separating each one.
Only one number changes from base-block to base-block, and that is the kth element of the SMALL array. These variables will obviously step by one in each base unit. For my test, I used 14 base units.
Complete Formula with 14 Base Units
=REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),1)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),1))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),1)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),2)))=TRUE,””,REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),2)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),2))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),2)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),3)))=TRUE,””,REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),3)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),3))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),3)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),4)))=TRUE,””,REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),4)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),4))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),4)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),5)))=TRUE,””,REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),5)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),5))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),5)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),6)))=TRUE,””,REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),6)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),6))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),6)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),7)))=TRUE,””,REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),7)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),7))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),7)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),8)))=TRUE,””,REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),8)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),8))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),8)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),9)))=TRUE,””,REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),9)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),9))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),9)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),10)))=TRUE,””,REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),10)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),10))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),10)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),11)))=TRUE,””,REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),11)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),11))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),11)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),12)))=TRUE,””,**REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),12)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),12))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),12)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),13)))=TRUE,””,REPLACE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),13)),1,LEN(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),13))),CONCATENATE(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),13)),".",IF(ISERR(INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),14)))=TRUE,””,INDEX($D$1:$D$40,SMALL(IF(VALUE(RIGHT($C$1:$C$40,3))>400,ROW($D$1:$D$40),""),14)))))))))))))))))))))))))))))))))))))))))
Obviously, if you look at the entire formula, it is pretty indecipherable. But, looking at it in terms of base units, you may see how it can be easily constructed then copied and pasted (after writing the initial base unit, it took about 2 minutes to put it all together).
This is a VBA-free solution using Get&Transform in Excel 2016 or the Power Query Add-In for versions before:
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
ExtractLast3Digits = Table.AddColumn(Source, "Value", each Text.End([ProductID],3)),
ChangeToNumber = Table.TransformColumnTypes(ExtractLast3Digits,{{"Value", type number}}),
FilterAbove400 = Table.SelectRows(ChangeToNumber, each [Value] > 400),
Concatenate = Text.Combine(FilterAbove400[ProductName])
in
Concatenate
You can perform all sorts of text manipulation on the “array-output” (Step “FilterAbove400”), in this example I’ve just concatenated without separators as I understood your request.
It takes your input data that should be in table-form and named “Table1” in the 1st step (Source).
Link to file with solution: https://www.dropbox.com/s/utsraj0bec5ewqk/SE_ConvertArrayFormulasTextResult.xlsx?dl=0
You can create your own aggregate function to handle the results of a formula array. It does require a little VBA... but it's not difficult. This will allow you to do all kinds of string manipulation or numerical analysis on arrays of values.
To do your concatenation function, open up a VBA code window and create a new module by right clicking on the project -> insert -> new module. Double click the new module and insert this code to create the function that will concatenate an array into one large string:
Function ConcatenateArray(ParamArray Nums() As Variant) As Variant
Dim BigString As String
Dim N As Long
Dim A() As Variant
Let A = Nums(0)
BigString = ""
For N = LBound(A) To UBound(A)
BigString = BigString & A(N, 1)
Next
ConcatenateArray = BigString
End Function
Then change your array formula in the cell to:
=ConcatenateArray(IF(VALUE(RIGHT($A$1:$A$500,3))>400,$A$1:$A$500,""))
Of course you have to hit CTRL + SHIFT + ENTER instead of just ENTER to confirm the cell as an array formula.
I would try to address the several question raised in this post:
how to get a formula to work which takes an array of text results, and
either converts it into a 'usable range' [so it can be plugged into
Concatenate above],
Even if the first part of this question is feasible, the last part (i.e. "[so it can be plugged into Concatenate above]" is not possible as the CONCATENATE function does not take ranges as argument.
or can be manipulated with text arguments immediately [such as mid,
search, substitute, etc.]? Right now the only method I can see would
be using example 3 above, and then going further and saying, for
example, Concatenate(C1,C2,C3...C10).
That’s certainly one method, but please give a try to this:
Let's start from this:
Now assume that I want to take the results in Example 3, and perform
some text manipulation on them. For example, assume I want to
concatenate them all into a single string of text.
But first let’s assume the following:
-. Data range is located at D10:F510 and includes fields: Product, Product, Sales and Product Name (Selection)*
*used to list results from formula in example 3
.- Data contains 23 records complying with the criteria defined in example 1 (see Fig. 1)
.- Value 400 is enter in cell E4 to ease modifications to the criteria instead of hard code in the formulas (see Fig. 3).
Fig. 1
Now, in order to generate an Array with the concatenated results and to post it a usable range, let’s apply a minor modification to the formula in example 3. Enter this FormulaArray in G11 and copy till last record (not just 10 lines)
=TRIM(CONCATENATE(
IF(ROW(G11)-ROW(G$11)+1=1,"",G10)," ",
IFERROR(INDEX($E$11:$E$510,
SMALL(IF(VALUE(RIGHT($D$11:$D$510,3))>$E$4,ROW($D$11:$D$510)-ROW($D$11)+1,""),
ROW(G11)-ROW(G$11)+1)),"")))
Fig. 2
The in the Summary section located at D4:E8 we have the results from examples 1 & 2 and the Concatenated results with the list of selected products (see Fig. 3). Enter this formula in E8 (suggest to increase the row height to the max of 409 and Wrap Text to true)
=INDEX($M$11:$M$510,1+MAX(ROW($M$11:$M$510))-ROW($D$11))
Fig. 3
As regards this question:
Is there a way to access multiple text elements from a 'Formula Array
result', without individually selecting (eg: with INDEX)?
On this particular case (i.e. concatenation of array elements) I would apply a different perspective and generate the array with concatenated results then to pick the needed element, even if the use of INDEX is required.
Last I would like to make a minor note about these formulas:
Example 2:
=INDEX(B1:B500,MIN(IF(VALUE(RIGHT(A1:A500,3))>400,ROW(A1:A500),"")))
If the data range does not start at Row 1 use this formula instead:
=INDEX($E$11:$E$510,MIN(IF(VALUE(RIGHT($D$11:$D$510,3))>400,
1+ROW($D$11:$D$510)-ROW($D$11),"")))
Example 3:
=INDEX($B$1:$B$500,SMALL(IF(VALUE(RIGHT($A$1:$A$500,3))>400,ROW($A$1:$A$500),""),ROW()))
If the data range does not start at Row 1 use this formula instead:
=IFERROR(INDEX($E$11:$E$510,
SMALL(IF(VALUE(RIGHT($D$11:$D$510,3))>$E$4,
1+ROW($D$11:$D$510)-ROW($D$11),""),
1+ROW()-ROW($K$11))),"")

Summing numeric portion of cell when alpha portion of cell is the same

I have a spreadsheet that has columns for dates and the values can be either "1v, .5v, 1p, .5p, 1s, .5s"
I have 3 columns in each row one for each letter "v, p and s". I want to be able to add the total of all cells in the range grouped by letter and then display the sum for each letter in it's respective column (v, p or c).
Here is an example of the sheet:
Name Vacation Personal Sick 1/5/15 1/6/15 1/7/15 1/8/15
Billy 1.5 1 0 .5v 1v 1p
It is the formula that goes in the vacation/personal/sick cell that I just can't figure out.
I went down the array formula route and came up with essentially the same formula as #Sancho.s :-
=SUM(LEFT($E2:$H2,LEN($E2:$H2)-1)*(RIGHT($E2:$H2)="v"))
You could modify it to take account of blanks:-
=SUM(IF($E2:$H2<>"",LEFT($E2:$H2,LEN($E2:$H2)-1)*(RIGHT($E2:$H2)="v")))
Perhaps this would be better, to ignore any mis-formatted cells:-
=SUM(IFERROR(LEFT($E2:$H2,LEN($E2:$H2)-1)*(RIGHT($E2:$H2)="v"),0))
These all have to be put in with Ctrl-Shift-Enter.
Assuming the range you posted starts at A1, use
=SUMPRODUCT((RIGHT($E2:$G2,1)="v")*LEFT($E2:$G2,LEN($E2:$G2)-1))
in B2. Change "v" and the range to use suitably.
Pro:
It is not an array formula. See why this may be important
Con:
I could not make it work with blank cells.
This "array entered" version will also allow blanks
=SUM(IF(RIGHT(E2:G2)="v",SUBSTITUTE(E2:G2,"v","")+0))
confirmed with CTRL+SHIFT+ENTER

INDEX/MATCH with multiple criteria

Need assistance with an Excel formula.
I am trying to get a summary of a range. I have been playing with the Match, Index, Countif functions and can create a list of unique dates and then using a vlookup to return the persons name.
I need something to take the persons name into account so if the same date appears for 2 people, it shows as 2 different lines in the output.
Please see table below - A&B is the input, D&E is what I can currently get, G&H is the output I want.
Thanks in advance.
A B C D E F G H
1 13/01/15 RYAN 13/01/15 RYAN 13/01/15 RYAN
2 13/01/15 RYAN 14/01/15 RYAN 14/01/15 RYAN
3 14/01/15 RYAN 15/01/15 RYAN 14/01/15 FRANK
4 14/01/15 RYAN 15/01/15 RYAN
5 14/01/15 RYAN
6 14/01/15 RYAN
7 14/01/15 FRANK
8 14/01/15 FRANK
9 14/01/15 FRANK
10 15/01/15 RYAN
11 15/01/15 RYAN
All knowledge I have of Excel in self taught thanks the forums like stackoverflow so any help is greatly appreciated.
Much the easiest way to achieve this is with a PivotTable. Add labels to Columns A and B (say Date and Name) then select A:B, INSERT, Tables - PivotTable, chose where in Existing Sheet or New Sheet and drag Date and then Name (below) into ROWS.
Reformat as desired.
The style of array formula I prefer requires that there be an unused cell directly above the first formula to avoid circular references. This unused cell can be used as a column header label.
The array formulas¹ used in D2:E2 are,
=IFERROR(INDEX(A:A, MATCH(0, COUNTIFS(D$1:D1,A$1:INDEX(A:A, MATCH(1E+99, A:A))&"",
E$1:E1,B$1:INDEX(B:B, MATCH(1E+99, A:A))&""), 0)), "")
=IFERROR(INDEX(B:B, MATCH(0, COUNTIFS(D$1:D1,A$1:INDEX(A:A, MATCH(1E+99, A:A))&"",
E$1:E1,B$1:INDEX(B:B, MATCH(1E+99, A:A))&""), 0)), "")
Fill down as necessary. These array formulas have their most active lookup ranges dynamically truncated at the row containing the last date in column A to cut calculation cycles down to the minimum necessary.
    
I have added an extra entry for Frank at the bottom of the list of your sample data to further demonstrate the double unique lookup.
¹ Array formulas need to be finalized with Ctrl+Shift+Enter↵. If entered correctly, Excel with wrap the formula in braces (e.g. { and }). You do not type the braces in yourself. Once entered into the first cell correctly, they can be filled or copied down or right just like any other formula. Try and reduce your full-column references to ranges more closely representing the extents of your actual data. Array formulas chew up calculation cycles logarithmically so it is good practise to narrow the referenced ranges to a minimum. See Guidelines and examples of array formulas for more information.
With helper columns this could be achieved without any array formulas. The idea is to get first a concatenation of date and name, then get only the line number of the first occurrence of date&name in the list, get those line numbers without duplicates and finally get the INDEXes of those line numbers from A:A and B:B.
Formulas:
D1:D13 =A1&B1
E1:E13 =IF($D1<>"",MATCH($D1,$D:$D,0),"empty")
F1 =MIN($E:$E)
F2:F13 =LARGE($E:$E,COUNTIF($E:$E,">"&$F1))
H1:H13 =INDEX($A:$A,$F1)
I1:I13 =INDEX($B:$B,$F1)

Formula to find match in two-dimensional range

I need a formula that will look up a value in a 2-dimensional range and return the coordinates or cell address of the matching cell. For example:
R A B C
1 John Matt Pete
2 Sara Bret Chad
3 Lila Maya Cami
I want to search the range A1:C3 for Chad and return C2 or 2,3. How can I accomplish this using Excel formulas? (I'll actually end up applying this to Google Sheets).
Thanks!
Old question, but I thought I'd share a much simpler and elegant answer here that doesn't involve helper columns or complicated formulas, so that more people will get things done easier. Assuming that the table contains unique values and that you use E1 to store your search string Chad and E2 to display the result:
if you want the row and column result of 2,3 in E2:
=SUMPRODUCT((A1:C3=E1)*ROW(A1:C3)) & "," & SUMPRODUCT((A1:C3=E1)*COLUMN(A1:C3))
if you want the R1C1 style cell address string of C2 in E2:
=ADDRESS(SUMPRODUCT((A1:C3=E1)*ROW(A1:C3)),SUMPRODUCT((A1:C3=E1)*COLUMN(A1:C3)))
if you want the found cell's contents of Chad in E2:
=INDIRECT(ADDRESS(SUMPRODUCT((A1:C3=E1)*ROW(A1:C3)),SUMPRODUCT((A1:C3=E1)*COLUMN(A1:C3))))
How things work:
SUMPRODUCT returns in this case the sum of the products between a boolean array of TRUE (searched value found in cell) and FALSE (searched value not found in cell) for every cell in the table and the corresponding row/column (absolute) numbers of those cells in the sheet; thus, the result is essentially the row/column (absolute) number of the cell where the value has been found, since TRUE=1 and FALSE=0 in mathematical terms
ADDRESS returns a cell's address as text (not as reference!)
INDIRECT returns the reference corresponding to a cell's text address
Source and credit goes to: this answer by XOR LX. Could have added the link in a comment, mentioning the duplicate question, but I wanted to expand and explain the answer a little bit, therefore more characters were needed.
Assuming you're using Excel 2007 and above.
You will need a helper column. If your table looks like in your example, in cell D1 write:
=IFERROR(MATCH($E$1,$A1:$C1,0),0)
And drag it down. Then in cell E1 write your search value ("Chad" for instance). Then you have your search result in cell E2 with this formula:
=IF(MAX($D:$D)=0,NA(),MATCH(MAX($D:$D),$D:$D,1)&","&MAX($D:$D))
If you want a simpler solution, it is possible to use only one helper (or not at all, at the cost of a complicated formulae).
Let's say I take your example. I will use the D column to display result :
In D1, I put the name I want to find : Chad
In D2, I put the helper that will return an Index of the value searched (-1 if not found) : =IFERROR(MATCH(D1,SPLIT(TEXTJOIN(";",TRUE,A1:C3),";"),0),-1)
In D3, I put the formulae to get the row,column value (FALSE if not found) : =IF(D2<>-1,ROUNDUP(DIVIDE(D2,COLUMNS(A1:C3))) & "," & IF(MOD(D2,COLUMNS(A1:C3))=0,COLUMNS(A1:C3),MOD(D2,COLUMNS(A1:C3))))
If you really want to use only one formulae, it is possible in D3 to replace all references to D2 by the formulae used in D2.
This formula returns the row and column number of a given value in a two-dimensional array.
=LET(
array, B2:D4,
findvalues, C7,
arrayrows, ROWS(array),
arraycols, COLUMNS(array),
rowindex, SEQUENCE(arrayrows*arraycols,,1,1/arraycols),
colindex, MOD(SEQUENCE(arrayrows*arraycols,,0),arraycols)+1,
flatarray, INDEX(array,rowindex,colindex),
valueflatindex, MATCH(findvalues,flatarray,0),
valuerow, ROUNDUP(valueflatindex/arraycols,0),
valuecol, MOD(valueflatindex-1,arraycols)+1,
absvaluerow, MIN(ROW(array))+valuerow-1,
absvaluecol, MIN(COLUMN(array))+valuecol-1,
CHOOSE({1,2},absvaluerow,absvaluecol)
)
A B C D E
1
2 John Matt Pete
3 Sara Bret Chad
4 Lila Maya Cami
5
6
7 find: Chad
8 formula: 3 4
More precisely, this formula scans a given array row by row and returns the address of the first occurrence of a given value.
If you need the row and column numbers relative to the array's top left cell, then in CHOOSE(...), instead of absvaluerow/absvaluecol, use valuerow/valuecol.
If you want the values to be comma separated and in one cell, instead of CHOOSE(...), use absvaluerow & "," & absvaluecol
If your Excel version does not support the latest functions, such as LET, the formula should still work if you rewrite it so that it does not use the LET variables.
Find Multiple Values
You can also find multiple values in an array using this formula as explained in my answer in this thread.

Find something in column A then show the value of B for that row in Excel 2010

Basically my problem is that I have a string in one cell in excel, I then need to see if that string exists in another row (not one cell but the whole row) and if so then print the contents of another cell in the same row but in another column.
I will give a basic example:
Title Answer
Police 15
Ambulance 20
Fire 89
Now I need to scan the title column for, say, "Police" and then populate the cell with the value under Answer (in this case 15).
I cant just say IF(A2="Police";B2;"" as I need the scan the whole of the Title column.
I have tried using IF(COUNTIF(A$2:A$100;"Police"); which scans the contents of A2 to A100 for the string Police, and know how to make it print a constant (just put something after the ;) but cant work out how to make that "constant" a variable that changes depending on the found row. So if the COUNTIF found Police in cell A44 then the answer to my formula would be B44, the same as if it found Police in A62 then my formula should show B62
I hope this makes sense and that someone can help me :)
Note that I am using excel 2010 and need a normal formula as I can not use scripting for this document.
EDIT:
Here is what I have so far, note that the spreadsheet I am using is far more complex than the "simple" example I have in the question...
=IF(ISNUMBER(FIND("RuhrP";F9));LOOKUP(A9;Ruhrpumpen!A$5:A$100;Ruhrpumpen!I$5:I$100);"")
This is showing "RuhrP" in every answer where "RuhrP" is found in F9 and not the answer I want which should be that found in RuhrPumpen!I$5:I$100 where the cell index is the same as that for the A coloum where A9 was found. Again, sorry for the complexity I cant think of any better way to word it.
I note you suggested this formula
=IF(ISNUMBER(FIND("RuhrP";F9));LOOKUP(A9;Ruhrpumpen!A$5:A$100;Ruhrpumpen!I$5:I$100);"")
.....but LOOKUP isn't appropriate here because I assume you want an exact match (LOOKUP won't guarantee that and also data in lookup range has to be sorted), so VLOOKUP or INDEX/MATCH would be better....and you can also use IFERROR to avoid the IF function, i.e
=IFERROR(VLOOKUP(A9;Ruhrpumpen!A$5:Z$100;9;0);"")
Note: VLOOKUP always looks up the lookup value (A9) in the first column of the "table array" and returns a value from the nth column of the "table array" where n is defined by col_index_num, in this case 9
INDEX/MATCH is sometimes more flexible because you can explicitly define the lookup column and the return column (and return column can be to the left of the lookup column which can't be the case in VLOOKUP), so that would look like this:
=IFERROR(INDEX(Ruhrpumpen!I$5:I$100;MATCH(A9;Ruhrpumpen!A$5:A$100;0));"")
INDEX/MATCH also allows you to more easily return multiple values from different columns, e.g. by using $ signs in front of A9 and the lookup range Ruhrpumpen!A$5:A$100, i.e.
=IFERROR(INDEX(Ruhrpumpen!I$5:I$100;MATCH($A9;Ruhrpumpen!$A$5:$A$100;0));"")
this version can be dragged across to get successive values from column I, column J, column K etc.....
Assuming
source data range is A1:B100.
query cell is D1 (here you will input Police or Fire).
result cell is E1
Formula in E1 = VLOOKUP(D1, A1:B100, 2, FALSE)
I figured out such data design:
Main sheet:
Column A: Pump codes (numbers)
Column B: formula showing a corresponding row in sheet 'Ruhrpumpen'
=ROW(Pump_codes)+MATCH(A2;Ruhrpumpen!$I$5:$I$100;0)
Formulae have ";" instead of ",", it should be also German notation. If not, pleace replace.
Column C: formula showing data in 'Ruhrpumpen' column A from a row found by formula in col B
=INDIRECT("Ruhrpumpen!A"&$B2)
Column D: formula showing data in 'Ruhrpumpen' column B from a row found by formula in col B:
=INDIRECT("Ruhrpumpen!B"&$B2)
Sheet 'Ruhrpumpen':
Column A: some data about a certain pump
Column B: some more data
Column I: pump codes. Beginning of the list includes defined name 'Pump_codes' used by the formula in column B of the main sheet.
Spreadsheet example: http://www.bumpclub.ee/~jyri_r/Excel/Data_from_other_sheet_by_code_row.xls
Guys Its very interesting to know that many of us face the problem of replication of lookup value while using the Vlookup/Index with Match or Hlookup.... If we have duplicate value in a cell we all know, Vlookup will pick up against the first item would be matching in loopkup array....So here is solution for you all...
e.g.
in Column A we have field called company....
Column A Column B Column C
Company_Name Value
Monster 25000
Naukri 30000
WNS 80000
American Express 40000
Bank of America 50000
Alcatel Lucent 35000
Google 75000
Microsoft 60000
Monster 35000
Bank of America 15000
Now if you lookup the above dataset, you would see the duplicity is in Company Name at Row No# 10 & 11. So if you put the vlookup, the data will be picking up which comes first..But if you use the below formula, you can make your lookup value Unique and can pick any data easily without having any dispute or facing any problem
Put the formula in C2.........A2&"_"&COUNTIF(A2:$A$2,A2)..........Result will be Monster_1 for first line item and for row no 10 & 11.....Monster_2, Bank of America_2 respectively....Here you go now you have the unique value so now you can pick any data easily now..
Cheers!!!
Anil Dhawan

Resources