Get column by finding value in the row - excel

In Excel, I've looked into hlookup, vlookup, match and index but none of these functions do following:
I need to find a text value in A1:Z1 and get the column of it. For example, I found the value in F1, then I want a result F:F.
EDIT: This is the function I want it to be added to:
=COUNTIFS(Source!B:B;Result!C3;Source!AT:AT;Result!$D$2)
I need the Source!B:B and alternatively Source!AT:AT be a search function that looks for a specific value in my table row and column in different sheet (Source).

INDEX function can return a whole column, e.g. assuming you want to search for "x" in A1:Z1 try
=INDEX(A:Z;0;MATCH("x";A1:Z1;0))
Note: this doesn't return a text string like F:F, it returns a reference to the column in question which you would normally use within a function that expects a whole column reference, e.g. SUM, SUMIF, LOOKUP etc.
Edited: You can use the above in COUNTIFS function like this:
=COUNTIFS(INDEX(Source!A:Z;0;MATCH("x";Source!A1:Z1;0));Result!C3;Source!AT:AT;Result!$D$2)
That makes the first range dynamic (between columns A and Z - extend as required) based on where "x" is first found in Source!A1:Z1, e.g. if "x" is first found in J1 then COUNTIFS uses Source!J:J for the first range - you can do that for any of the ranges in COUNTIFS

You can use this (it will return E:E, which you could then use INDIRECT with to return a workable range). This uses "words" as the word to match and stop at the first match:
=SUBSTITUTE(
ADDRESS(1,MATCH("words",$A$1:$Z$1,0),4),"1",
":"&
SUBSTITUTE(ADDRESS(1,MATCH("words",$A$1:$Z$1,0),4),"1",""))
This works by using MATCH to find the position of the occurrence in your range (in this case, 5), and then using ADDRESS, with row_num = 1 and column_num = the result of the match. Using 4 for the abs_num argument ensures that the returned value will be without the $'s. You then substitute out the 1 in E1 with ":" and concatenate it with the same formula, giving you E:E as a string. You can then do look-ups based on that range (using INDIRECT), such as this:

Related

Check contents of one cell to see if they contain a value from an array of cells

I'm running an excel formula and having issues with a #Spill error. The idea is that I have a column of cells that contain a ton of different numbers. I have another column with a bunch of String values that contain numbers as well.
For example,
Col A
Col B
1
String.10
2
String.1
3
String.3
4
String.6
The output, after running the formula, should return records of:
String.1
String.3
as 1 and 3 are contained in a cell.
The formula:
=IF(ISNUMBER(SEARCH($A$2:$A$10,B2)), "Yes", "No")
The idea is that I have a static range of cells to compare to and a way longer list of String.'numbers'. Why would this function result in a spill error?
Although this seems to be a trivial task, there are some pitfalls that need to be taken into account. For example, the problem that the search for "1" will be TRUE for both String.10 and String.1.
One approach to solving this issue in one formula could be as follows, combining, in particular, the following functions: TEXTJOIN(), BYROW(), and FILTER(). I also use some other functions that come in handy to find the exact string, etc.
Assuming that the data is stored in the range A2:B5, you can enter the following formula in C2, for example:
=TEXTJOIN(";",TRUE,
BYROW(A2:A5,LAMBDA(rowN,
FILTER($B$2:$B$5,
EXACT(rowN,RIGHT($B$2:$B$5,LEN($B$2:$B$5)-SEARCH(".",$B$2:$B$5)))=TRUE,""))))
The output of this formula looks as follows: String.1; String.3.
The TEXTJOIN() function combines the output of the BYROW() function separated by e.g, ";". In the BYROW() function, you first specify the array to which you want to apply the function specified in the LAMBDA()statement. In this context, rowN is then in the following simply used as the name for this particular array. The FILTER() function is used to filter data from a specified range that meets a certain criterion. The criterion in this context is that the number (specified in column A) matches the numeric part of the string in column B. To extract only the numeric part of the string, the number after the "." is extracted by combining the RIGHT(), LEN(), and SEARCH() functions. Subsequently, it is important to use the EXACT() function to ensure that when searching for "1", only this particular row is recognized as TRUE and not also the number "10", which also contains a 1.
Variation of the specification to get the output in a different format:
If you do not want the strings combined, you can simply delete the TEXTJOIN() function, which will return the corresponding string or an empty cell:
=BYROW(A2:A5,LAMBDA(rowN,FILTER($B$2:$B$5,EXACT(rowN,RIGHT($B$2:$B$5,LEN($B$2:$B$5)-SEARCH(".",$B$2:$B$5)))=TRUE,"")))
If you want to return "Yes" or "No", you can put the formula into an additional IF() statement as follows:
=IF(BYROW(A2:A5,LAMBDA(rowN,FILTER($B$2:$B$5,EXACT(rowN,RIGHT($B$2:$B$5,LEN($B$2:$B$5)-SEARCH(".",$B$2:$B$5)))=TRUE,"")))<>"","Yes","No")
In addition, I give some flavor for the spill error. This occurs because you are looking for a specific string in an array of values. Therefore, the output returns "Yes" and "No" for each row. In your particular case (the formula you presented above), an array containing 9 times "Yes" or "No" will be returned. Thus, if you then copy the formula down, you will get the spill error because you have stored something in the row and it is not possible to spill the 9 values down.
=BYROW($B$2:$B$5,LAMBDA(B,ISNUMBER(XMATCH(--(INDEX(TEXTSPLIT(B,".",,),2)),$A$2:$A$10))))
This will spill results (TRUE/FALSE) for all values.
It splits the text in column B and shows the string after the .. It's then converted from text to number by using --() and that value is matched with the values in column A. If it matches it returns the row number, so ISNUMBER is TRUE.
If no match is found, it throws an error, which is not a number, so ISNUMBER is FALSE.
Using LET will make it easier to update the ranges Col_A and/or Col_B. (You may even want to use a FILTER for Col_B: Col_B,DROP(FILTER(B:B,B:B<>""),1)) :
=LET(
Col_A,A2:A10,
Col_B,B2:B5,
BYROW(Col_B,LAMBDA(B,
ISNUMBER(
XMATCH(--(INDEX(TEXTSPLIT(B,".",,),2)),
Col_A)))))

=ISNUMBER(SEARCH()) formula not working properly

Basically, im trying to search if values from column b is contained in cells on column a
I am currently using the formula
=ISNUMBER(SEARCH(B1,$A:$A))
and using it inside a conditional formatting to highlight the cells in column A that contains strings from column B. But it is not highlighting the correct cells
any advice?
Problem is that your ISNUMBER(SEARCH(…. formula is returning an array of values {FALSE;TRUE;FALSE;FALSE;...} one return for each item in within_text. You need to know if any of those items match.
So, with your formula, consider the array formula modification
=OR(ISNUMBER(SEARCH(B1,$A:$A)))
Since this is an array formula, you need to "confirm" it by holding down ctrl + shift while hitting enter. If you do this correctly, Excel will place braces {...} around the formula as observed in the formula bar
If you don't like to use the CSE entry method, you could use this formula which will return zero for no matches, or be non-zero for any matches:
=SUMPRODUCT(-ISNUMBER(SEARCH(B1,$A:$A)))
Excel's SEARCH function is used to find the position of one string within another string. Generally you use it like this:
=SEARCH("String A", "A Longer String Containing String A")
This will return the character index where first string starts within the second string, which in this case would be 28.
What you really need is a VLOOKUP. Since you're doing a textual search (substring), you need your range to be of text type instead of number.
You should do the following:
Add an extra column to the right of Column A and use TEXT function to convert entries to textual form:
=TEXT(A1, "#")
Now you can use VLOOKUP to perform a substring-match in this textual range. VLOOKUP supports wildcards when you do not ask it to perform an exact match (4th argument should be FALSE). Here is your formula then:
=VLOOKUP("*" & C1 & "*",$B:$B,1,FALSE)
Note that I have passed column B (textual column) as the lookup range, whereas C1 is the cell containing the text that you want to search.
This method also has the additional advantage that it returns the actual matched entry from the range so you don't have to find it manually.
Once you have your results, you can apply conditional formatting to it.
Highlight column A (or the relevant range in column A starting cell A1) with the first cell (which is A1 in this case) as the active cell, use the following formula as the conditional formatting rule:
=(SEARCH($B1,$A1)*(LEN($B1)>0))>0
The logic is to first search the given sub-string from the main string, then multiple the result by LEN($B1)>0 to exclude the result of 1 returned for blank cells in column B.
Note: Conditional Formatting works in array fashion so even though the formula only looks at values in the first row of the range, as long as you use the relative (or in some cases absolute) cell references correctly and highlight the result range correctly before setting up the rule, the rule will be applied across in the same way as for the first row of the array as demonstrated in this example.

Giving specific values of a cell reference INSIDE lookup array parameter of MATCH function

I want to know column number of a particular text within an array in a sheet.Hence i used the MATCH function
=MATCH (lookup_value, lookup_array, [match_type])
The 2nd Parameter expects a lookup_array.Eg of a valid input: C5:N5
I dont want to specify "C" as the starting column of the array nor Row number 5 as the row number.I want it to be dynamic.I want to give a absolute column number & absolute row number.
Is there any way to do this.I have tried a lot in vain.
If your dynamic cell references are in A1 and B1 this should work...
=MATCH(0,INDIRECT(A1):INDIRECT(B1),0)

VLOOKUP in last column of Table_array

I understand that VLOOKUP searches the first column of a table in order to find a value, then it grabs the value from the same row and a different user-specified column. The following code returns data from the 2nd column, column B.
VLOOKUP(5,$A$2:B100,2)
Is there a way to set the return column to the last column of the input table? Something like the following, which would return data from columns B, P, and AC, respectively.
VLOOKUP(5,$A$2:B100,end)
VLOOKUP(5,$A$2:P100,end)
VLOOKUP(5,$A$2:AC100,end)
Alternatively, is there a way to grab the current column number and use that as an index?
VLOOKUP(5,$A$2:B100,current_column_number)
I'd like to write one VLOOKUP formula and then be able to drag it right across the spreadsheet, so that B100 becomes C100, D100, E100, etc. and the column lookup changes accordingly.
Update
I can do the alternate approach using the COLUMN function, but it requires programming a fixed offset and doesn't seem as robust. I'd still like to know if there is an "end" option.
=VLOOKUP(5,$A$2:B100,COLUMNS($A$2:B100))
Unfortunately you cannot simply drag it, you'll need to replace as there are two equivalent ranges written in the nested function.
The COLUMNS effectively counts the columns in the range giving the exact result needed for the VLOOKUP's end variant.
EDIT to show OP what a simple drag function would be like:
Function VLOOKUP2(Expected As Variant, Target As Range)
x = Target.Columns.Count
VLOOKUP2 = Application.WorksheetFunction.VLookup(Expected, Target, x)
End Function
You can use the Excel COLUMN() function to convert the column reference to a numerical index into the VLOOKUP table. Try this:
VLOOKUP(5, $A$2:B100, COLUMN(B2))
VLOOKUP(5, $A$2:P100, COLUMN(P2)
VLOOKUP(5, $A$2:AC100, COLUMN(AC2))
In pratice, you can just enter the first formula I gave above and then copy to the right. Each copy will automatically shift the column number to the end.
You could use the count function while holding ($) one side of the count range, thus giving you an integer that Vlookup can use.
Something like:
VLOOKUP(5,$A$2:B100,COUNT($A$2:A2))
You may need to add a + or - 1 to the count function depending on where your range starts.
It's effectively doing the same thing you already did with the array for the vlookup

Looking up a value in a specified column

Something I've wanted to do quite a bit lately, and can't work out how to do, is MATCH in a column I pass as an argument. Essentially, I have a two dimensional array, and I want to be able to find the first occurrence of a given value in the nth column, for any given value of n, and return the row number it occurs at. Alternatively (and more-or-less equivalently), I want to be able to search in the column with a given column header. Is there any way to do this?
Effectively, I want to simulate the non-existent function =MATCH(lookup_value,lookup_array,lookup_column,[match_type])
I've kludged together a horrible bodge job using INDIRECT, which works, but offends me horribly.
=MATCH(lookup_value,INDIRECT("R"&<top of array>&"C"&<left of array>+<column reference>&":R"&<bottom of array>&"C"&<left of array>+<column reference>,FALSE),FALSE)
This formula should work for you and will avoid INDIRECT. Anytime you can avoid using Indirect, I recommend doing so.
=MATCH(lookup_value,INDEX(lookup_array,0,MATCH(lookup_header,array_headers,0)),0)
If you aren't looking up the column by column header and just have the column number, then it becomes easier:
=MATCH(lookup_value,INDEX(lookup_array,0,column_number),0)
You could do something like this:
Set findCell = ActiveSheet.Range("A:Z").Find(What:="term_to_search")
Will select a header based on your search term.
Set range = ActiveSheet.Range(findCell, findCell.Offset(DEF_MAX_ROWS, 0))
Set up a range which will search from that header down a whole column.
For column references beyond Z you might switch notation (Excel Options, Formulas, Working with formulas and check R1C1 reference style) and, assuming the value to be looked up is in 'A1' (R1C1) with the column number in 'A2' (R2C1) apply:
=MATCH(R1C1,INDIRECT("C"&R2C1,0),0)
to save some complexity in converting a string of two or three characters into the relevant column number.
Say we have a two dimensional array: B3:E17 and we wish to locate Happiness in the third column of that array.In G1 enter:
B3:E17
In G2 enter:
3
In G3 enter:
=ADDRESS(ROW(INDIRECT(G1)),COLUMN(INDIRECT(G1))+$G$2-1) & ":" & ADDRESS(ROW(INDIRECT(G1))+ROWS(INDIRECT(G1))-1,COLUMN(INDIRECT(G1))+$G$2-1)
This will display the address of that third column. Then in G4 enter:
=MATCH("Happiness",INDIRECT(G3),0)
For example:
You can specify a range in a formula using the INDIRECT function. So, for example, if you put the letter designation for the column you want to search in cell A75, you could use:
=MATCH("Value_To_Match", INDIRECT(A75 & ":" & A75), 0)
So, if the value in A75 is G, the string built up in the INDIRECT call is G:G, and the MATCH will look through column G for "Value_To_Match" and return the row number in which it's found.
Using this idea, you can put a formula into A75 that generates the column designation for the column you want to search. For example, if your column headers are all in row 1, and the header you want to search for is in A74, you can do:
=CHAR(MATCH(A74, 1:1, 0) + 64)
using the CHAR function to convert numbers into ASCII characters, so 65 becomes A, 66 becomes B, etc. Note that this will only work if you don't have columns past Z. You'd need a more fussy formula to do the right thing with AA, etc.
You can overcome the annoyances of dealing with column letters by using R1C1 notation instead, which you can activate by adding a second parameter of FALSE to the INDIRECT expression. Now, instead of specifying your column by a letter, you'll specify it using a number. This simplifies the column-finder in A75:
=MATCH(A74, 1:1, 0)
and also the INDIRECT expression in your overall MATCH:
=MATCH("Value_To_Match", INDIRECT("C" & A75, FALSE), 0)

Resources