I have the following input data:
I want to get a formula that can sort out descending order values for the factors across the three treatments.
For a particular factor, the formula should return A for six (6) consecutive descending ordered values within the treatment, B for four (4) consecutive descended order values, C for three (3) consecutive descended ordered values, and blank otherwise.
Here is the expected output from the input data sample:
Notes:
I'm using office 365, please consider that in your answer
I need a formula with drag and drop than doing it manually because in some cases, the factors are up to 100 and more than 70 treatments...
The following formula will return the number of values that appear in consecutively descending order:
=LET(
Order,MMULT(IFERROR(N(C3:H3>D3:H3),0),N(COLUMN(C3:H3)>=TRANSPOSE(COLUMN(C3:H3)))),
Score,UNIQUE(FILTER(Order,Order>0),1,1),
IF(SUM(ISERROR(Score))=0,COUNT(Score)+2,0)
)
So that the resulting table will look like this:
You can then use an IF() or SWITCH() or INDEX() function solution to categorize the numerical scores into the classes 'A', 'B', and 'C'.
This would be a partial answer because it cannot be dragged to right.
I've used old functions from Excel 2007 so this should work for you, but I'm pretty sure that with advanced functions this solution can be improved and be dragged to right.
The formula I've used for Treatment 1 is:
=IF(--(CONCATENATE(B2;C2;D2;E2;F2;G2)="654321")>0;"A";IF(O(ISNUMBER(FIND("6543";CONCATENATE(B2;C2;D2;E2;F2;G2)));ISNUMBER(FIND("5432";CONCATENATE(B2;C2;D2;E2;F2;G2)));ISNUMBER(FIND("4321";CONCATENATE(B2;C2;D2;E2;F2;G2))));"B";IF(O(ISNUMBER(FIND("654";CONCATENATE(B3;C3;D3;E3;F3;G3)));ISNUMBER(FIND("543";CONCATENATE(B3;C3;D3;E3;F3;G3)));ISNUMBER(FIND("432";CONCATENATE(B3;C3;D3;E3;F3;G3)));ISNUMBER(FIND("321";CONCATENATE(B3;C3;D3;E3;F3;G3))));"C";"")))
My argument separator is the ; so you may need to replace those with commas
Related
I have array of numbers in a single column like this:
I want only that numbers for which corresponding negative numbers exist. If number exist 2 times, but negative number exist only one time, then I wanted to retain one positive and one negative number. Similarly, if number exists 3 times, and negative number appears only two times, then I want 2 set of numbers including positive and negative. In this case, I wanted to get output:
5 2 -2 -5
Orders of numbers are not relevant for me. Please do not use VBA. You can create multiple column and apply filter at the end.
Thank you for the response, but I wanted to get the data in column next to the values. Like:
5
2
-2
-5
Please help.
Here's another Office 365 solution:
Name the data range DATA
Put this formula anywhere: =CONCAT(REPT(-ROW(A1:A100)&" "&ROW(A1:A100)&" ",COUNTIF(DATA,"="&ROW(A1:A100)*IF(COUNTIF(DATA,"="&-ROW(A1:A100))<COUNTIF(DATA,"="&ROW(A1:A100)),-1,1))))
That will output the pairs into one cell.
Here's a slightly modified Step 2, which excludes duplicates: =CONCAT(IF((COUNTIF(DATA,"="&-ROW(A1:A100))>0)*(COUNTIF(DATA,"="&ROW(A1:A100))>0),-ROW(A1:A100)&" "&ROW(A1:A100)&" ",""))
Looks like this:
The data doesn't need to be sorted. Both methods work up to 100, but you can easily expand that by changing A100 to A1000 or whatever you need.
Use the vlookup formula to identify the rows, and you can use the Filter & Unique formula to get the list, or a pivot table.
First, immediately next to your data use the formula:
=vlookup(A1*-1,$A$1:$A$1,1,0)
For non-365:
This will produce an error for each instance that doesn't have a match. You can filter at this point to get your list from the existing table. You can also create a pivot table under the Data tab of your ribbon and inserting a pivot table. Filter the #N/A from there to get an exclusive list without hidden rows.
For 365:
You can use the following combination of formulas to get the exclusive list as well.
=UNIQUE(FILTER(B1:B8,ISNUMBER(B1:B8)),0,0) or =UNIQUE(FILTER($B$1:$B$8,ISNUMBER($B$1:$B$8)),0,0) should yield the same results
As ScottCraner mentioned, you can circumvent the helper column in 365 by modifying the formula a bit more:
=UNIQUE(FILTER(A1:A8,ISNUMBER(MATCH(-A1:A8,A1:A8,0)),"")
The Match here is doing something similar to the Vlookup, but housing that logic within the formula, so it's a cleaner solution in my opinion.
Using your data the result was { -5,-2,2,5 }
These are spill formulas so you only need to put it in one spot and it will expand the formula over the adjacent cells below where it's entered for however many cells needed to list all the unique numbers that occur. It takes into account the negatives and so on. This may be a 365 formula, so if you're on another version of excel it may not work.
Edit: Adjusted the instructions to fully address the question.
Here is my problem:
I need to search using or logic in a 2d array for any row that contains any given substring(s), and sum that row's sum column as a result.
I have a column, Hours, that I would like to sum if the column Name OR the column Description contain any number of criteria. So far my (ugly) solution is (pardon the formatting):
SUM(SUMIFS(B16:B100,C16:C100,{"(asterisk)Crit1(asterisk)","(asterisk)Crit2(asterisk)"}),SUMIFS(B16:B100,D16:D100,{"(asterisk)Crit1(asterisk)","(asterisk)Crit2(asterisk)"}))
This by itself is not bad, and with only 2 columns isn't horrible. But, some of you may have seen that this can cause double-counts if the criteria is in both columns, which I do not want.
So my question: Can I do this in such a way where I can search for criteria in multiple columns, and if they exist in any column, then sum the sum range, only once?
Try (untested since you show no data):
=SUM(B16:B100*((ISNUMBER(SEARCH({"Crit1","Crit2"},C16:C100))+ISNUMBER(SEARCH({"crit3","Crit4"},D16:D100)))>0))
Adding comparisons is like doing an OR; by comparing the sum of the comparisons to zero, we determine if any single one is present.
The formula may need modification if you have criteria which can be miscounted.
For example:
Note that Crit1 will return a match for Crit1, Crit101, etc. Depending on your actual data, a formula modification might be possible; or a UDF might be more practical.
Let's say 3 columns (A, B, C) are dynamic arrays and I want to create a fourth/final dynamic array formula that is the sum of these 3 columns for each row in column D. For clarity, I am looking for the row-by-row sum of each row in this final column.
This will work:
=A2#+B2#+C2#
How can the same be accomplished by using the SUM function? The reason I ask is that this is easier to use on larger ranges of data.
The following gives a #REF! error:
=SUM(A2:C2#)
New Edit:
With the addition of BYROW and LAMBDA we can do this a little easier than my original answer below:
=BYROW(A1#:C1#,LAMBDA(x,SUM(x)))
The BYROW passes each row into the LAMBDA which does the SUM iteratively and returns an array:
Original Answer
The problem is that SUM,MAX,MIN all allow arrays and do the whole on the full array. So we need to use something that uses arrays and spills individual results. That is what MMULT was built for.:
=MMULT(A2#:C2#,TRANSPOSE(COLUMN(A2:C2)^0))
Just realized with the dynamic arrays we have SEQUENCE:
=MMULT(A2#:C2#,SEQUENCE(COLUMNS(A2:C2),,1,0))
Try this for sums per column (assuming A1# is the dynamic range with the source data):
=SUBTOTAL(9,OFFSET(A1#,0,SEQUENCE(1,COLUMNS(A1#))-1,ROWS(A1#),1))
Just change the first argument of the SUBTOTAL function to use any of the aggregation functions available (min, max, average, etc.). With some tweaks, this can be made to work for row totals.
When I tried Scott Craner's formula above I received a VALUE# error, possibly related to the fact that I was testing it on data columns of different dynamic lengths.
Even though the expression A2#:C2# returns a matrix of width 3 columns, and height of whichever of the three columns has the most rows (filling in zeros for any blank cells), MMULT didn't seem to like that expression and resulting matrix as the first argument. However I found that I was able to modify it as follows to make it work:
=MMULT((A2#:C2#*1),SEQUENCE(COLUMNS(A2:C2),,,0))
Absolute legend. I've been trying to work this out. Thank you so much. I have never used MMULT before, only SUMPRODUCT for similar problems. My problem was to dynamically sum up the last few columns in a spill table and I was able to adapt your solution.
In terms of the question above, if the three spill columns were one spill table with rows and columns in the one spill range it would be:
=MMULT(A2#,SEQUENCE(ROWS(A2#)),SEQUENCE(COLUMNS(A2#)),,1,0))
I have a large table of 12 digit numbers and associated info
I have a small list of 10 and 11 digit numbers (the first and/or last digits were cut off) - I'm attempting to cross these two lists to identify the items on the small list
normally, I'd use an index match to bring the associated info out of the table into the list, but because today I have only partial numbers in my list, I can't get the formula to work
I've seen other examples here that search for partial text strings contained within a range, but I haven't been able to adapt those formulas to my data. wildcards don't seem to work with numbers.
Many thanks for your input, and apologies in advance if I failed to find an existing solution on the site.
To match partial numbers inside a number range, like you do with strings, you can use an array formula with INDEX/MATCH, by composing a temporary array that converts the numbers into strings.
Say column A is your 12 digit numbers column, and you want to match the sequence 1234567890 and retrieve the value from column B, This CSE formula works:
=INDEX($B$2:$B$9999, MATCH("*1234567890*",""&$A$2:$A$9999,0))
CtrlShiftEnter
Although you can use full columns A:A and B:B, this should be avoided as much as possible with array formulas, because they're slow. Full columns mean computing and operating arrays of more than a million entries, so avoid it. Also note the "expensive" conversion from numbers to strings (all numbers in the $A$2:$A$9999 are converted to strings here).
To use a cell reference, say D2, instead of the harcoded 1234567890, the formula should be used like this:
=INDEX($B$2:$B$9999,MATCH("*"&D2&"*",""&$A$2:$A$9999,0))
I have around 30 numbers which are either 1, 2 or 3 digits which are codes. These codes are attached in front of other numbers. I want to know what code is in front of a number, for example for the number 35467036 the first two digits matches with the code 35. So I want the output for that to be 1.5.
This is my current setup, I have a table with all the codes followed by the output in the next column. If all the codes were three digits long I could just do this =VLOOKUP((LEFT(E6,3)&"*"),D1:E3,2,FALSE) but they are unfortunately not.
I have also tried using nested IF statements but I can only go so far as 7 levels.
Will this only be possible in VBS or is there anther way?
Edit:
The code column is formatted to text. If I enter the value 3 into LEFT it does not work for two digits. Is there anyway I can make it work for 1, 2 and 3 digit codes? Also the codes do not overlap, for example, there isn't going to be 96 and 965 in the code table.
Seven nested IFs as a limit points to a very old version of Excel. You may want to consider upgrading to a version that is still supported in this millennium.
But your main problem is that the data type of your lookup value is text, because you concatenate a string with a wildcard. Whereas your Lookup Table's first column is probably made up of numbers.
In order to solve this you will need to add a Text column to your lookup table that represents the numeric value as a text value.
IF you want to use Vlookup, that helper column will need to be the first column of your lookup range.
You can use an Index/Match instead of Vlookup to be independent of the column order, as this screenshot shows:
Column H shows the formula that has been applied in column G.
Edit:
According to the screenshot you posted, you want to look up from the table in columns E to F and this table only has the short codes. Therefore, it makes no sense to add a wildcard to the lookup value. You just need to extract the value you want to use for the lookup.
If you want to lookup only two digits, then you need to extract only two digits. Adding a wildcard does nothing to remove the third digit.
In the screenshot below, a helper column feeds the LEFT() function the number of characters to extract, then uses that value in the VLookup.
=VLOOKUP(LEFT(A1,B1),$E$1:$F$5,2,FALSE)
=INDEX($G$2:$G$5,
SMALL(
IF(LEFT(A1,3)*1=$F$2:$F$5,ROW($G$2:$G$5)-1,
IF(LEFT(A1,2)*1=$F$2:$F$5,ROW($G$2:$G$5)-1,
IF(LEFT(A1,1)*1=$F$2:$F$5,ROW($G$2:$G$5)-1))),1))
=INDEX(LookupValues,Small(ArrayOfRowsFromIfStatements,FirstRow))
This is an array formula so you will need to use Ctrl+Shift+Enter while still in the formula bar.
We use If to build an array of Row numbers where the conditions match or return FALSE if not. The Small function then returns the smallest result in the array which will be the first row where conditions match.
We then index the results returning that row number (-1 deducted from rows to offset the headers).
If your numbers in column A are always 6 digits + the code length you can use this:
=VLOOKUP(--LEFT(A1,LEN(A1)-6),E2:F5,2,FALSE)