简体   繁体   中英

Extract nth Occurance Number from String

I have a column containing cells of text string which includes text and numbers. I found a great formula that finds the first number in the string and extracts it to the corresponding cell eg

Text String: "Initial commission of £9,999.99, then renewal commission of £9.9 from month 99"

Entering this formula =LOOKUP(99^99,--("0"&MID(F8,MIN(SEARCH({0,1,2,3,4,5,6,7,8,9},F8&"0123456789")),ROW($1:$10000)))) adjacent to the cell will extract the first number of 9,999.99.

This is not my formula but one that I found and love but would like to be able to indicate that I would also like to extract the 2nd occurring number and also the 3rd occurring number. Basically all the numbers in the string, into separate cells.

Are any of you clever people able to suggest an edit on the formula to allow this?

Thanks in advance.

Well I managed to sort it out in the end with a crazy long formula. Its not the prettiest of formulas but it does the job.

Thank you for your suggestiongs to which did lead me down the trail of thought to get the answer. Here are my formulas.

The string of text is in a table column called 'Event Label' formula reference [@[Event Label]].

So for the first number I use this formula:

=SUBSTITUTE(LEFT([@[Event Label]],FIND("Â",[@[Event Label]],FIND("Â",[@[Event Label]])+1)),LEFT([@[Event Label]],FIND("Â",[@[Event Label]],FIND("Â",[@[Event Label]])+1)),LOOKUP(99^99,--("0"&MID(LEFT([@[Event Label]],FIND("Â",[@[Event Label]],FIND("Â",[@[Event Label]])+1)),MIN(SEARCH({0,1,2,3,4,5,6,7,8,9},LEFT([@[Event Label]],FIND("Â",[@[Event Label]],FIND("Â",[@[Event Label]])+1))&"0123456789")),ROW($1:$10000)))))

For the second number I use this formula:

=SUBSTITUTE(RIGHT([@[Event Label]],FIND("Â",[@[Event Label]],FIND("Â",[@[Event Label]]))),RIGHT([@[Event Label]],FIND("Â",[@[Event Label]],FIND("Â",[@[Event Label]]))),LOOKUP(99^99,--("0"&MID(RIGHT([@[Event Label]],FIND("Â",[@[Event Label]],FIND("Â",[@[Event Label]]))),MIN(SEARCH({0,1,2,3,4,5,6,7,8,9},RIGHT([@[Event Label]],FIND("Â",[@[Event Label]],FIND("Â",[@[Event Label]])))&"0123456789")),ROW($1:$10000)))))

And for the final 3rd number I use this formula:

=SUBSTITUTE(RIGHT([@[Event Label]],LEN([@[Event Label]])-FIND("month",[@[Event Label]])+1),RIGHT([@[Event Label]],LEN([@[Event Label]])-FIND("month",[@[Event Label]])+1),LOOKUP(99^99,--("0"&MID(RIGHT([@[Event Label]],LEN([@[Event Label]])-FIND("month",[@[Event Label]])+1),MIN(SEARCH({0,1,2,3,4,5,6,7,8,9},RIGHT([@[Event Label]],LEN([@[Event Label]])-FIND("month",[@[Event Label]])+1)&"0123456789")),ROW($1:$10000)))))

This works for me as I have defined text strings that will always be in the same position in the text string.

I'm sure there is probably a better way but it will do for now.

So this is the proposed function - it uses a simple 2-state approach. The problem with a general solution is with using a comma both as a thousands separator and part of the text as in the question. So 999,999 could be a single number or two separate numbers. Also, 99,99,99 although not a valid number returns TRUE from ISNUMERIC and 99 from VAL. You could try and find the longest possible number but if faced with a string such as 99,999,99 you would have to backtrack and a simple 2-state model wouldn't work.

So I think the only practical solution at this kind of simple level is for the function to be called with a parameter which tells it either (a) to treat a comma as a thousands separator (and basically ignore it) or (b) to treat it as a delimiter and therefore to stop adding characters to a number whenever a comma is encountered.

It should be easy enough to be able to process an initial minus sign if required, but that isn't in the present version yet.

Function GetNthNumber(s As String, n As Integer, Optional CommaAsThousands As Boolean = True) As Variant

Dim c, testNumber, number As String

' Ignore commas if treated as thousands separator
If CommaAsThousands Then s = Replace(s, ",", "")

s = s & "x"

Dim i, j, count As Integer

Dim inNumber As Boolean

inNumber = False

' Loop through each character of string

For i = 1 To Len(s)

c = Mid(s, i, 1)

' Part of a number - append new character or finish number

    If inNumber Then
        If IsNumeric(number & c) And (CommaAsThousands Or c <> ",") Then
            number = number & c
        Else
            inNumber = False
            If count = n Then Exit For
        End If
    Else

' Not part of a number - start new number or do nothing

        If IsNumeric(c) Then
            inNumber = True
            number = c
            count = count + 1
        End If

    End If
Next i

'Return nth number or #Value error

If count = n Then
    GetNthNumber = Val(number)
Else
    GetNthNumber = CVErr(xlErrValue)
End If
End Function

Here are the results when called in the two different ways (first row with comma as thousands separator and second row with comma as delimiter):-

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM