Check whether a cell contains a substring - excel

Is there an in-built function to check if a cell contains a given character/substring?
It would mean you can apply textual functions like Left/Right/Mid on a conditional basis without throwing errors when delimiting characters are absent.

Try using this:
=ISNUMBER(SEARCH("Some Text", A3))
This will return TRUE if cell A3 contains Some Text.

The following formula determines if the text "CHECK" appears in cell C10. If it does not, the result is blank. If it does, the result is the work "CHECK".
=IF(ISERROR(FIND("CHECK",C10,1)),"","CHECK")

For those who would like to do this using a single function inside the IF statement, I use
=IF(COUNTIF(A1,"*TEXT*"),TrueValue,FalseValue)
to see if the substring TEXT is in cell A1
[NOTE: TEXT needs to have asterisks around it]

This formula seems more intuitive to me:
=SUBSTITUTE(A1,"SomeText","") <> A1
this returns TRUE if "SomeText" is contained within A1.
The IsNumber/Search and IsError/Find formulas mentioned in the other answers certainly do work, but I always find myself needing to look at the help or experimenting in Excel too often with those ones.

Check out the FIND() function in Excel.
Syntax:
FIND( substring, string, [start_position])
Returns #VALUE! if it doesn't find the substring.

It's an old question but I think it is still valid.
Since there is no CONTAINS function, why not declare it in VBA?
The code below uses the VBA Instr function, which looks for a substring in a string. It returns 0 when the string is not found.
Public Function CONTAINS(TextString As String, SubString As String) As Integer
CONTAINS = InStr(1, TextString, SubString)
End Function

I like Rink.Attendant.6 answer. I actually want to check for multiple strings and did it this way:
First the situation: Names that can be home builders or community names and I need to bucket the builders as one group. To do this I am looking for the word "builder" or "construction", etc. So -
=IF(OR(COUNTIF(A1,"*builder*"),COUNTIF(A1,"*builder*")),"Builder","Community")

This is an old question but a solution for those using Excel 2016 or newer is you can remove the need for nested if structures by using the new IFS( condition1, return1 [,condition2, return2] ...) conditional.
I have formatted it to make it visually clearer on how to use it for the case of this question:
=IFS(
ISERROR(SEARCH("String1",A1))=FALSE,"Something1",
ISERROR(SEARCH("String2",A1))=FALSE,"Something2",
ISERROR(SEARCH("String3",A1))=FALSE,"Something3"
)
Since SEARCH returns an error if a string is not found I wrapped it with an ISERROR(...)=FALSE to check for truth and then return the value wanted. It would be great if SEARCH returned 0 instead of an error for readability, but thats just how it works unfortunately.
Another note of importance is that IFS will return the match that it finds first and thus ordering is important. For example if my strings were Surf, Surfing, Surfs as String1,String2,String3 above and my cells string was Surfing it would match on the first term instead of the second because of the substring being Surf. Thus common denominators need to be last in the list. My IFS would need to be ordered Surfing, Surfs, Surf to work correctly (swapping Surfing and Surfs would also work in this simple example), but Surf would need to be last.

Why not simply
COUNTIF(A1,"*xyz*")
This searches for any appearence of "xyz" in cell A1.
It returns "1" when found, and "0" when not found.
Attention, the search is not case sensitive, so any of xyz, XYZ, XyZ, and so on will be found. It finds this as substrings in the cell, so also for abcxYz you get a hit.
If you do not want to write your search string into the formula itself, you can use
COUNTIF(A1,"*" & B1 & "*")
and enter your search string into B1. - Attention, when B1 is empty, the formula will return "found" ("1") as the search string is then read as "**".

Interesting *
=COUNT(MATCH("*SomeText*",A1,))
=COUNTA(VLOOKUP("*SomeText*",A1,1,))
=COUNTA(HLOOKUP("*SomeText*",A1,1,))
this returns 1 if "SomeText" is contained within A1.

Here is the formula I'm using
=IF( ISNUMBER(FIND(".",A1)), LEN(A1) - FIND(".",A1), 0 )

Related

if statement gives a value for blank cells

I am categorizing my excel output by the following if formula:
=IF(M13>0,8;">80%";IF(M13>0,5;"80%-50%";IF(M13>0,5;"50%-20%";"<20%")))
My data has some blank cells, and I would like my formula to return a blank cell in this case. At the moment, however, the formula returns a <20% value (see picture). How can I fix this?
The answers and proposed solutions here work in your specific case. I wanted to provide a more generalized approach to prevent this problem with any nested IF() structure, that is not unique to just your use case.
The potential problem with starting your formula with a IF(M13=""...) condition is that it is not generalized. You always want to skip this cell if it has a space, or a non-printable character, or a text value, not just if it is blank. Any non-numeric or out-of-range value should result in a "".
Thus the generalized form of your formula could be:
=IF(ISNUMBER(M13); IF(M13>0,8; ">80%";IF(M13>0,5; "80%-50%";IF( M13>0,2; "50%-20%"; "<20%")));"")
Or, for readability, I have added spaces and alt-returns as non-breaking carriage returns to the exact same formula as well:
=IF(ISNUMBER(M13);
IF(M13>0,8; ">80%";
IF(M13>0,5; "80%-50%";
IF( M13>0,2; "50%-20%"; "<20%"
)));"")
The US English notation for this would be:
=IF(ISNUMBER(M13), IF(M13>0.8, ">80%",IF(M13>0.5, "80%-50%",IF( M13>0.2, "50%-20%", "20%"))),"")
IF you have Excel 2019 or later
A better approach is to use the recent IFS() function as a way of creating the IF-THEN-ELSEIF logical construct instead of nested IF()s. Here it is in the same alt-return notation for readability:
=IFS(
NOT(ISNUMBER(M13));"";
M13>0,8; ">80%";
M13>0,5; "80%-50%";
M13>0,2; "50%-20%";
TRUE ; "<20%"
)
Which without the alt-returns is:
=IFS(NOT(ISNUMBER(M13));"";M13>0,8;">80%";M13>0,5;"80%-50%";M13>0,2; "50%-20%";TRUE;"<20%")
The conditions are evaluated and tested in order, so you create one final "TRUE" condition/result pair that means "if you made it past all the other tests and still ended up here, then the result is (a) numeric and (b) less than or equal to 0,2."
Add a check for blank cells:
=IF(M12="";"";IF(M12>0,8;">80%";IF(M12>0,5;"80%-50%";IF(M12>0,2;"50%-20%";"<20%"))))
Here is the formula version where the formula separator is , and the decimal separator is .:
=IF(M12="","",IF(M12>0.8,">80%",IF(M12>0.5,"80%-50%",IF(M12>0.2,"50%-20%","<20%"))))

Excel - VLOOKUP return based on partial string

I am trying to get VLOOKUP to return a value based on a partial string. So I want to say: look up this string, look in the list and if you find a partial string matching it, return the date next to it. But not having much luck. In my example, B2 should show: April 9th as the first bit of the string in D2 matches.
Try this one... Will help you
=VLOOKUP(LEFT(A3,FIND(" ",A3,FIND(" ",A3)+1)-1),$D$3:$E$5,2,0)
Use:
=VLOOKUP(MID(A2,1,FIND(" ",A2,FIND(" ",A2)+1)-1),$D$2:$E$4,2,FALSE)
Results:
Or you can do the other way around and use combination of INDEX and MATCH (with wildcard match) - look at the picture:
=INDEX($D$1:$E$4,MATCH(D2&"*",$A$2:$A$4,0)+1,2)
INDEX MATCH example
Advantage is of this is that you do not assume a given pattern of your values. So it does not matter whether it is SPXL APR19 59P or SPXL APR19_____59P.
You can also use the asterisk on both sides "*"&[]&"*", so then you'll do an inside search.

Have COUNTIFS ignore all blank cells (= empty cells and cells containing "")

I want to get a formula with COUNTIFS, like
=COUNTIF(A1:A3,"<>"&"")
such that when A1 = 2, A2 = "", A3 = empty, it returns 1.
Notes:
A2 contains an empty string, as the result of a formula. A3 is a blank cell, with no formulas in it.
The formula posted returns 2.
I tried using various numbers of double quotes. I always get 2.
I tried using &CHAR(34)&CHAR(34). I get 2.
The solution posted in How do I get countifs to select all non-blank cells in Excel? is what I tried, it returns 2 (not useful).
The formula would actually be =COUNTIFS(range1,cond1,range2,cond2), that is why I cannot use something like
=ROWS(A1:A3)-COUNTIF(A1:A3,"") or =ROWS(A1:A3)-COUNTBLANK(A1:A3) (see this).
range1 and range2 would come from expressions with INDIRECT, but that is probably not relevant.
I have worked it out with =SUMPRODUCT(--(expression1),--(ISNUMBER(A1:A3))), but I am specifically asking about the possibility of using COUNTIFS. Discrimination of number vs. text (e.g.) is not relevant at this point.
Blank vs. Empty string is the source of "troubles" (see, e.g., this).
Excel itself is somewhat ambiguous with respect to the definition of BLANK. In my example, ISBLANK(A2) returns FALSE, but COUNTBLANK(A2) returns 1.
I am not interested in a user Function.
Use a SUMPRODUCT function that counts the SIGN function of the LEN function of the cell contents.
    
As per your sample data, A1 has a value, A2 is a zero length string returned by a formula and A3 is truly blank.
The formula in C2 is,
=SUMPRODUCT(SIGN(LEN(A1:A3)))
I was having this exact problem, and I just found out about the "?*" wildcard which searches for any one or more characters, thus avoiding the empty string problem--genius! See Jonathan Gawrych's answer (posted right after the selected answer) here:
Excel Countif Not equal to string length of zero
Not sure if this works for the OP, since it looks like the value in A1 could need to be handled as a number not a string, but it might help anyone else who arrived here looking for a text-parsing solution.
Is using SUM instead of COUNTIFS an option? If so, I've found it to be much more flexible for filtering data sets. For example:
=SUM(IF(NOT(ISBLANK(A1:A3)),IF(NOT(ISTEXT(A1:A3)),1,0),0))
(entered as an array formula). IF(NOT(ISBLANK(x))... filters out non-blanks, then IF(NOT(ISTEXT(x))... filters out non-text. Whatever survives the filters is counted by summing 1. You can add as many filters as necessary. If you wanted to filter out only empty strings but include other text entries you could use a filter like
IF(ISTEXT(x),IF(LEN(x)>0,1,0),0)

Using substrings within an INDEX MATCH function

I'm trying to use an INDEX MATCH function to automate filling one spreadsheet using data from another. However, the sheet I am filling has people's names listed in two separate cells (e.g. "John" in A1, "Doe" in B1), while the sheet I am filling from has them listed as "DOE, JOHN Q." in one cell. A regular INDEX MATCH function would never give a result since no cell in the domain contains just the string "Doe." Is there any way to perform the function for cells that have the lookup value within the cell as a substring?
For reference, this is my attempt at this problem, which of course returns an error:
=INDEX(Sheet2!G2:Sheet2!G2340,MATCH(B3,ISNUMBER(SEARCH(B3,Sheet2!C2:Sheet2!C2340)),0))
I think you're on the right track. I think your initial formula should work but you need to make two changes:
Match criteria should be "TRUE" instead of "B3", as the result iof the ISNUMBER() function is a TRUE or FALSE
When entering the formula, press CTRL+SHIFT+ENTER instead of just ENTER, to make this an array function
Formula:
=INDEX(Sheet2!G2:Sheet2!G2340,MATCH(TRUE,ISNUMBER(SEARCH(B3,Sheet2!C2:Sheet2!C2340)),0))
If you wanted to search for both the first and last name, you could multiply two ISNUMBER() arrays together, and search for 1 instead of TRUE. This would get it to match both A3 and B3:
=INDEX(Sheet2!G2:Sheet2!G2340,MATCH(1,ISNUMBER(SEARCH(A3,Sheet2!C2:Sheet2!C2340))*ISNUMBER(SEARCH(B3,Sheet2!C2:Sheet2!C2340)),0))
Alternately, you could attempt to match both first and last names together with:
=INDEX(Sheet2!G2:Sheet2!G2340,MATCH(TRUE,ISNUMBER(SEARCH(B3&", "&A3,Sheet2!C2:Sheet2!C2340)),0))
Hope this helps. If I missed something, let me know!
You may concatenate the strings and provide that as an argument for MATCH or INDEX function. Still it would not work precisely as you do not have second names/initials like
MATCH(B1 & ", "& A1, Sheet2!C2:C2340, -1)
Although, you need to provide more details to get anything more from the StackOverflow community.

How to convert a word to a Unique Code in Excel using Formula without using VBA?

Say, I got 2 words A1:ddC, A2:DDC
I want to convert these 2 words into a unique code so that so that i can do the Case Sensitive Vlookup.
So i tried, =Code(A1) & it returned 100, but if i tried =Code("dady") then it also returns 100. It is cos =Code() only pic the first char of the word.
I want to convert a word to a Unique Code (could be ASCII code or any form of unique code).
So how to do that without using VBA?
As this is a hash, it would be possible for some strings to end up with the same value, but it would be unlikely.
Note that the row function uses 1:255 to generate a list of numbers from 1 to 255 - change this number if your strings end up longer.
=A1&SUMPRODUCT(IF(IFERROR(CODE(MID(A1,ROW($1:$255),1)),0)>96,1,0),POWER(2,ROW($1:$255)))
This has to be entered as an array formula using CTRL+SHIFT+ENTER - you will see {} around the formula if you have successfully done that.
This will produce a decimal representation of the upper and lower case letters, and this is then appended to the word itself - this will guarantee uniqueness, as the only way to have a word and number match is to have the same word and case, which means it was a duplicate in the first place.
With this, ddC = ddC & 1*2 + 1*4 + 0*8 = ddC6
DDC = DDC & 0*2 + 0*4 + 0*6 = DDC0
ddC (ddC with a space after it) = ddc & 1*2 + 1*4 + 1*8 + 0*16 = ddC 6
*WARNING: * This is not a solution to the titled question
"How to convert a word to a Unique Code in Excel using Formula without using VBA?" but instead is a solution to what I believe is the underling problem as the original question states "so that i can do the Case Sensitive Vlookup." this is a solution acomplishing a Case Sensitive Vlookup, without the need to convert the values before doing so.
An alternative to converting all the values then doing a look up on the converted values, you could use the INDEX and MATCH functions in an array entered formula and directly look up the values:
=INDEX(A1:A14,MATCH(TRUE,EXACT(A1:A14,"ddC"),0))
This will return the value in A1:A14, at the same index of an exact (case-sensitive) match in A1:A14 to ddC you can VERY easily modify this into a look up of other columns.
Explanation:
Start with getting an array of all exact matches in your look up list to your look up value:
So if I enter this formula:
=EXACT(A1:A14,"ddC")
Then go into the formula bar and press F9 it will show me an array of true false values, relating to each cell in the range A1:A14 that are an Exact match to my expression "ddC":
now if we take this Boolean Array, and use the Match function to return the relative position of True in the array.
=MATCH(TRUE,EXACT(A1:A14,"ddC"),0)
But remember we need to enter this by pressing Ctrl + Shift + Enter because we need the EXACT(A1:A14,"ddC") portion of the formula to be returned as an array.
Now that we have the position of the True in the array, in this case 6 we can use that to retrieve the corresponding value in any column, as long as it is relational and that same size. So if we want to return the value of the exact match (although relatively useless in this situation, but will continue for demonstration) in the original look up column we just wrap the last formula up in an Index function:
=INDEX(A1:A14,MATCH(TRUE,EXACT(A1:A14,"ddC"),0))
But remember we need to enter this by pressing Ctrl + Shift + Enter because we need the EXACT(A1:A14,"ddC") portion of the formula to be returned as an array.
Now we can apply that same concept to a larger range for more useful look up function:
But remember we need to enter this by pressing Ctrl + Shift + Enter because we need the EXACT(A1:A14,"ddC") portion of the formula to be returned as an array.
Now notice in this last step I offered 2 formulas:
=INDEX(A1:B14,MATCH(TRUE,EXACT(A1:A14,D2),0),2)
And
=INDEX(B1:B14,MATCH(TRUE,EXACT(A1:A14,D2),0))
The first returns the value in the range A1:B14 in the Second column at the position of the exact match in A1:A14 to the value in D2 (in this case "dady")
The second returns the value in the range B1:B14 at the position of the exact match in A1:A14 to the value in D2 (in this case "dady")
Hopefully someone else can add more input but as far as I know the second might be better performing, as it has a smaller index range, and doesn't require going to the specified column, it is also shorter.
While the first to me is much easier to read, to some (more of a preference I think) because you know that your looking at a look up table that spans 2 columns and that you are returning the value in the second column.
*Notes: * I am note sure if this solution will be better in practice then converting the original values in the first place, seeing as how converting all the values once, then hard coding the converted values will require no additional formula or calculation (if formulas are afterwards replaced with values) once finished, while this method will recalculate, and also is array entered. But I feel in the case the asker is doing a single look up against a changing look up list (one that constantly requires all values are converted at all times using array formula) this option does allow you to remove the formula per word, with one single formula
all in all I hope this solves your original problem,
Cheers!!
if all your strings like the one you pointed above try something like this:
= CONCATENATE(Code(A1) , Code(Mid(A1,2,1)) , Code(Mid(A1,3,1)))
In order to account for capital letters you're going to end up with a VERY long formula, especially if you have long word entries. Without VBA I would approach it this way and set up the formula once to allow for the biggest word you anticipate, and then copy it around as needed.
Formula (to expand):
=CONCATENATE(IF(EXACT(A1,UPPER(A1))=TRUE,"b","s")&CODE(A1),IF(EXACT(A1,UPPER(A1))=TRUE,"b","s")&CODE(MID(A1,2,1)),IF(EXACT(A1,UPPER(A1))=TRUE,"b","s")&CODE(MID(A1,3,1)), . . . )
You can substitue the "b" and "s" with whatever you like. I was just using those for a case check for capital versus lowercase letters (b=big, s=small) and building that into your unique code.
In order to expand this, add additional cases to account for the length of the words you are using by adding this snippet JUST inside the last parenthesis and modifying the "3" in the MID() function to account for a word length of "4", "5", "6", etc.:
IF(EXACT(A1,UPPER(A1))=TRUE,"b","s")&CODE(MID(A1,3,1))
Painful, yes, but it should work.
Cheers.

Resources