1

I wrote an Excel LAMBDA function for extracting numbers from a string. This is the formula get.numbers=LAMBDA(text,ntext,position,size,VALUE(LET(x,LEN(text),n,position,IF(n>x,ntext,get.numbers(text,IF(ISNUMBER(VALUE(MID(text,n,size))),ntext&MID(text,n,size),ntext),n+1,size)))))

The formula works well when the text is from a single cell range eg A2, but if you try to use it on a spill range (A2#) it returns #NUM! error. I have another LAMBDA function that accepts a string and gets a character from a particular position in another string. It joins to character to the given string if the character is a number. I tried to use this function within the get.numbers function but it returned error.

My conclusions are

  1. Lambda function cannot be used within a recursive lambda function
  2. Recursive Lambda function cannot accept data from a spill range

Is there any way out of this?

ZygD
  • 22,092
  • 39
  • 79
  • 102
draustine
  • 35
  • 5
  • Can you include a sample call to your function? I couldn't get it to work on just one cell. – Axuary Feb 10 '21 at 15:13
  • =LAMBDA(text,ntext,position,size,VALUE(LET(x,LEN(text),n,position,IF(n>x,ntext,get.numbers(text,IF(ISNUMBER(VALUE(MID(text,n,size))),ntext&MID(text,n,size),ntext),n+1,size)))))(A2,"",1,1) A2 contains the text from which numbers are to be extracted, "" is the output string Dont forget you 1st have to add the function to defined names as get.numbers – draustine Feb 10 '21 at 16:56

2 Answers2

1

There seems to be some limits on the number of pending calculations you have have in a recursive lambda. So you have to be careful to do things in the right order. I got this to work for an array with up to 93 rows and one column. The call is =get.numbers.array(A2#, "", 1, 1, 1).

get.numbers.array =LAMBDA(textArray, ntext, position, size, x, 
  LET(s, ROWS(textArray), 
      q, SEQUENCE(s), 
      singleResult, get.numbers(INDEX(textArray,x), ntext, position, size), 
      d, IF(x=s, textArray, get.numbers.array(textArray, ntext, position, size, x+1)), 
      IF(x=q, singleResult, INDEX(d,q))))

It would require some more experimentation to get it to work for multiple dimensions.

EDIT 1: After some digging, I found the explanation for the limit here. It states

Furthermore, do note that the current operand stack limit in Excel is 1,024. This should be borne in mind together with calculation times, as the current recursion limit is set as 1,024 divided by (number of lambda parameters + 1).

Axuary
  • 1,497
  • 1
  • 4
  • 20
0

Following Axuary's answer above, I did further trials and was able to clean-up the formula such that the formula takes only one parameter (the string or a range containing strings). The final formula is

Call.GetNumbers.Array =LAMBDA(array,get.numbers.array(array,"",1,1))

It takes only one parameter (array) which could be a cell containing a string, or a spilled range
The main formula is:

get.numbers.array =LAMBDA(array,last,r,ln,LET(n,ROWS(array),q,SEQUENCE(n),lineresult,Call.Join.numbers(INDEX(array,r)),d,IF(r>n,last,get.numbers.array(array,Call.Join.numbers(INDEX(array,r)),r+1,ln+1)),IF(ln=q,lineresult,INDEX(d,q))))

The remaining formulae are:

Call.Join.numbers =LAMBDA(text,join.numbers(text,"",1))
join.numbers =LAMBDA(text,ntext,p,LET(l,LEN(text),VALUE(IF(p>l,ntext,join.numbers(text,ntext&get.If.Number(text,p),p+1)))))
get.if.Number =LAMBDA(text,x,IF(ISNUMBER(VALUE(MID(text,x,1))),MID(text,x,1),""))

The formula worked on range of 1 column by 95 rows

Rubén
  • 34,714
  • 9
  • 70
  • 166
draustine
  • 35
  • 5