TL;DR summary: I want a formula that will find the Nth "_" (for any N) in a string, and return its index; OR to find the Nth substring, separated by "_". I have VBA to do this, but it's slow.
Long version: I am working with advertising campaign data. My marketers (fortunately) use a consistent naming scheme for their campaigns. Unfortunately, it's very long.
The campaign names contain exactly 1 piece of data that I cannot otherwise get from reports.
For reference, campaign names are of the format:
ADV_CO_BG_Product_UniqueID_XX_mm.dd.yyyy_mm.dd.yyyy_TYP_NUM
... and I have a column of about 200K of them (growing by a couple hundred each week).
Edit:
The important part is that there are multiple parts of the campaign name, with _ as a delimiter between them. In this case, I want the 9th part, but i want an option that is flexible enough that I don't have to add or remove lines to change which part I target.
I've seen on other questions to use a nested formula like:
=MID(
Data_OLV[@Campaign],
FIND("_",Data_OLV[@Campaign],
FIND("_",Data_OLV[@Campaign],
FIND("_",Data_OLV[@Campaign],
FIND("_",Data_OLV[@Campaign],
FIND("_",Data_OLV[@Campaign],
FIND("_",Data_OLV[@Campaign],
FIND("_",Data_OLV[@Campaign],
FIND("_",Data_OLV[@Campaign])+1)
+1)
+1)
+1)
+1)
+1)
+1)
+1,
3)
... but that is hard to modify if I need something in a different position.
I have a UDF called StringSplit (see below) that provides the desired results, but it's extremely slow (and only works if you enable macros, which not all of my audience does).
Is there a better way to do what I'm trying to do?
Public Function StringSplit(input_ As String, delimiter_ As String, index_ As Integer)
On Error GoTo err
out = Split(input_, delimiter_, -1, vbTextCompare)
StringSplit = out(index_ - 1)
Exit Function
err:
If err.Number = 9 Then
StringSplit = CVErr(xlErrRef)
Exit Function
End If
StringSplit = err.Description
End Function


split(split(strInput,"[typ]")(1),chr(10))(0)ADV_CO_BG_Product_UniqueID_XX_mm.dd.yyyy_mm.dd.yyyy_TYP_NUM ADV: Advertiser (Abbreviated) CO: Country (2 letter code) BG: Business (2- or 3-letter code) Product: Product Line (arbitrary string) UniqueID: structured text (variable length) XX: 2-letter code mm.dd.yyyy: Start / End of campaign TYP: The type of advertisment NUM: An internal identifier for a specific advertiser (not always present)and now I see i wasted my time. So you want to get the text between the last two underscores (if NUM is present) or last one (no NUM present)Nth instancevalue and you can also change thedelimiter typeif required. The drawback of this formula is if theNth instancechanges, you have to manually count it and change the value.