## Optimized Array Formula This formula is faster than my comparable array formula at the end. I favor shorter code where possible but apparently, that doesn't always go hand-in-hand with shorter execution time. ``` LET(rng,A1:A, arr,ARRAY_CONSTRAIN(rng,MAX(FILTER(ROW(rng), rng<>"")),1), m,INDEX(IFS(arr="",,ISNUMBER(arr),,1,IFERROR(REGEXEXTRACT(arr, " (\w)illion")))), v,IF(m="",,REGEXEXTRACT(arr, "([\d\.]*) ")), ARRAYFORMULA(IFS(m="m",v*10^6, m="d",v*10^9, 1,arr))) ``` 1. `rng` references Column A 2. `arr` stores an array created by removing any empty rows after the last populated cell in `rng`. 3. `m` returns an array of **m**ultipliers by processing the values in `arr` such that it has a: 1. blank, if `arr` is a number or a blank, 2. a single word character `\w`, if one is captured from the beginning of a text string using the regular expression `(\w)illion`. Presumably it would be an `m` from **m**illion or `b` from **b**illion, but other incidental captures aren't a concern. 3. lastly the value might be an error if there are string in Column A that don't match `(\w)illion`. This is also not a concern. 4. `v` stores an array of the same dimensions as `m` made up of blanks where `m` is blank, and extracts numbers from `arr` wherever `m` successfully extracted a single word character. 5. Finally, inside an ARRAYFORMULA, IFS evaluates multiple conditions, returning the value corresponding to the **first** true condition. 1. Conditions one and two check if `m` contains either the letter `"m"` or `"b"` returning either `v*10^6` or `v*10^9` respectively if one of them is true. 2. If the previous two conditions return false, then the original value from `arr` / Column A is returned (text string, number, whatever). To achieve this the last condition is set to `1`, which is equivalent to `TRUE`, therefore if ever the condition is reached, it must always succeed. This approach is why most errors generated in the earlier stages are not relevant as, if there is no `"m"` or `"b"` the formula returns the original value. ------------- ## Earlier Answer [Martin's answer][1] is a good approach and originally I created a slight variation of it adding only some code reduction and extending it to work as an array formula. I found later that changing the approach resulted in better performance. > **Credit:** [Martin's Original Formula][1]: > ``` > =IF(A1="","",IF(ISNUMBER(A1),A1,VALUE(REGEXEXTRACT(A1,"[0-9\.]*"))* > IF(REGEXMATCH(A1,"million"),1000000,IF(REGEXMATCH(A1,"billion"),1000000000,1)))) >``` ##### Variation on Martin's ``` =IFS(A1="",, ISNUMBER(A1),A1, 1,REGEXEXTRACT(A1,"[\d\.]*") * 10^ (REGEXMATCH(A1,"m")*6 + REGEXMATCH(A1,"b")*9)) ``` ##### Array Formula Version ``` =LET(rng,A1:A, INDEX( IFS(rng="",, ISNUMBER(rng),rng, 1,REGEXEXTRACT(rng,"[\d\.]*") * 10^ (REGEXMATCH(rng,"m")*6 + REGEXMATCH(rng,"b")*9)))) ``` [1]: https://webapps.stackexchange.com/a/175555