Excel: last character/string match in a string
Solution 1:
I think I get what you mean. Let's say for example you want the right-most \ in the following string (which is stored in cell A1):
Drive:\Folder\SubFolder\Filename.ext
To get the position of the last \, you would use this formula:
=FIND("@",SUBSTITUTE(A1,"\","@",(LEN(A1)-LEN(SUBSTITUTE(A1,"\","")))/LEN("\")))
That tells us the right-most \ is at character 24. It does this by looking for "@" and substituting the very last "\" with an "@". It determines the last one by using
(len(string)-len(substitute(string, substring, "")))\len(substring)
In this scenario, the substring is simply "\" which has a length of 1, so you could leave off the division at the end and just use:
=FIND("@",SUBSTITUTE(A1,"\","@",LEN(A1)-LEN(SUBSTITUTE(A1,"\",""))))
Now we can use that to get the folder path:
=LEFT(A1,FIND("@",SUBSTITUTE(A1,"\","@",LEN(A1)-LEN(SUBSTITUTE(A1,"\","")))))
Here's the folder path without the trailing \
=LEFT(A1,FIND("@",SUBSTITUTE(A1,"\","@",LEN(A1)-LEN(SUBSTITUTE(A1,"\",""))))-1)
And to get just the filename:
=MID(A1,FIND("@",SUBSTITUTE(A1,"\","@",LEN(A1)-LEN(SUBSTITUTE(A1,"\",""))))+1,LEN(A1))
However, here is an alternate version of getting everything to the right of the last instance of a specific character. So using our same example, this would also return the file name:
=TRIM(RIGHT(SUBSTITUTE(A1,"\",REPT(" ",LEN(A1))),LEN(A1)))
Solution 2:
How about creating a custom function and using that in your formula? VBA has a built-in function, InStrRev
, that does exactly what you're looking for.
Put this in a new module:
Function RSearch(str As String, find As String)
RSearch = InStrRev(str, find)
End Function
And your function will look like this (assuming the original string is in B1):
=LEFT(B1,RSearch(B1,"\"))
Solution 3:
With newer versions of excel come new functions and thus new methods. Though it's replicable in older versions (yet I have not seen it before), when one has Excel O365 one can use:
=MATCH(2,1/(MID(A1,SEQUENCE(LEN(A1)),1)="Y"))
This can also be used to retrieve the last position of (overlapping) substrings:
=MATCH(2,1/(MID(A1,SEQUENCE(LEN(A1)),2)="YY"))
| Value | Pattern | Formula | Position |
|--------|---------|------------------------------------------------|----------|
| XYYZ | Y | =MATCH(2,1/(MID(A2,SEQUENCE(LEN(A2)),1)="Y")) | 3 |
| XYYYZ | YY | =MATCH(2,1/(MID(A3,SEQUENCE(LEN(A3)),2)="YY")) | 3 |
| XYYYYZ | YY | =MATCH(2,1/(MID(A4,SEQUENCE(LEN(A4)),2)="YY")) | 4 |
Whilst this both allows us to no longer use an arbitrary replacement character and it allows overlapping patterns, the "downside" is the useage of an array.
Note: You can force the same behaviour in older Excel versions through either
=MATCH(2,1/(MID(A2,ROW(A1:INDEX(A:A,LEN(A2))),1)="Y"))
Entered through CtrlShiftEnter, or using an inline INDEX
to get rid of implicit intersection:
=MATCH(2,INDEX(1/(MID(A2,ROW(A1:INDEX(A:A,LEN(A2))),1)="Y"),))
Solution 4:
tigeravatar and Jean-François Corbett suggested to use this formula to generate the string right of the last occurrence of the "\" character
=TRIM(RIGHT(SUBSTITUTE(A1,"\",REPT(" ",LEN(A1))),LEN(A1)))
If the character used as separator is space, " ", then the formula has to be changed to:
=SUBSTITUTE(RIGHT(SUBSTITUTE(A1," ",REPT("{",LEN(A1))),LEN(A1)),"{","")
No need to mention, the "{" character can be replaced with any character that would not "normally" occur in the text to process.
Solution 5:
Just came up with this solution, no VBA needed;
Find the last occurance of "_" in my example;
=IFERROR(FIND(CHAR(1);SUBSTITUTE(A1;"_";CHAR(1);LEN(A1)-LEN(SUBSTITUTE(A1;"_";"")));0)
Explained inside out;
SUBSTITUTE(A1;"_";"") => replace "_" by spaces
LEN( *above* ) => count the chars
LEN(A1)- *above* => indicates amount of chars replaced (= occurrences of "_")
SUBSTITUTE(A1;"_";CHAR(1); *above* ) => replace the Nth occurence of "_" by CHAR(1) (Nth = amount of chars replaced = the last one)
FIND(CHAR(1); *above* ) => Find the CHAR(1), being the last (replaced) occurance of "_" in our case
IFERROR( *above* ;"0") => in case no chars were found, return "0"
Hope this was helpful.