This could be done through formula quite alright, but all depends on your Excel version:

1) Excel 2016, you could still use a formula:
Formula in B1
:
=IFERROR(MID(A1,MAX((MID(A1,ROW(A$1:INDEX(A:A,LEN(A1))),1)="1")*(ISNUMBER(--MID(A1,ROW(A$1:INDEX(A:A,LEN(A1))),8)))*(NOT(ISNUMBER(--MID(A1,ROW(A$1:INDEX(A:A,LEN(A1)))+8,1))))*(NOT(ISNUMBER(--MID(A1,ROW(A$1:INDEX(A:A,LEN(A1)))-1,1))))*(ROW(A$1:INDEX(A:A,LEN(A1))))),8),"Nothing found")
Note: This is an array formula and needs to be confirmed through CtrlShiftEnter
2) Excel 2019, using CONCAT()
and FILTERXML()
:
Formula in B1
:
=IFERROR(FILTERXML("<t><s>"&CONCAT(IF(ISNUMBER(--MID(A1,ROW(A$1:INDEX(A:A,LEN(A1))),1)),MID(A1,ROW(A$1:INDEX(A:A,LEN(A1))),1),"</s><s>"))&"</s></t>","//s[starts-with(., '1') and string-length(.) =8]"),"Nothing Found")
Note: This is an array formula and needs to be confirmed through CtrlShiftEnter
3) Excel 365, using previous mentioned functions but including SEQUENCE()
:
Formula in B1
:
=IFERROR(FILTERXML("<t><s>"&LET(X,MID(A1,SEQUENCE(LEN(A1)),1),CONCAT(IF(ISNUMBER(--X),X,"</s><s>")))&"</s></t>","//s[starts-with(., '1') and string-length(.) =8]"),"Nothing Found")
The XPATH
part of the formulas take care of the actual query, looking for strings that start with a '1' and are of a total length of '8'. This would then even work with strings like 'abc123456789abc12345678abc29876543' returning '12345678'.
If you enjoy FILTERXML
and XPATH
, then you might find this interesting.
4) Excel 365, insiders edition (time of writing) using TEXTSPLIT()
:
=LET(X,MID(A1,SEQUENCE(LEN(A1)),1),Y,TEXTSPLIT(A1,IF(ISNUMBER(--X)," ",X),,1),FILTER(Y,(--LEFT(Y)=1)*(LEN(Y)=8),"Nothing Found"))
5) VBA: For if you must use VBA, I guess an UDF is a good option. Something like:
Function GetStr(str As String, pat As String) As String
With CreateObject("vbscript.regexp")
.Pattern = pat
.Global = True
If .Test(str) = True Then
GetStr = .Execute(str)(0).Submatches(0)
Else
GetStr = "Nothing found"
End If
End With
End Function
You can call this in B1
as per =GetStr(A1,"(?:^|\D)(1\d{7})(?:\D|$)")
. This is making use of a regular expression. If you are interested and want to learn more then this is an interesting read for you.
I left the pattern outside the UDF on purpose might you ever want to change it up. The current pattern can be seen in this online Demo, where from left to right the engine will look for:
(?:
- 1st Non-capturing group
^|\D
- Either a start string ancor or anything other than a digit.
)
- Close 1st non-capturing group.
(
- 1st capture group.
1\d{7}
- Search for a literal 1 followed by 7 digits.
)
- Close 1st capture group.
(?:
- 2nd Non-capturing group
\D|$
- Either anything other than a digit or an end string ancor.
)
- Close 2nd non-capturing group.
