SOLVED

Evaluate Lambda in VBA

%3CLINGO-SUB%20id%3D%22lingo-sub-3280564%22%20slang%3D%22en-US%22%3EEvaluate%20Lambda%20in%20VBA%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-3280564%22%20slang%3D%22en-US%22%3E%3CP%3EQ%3A%26nbsp%3B%20How%20can%20I%20evaluate%20an%20expression%20containing%20a%20custom%20Lambda%20call%20in%20VBA%3F%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EI've%20created%20a%20LAMBDA%20function%20that%20returns%20a%20column%20vector%20array%20that%20I%20would%20like%20to%20be%20able%20to%20evaluate%20in%20VBA%20passing%20it%20a%20parameter%20and%20return%20that%20array%20to%20a%20variant%20variable.%26nbsp%3B%20Something%20like%20this%3A%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EDim%20v%20As%20Variant%3C%2FP%3E%3CP%3Ev%20%3D%20Evaluate(%22MyLambda(%22%20%26amp%3B%20param%20%26amp%3B%20%22)%22)%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EBut%20the%20Evaluate%20function%20chokes%20on%20the%20MyLambda%20with%20%23NAME!%20error.%26nbsp%3B%20The%20same%20formula%20evaluates%20fine%20in%20a%20cell%20in%20the%20same%20workbook.%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EIf%20it%20were%20a%20relatively%20simple%20Lambda%2C%20I%20could%20use%20Evaluate(Names(%22MyLambda%22).RefersTo%26amp%3B%22(%22%20%26amp%3B%20param%20%26amp%3B%20%22)%22).%26nbsp%3B%20But%20My%20Lambda%20is%20fairly%20complex%20and%20it%20calls%20other%20Lambdas.%26nbsp%3B%20Once%20hacky%20workaround%20I%20came%20up%20with%20is%20to%20stick%20the%20%3DMyLambda(%3COBJECT%3E%3CPARAM%20%2F%3E)%20into%20a%20cell%20on%20a%20sheet%2C%20calculate%2C%20and%20then%20grab%20the%20array%20off%20the%20sheet%2C%20but%20I'd%20prefer%20to%20find%20a%20way%20that%20doesn't%20mess%20with%20the%20user's%20sheets.%3C%2FOBJECT%3E%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EHas%20anyone%20figured%20out%20a%20way%20to%20get%20this%20to%20work%20in%20VBA%3F%3F%3F%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EThanks%20in%20advance%2C%3C%2FP%3E%3CP%3EErik%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-LABS%20id%3D%22lingo-labs-3280564%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3EExcel%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3EFormulas%20and%20Functions%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3EMacros%20and%20VBA%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E%3CLINGO-SUB%20id%3D%22lingo-sub-3286998%22%20slang%3D%22en-US%22%3ERe%3A%20Evaluate%20Lambda%20in%20VBA%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-3286998%22%20slang%3D%22en-US%22%3EBingo!%20So%20it%20seems%20that%20when%20a%20Lambda%20is%20evaluated%20using%20EVALUATE%2C%20it%20must%20be%20breaking%20the%20LET%20arguments%20down%20and%20evaluating%20them%20individually%2C%20so%20any%20LET%20variable%20assignments%20that%20are%20over%20255%20characters%20cause%20the%20whole%20EVALUATE%20to%20either%20fail%20or%20return%20unexpected%20results.%20So%2C%20moral%20of%20the%20story%2C%20if%20you%20want%20to%20use%20EVALUATE%20on%20Lambdas%2C%20the%20lambdas%20can%20be%20complex%20as%20whole%20but%20must%20be%20broken%20down%20into%20smaller%20calculation%20units%20within.%20Thanks%20Jan!%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-3285500%22%20slang%3D%22en-US%22%3ERe%3A%20Evaluate%20Lambda%20in%20VBA%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-3285500%22%20slang%3D%22en-US%22%3ENot%20that%20surprising%2C%20the%20Evaluate%20method%20accepts%20a%20string%20argument%20which%20is%20limited%20to%20255%20characters.%20See%3A%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Foffice%2Fvba%2Fapi%2Fexcel.application.evaluate%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3Ehttps%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Foffice%2Fvba%2Fapi%2Fexcel.application.evaluate%3C%2FA%3E%3CBR%20%2F%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-3285199%22%20slang%3D%22en-US%22%3ERe%3A%20Evaluate%20Lambda%20in%20VBA%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-3285199%22%20slang%3D%22en-US%22%3E%3CP%3E%3CA%20href%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fuser%2Fviewprofilepage%2Fuser-id%2F22322%22%20target%3D%22_blank%22%3E%40Jan%20Karel%20Pieterse%3C%2FA%3E%26nbsp%3B%3C%2FP%3E%3CP%3EOkay%2C%20so%20this%20is%20pretty%20bewildering.%20I've%20isolated%20the%20problem%20down%20to%20an%20IFS%20statement.%20This%20is%20a%20hugely%20simplified%20version%2C%20the%20simplest%20way%20I%20could%20find%20to%20demonstrate%20the%20problem%20in%20Immediate%20Window%3A%3C%2FP%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CPRE%20class%3D%22lia-code-sample%20language-visual-basic%22%3E%3CCODE%3E%3FEVALUATE(%22%3DIFS(FALSE%2C%22%22logical_test1%22%22%2CFALSE%2C%22%22logical_test2%22%22%2CFALSE%2C%22%22logical_test3%22%22%2CFALSE%2C%22%22logical_test4%22%22%2CFALSE%2C%22%22logical_test5%22%22%2CFALSE%2C%22%22logical_test6%22%22%2CFALSE%2C%22%22logical_test7%22%22%2CFALSE%2C%22%22logical_test8%22%22%2CFALSE%2C%22%22logical_test9%22%22%2CFALSE%2C%22%22logical_test10%22%22%2CFALSE%2C%22%22logical_test11%22%22%2CTRUE%2C%22%22logical_test12%22%22)%22)%0AError%202015%3C%2FCODE%3E%3C%2FPRE%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EThe%20crazy%20thing%20is%20that%20these%20two%20both%20work%20fine.%26nbsp%3B%20Very%20minor%20differences%20that%20shouldn't%20make%20a%20difference.%3C%2FP%3E%3CPRE%20class%3D%22lia-code-sample%20language-visual-basic%22%3E%3CCODE%3E%3FEVALUATE(%22%3DIFS(FALSE%2C%22%22logical_test1%22%22%2CFALSE%2C%22%22logical_test2%22%22%2CFALSE%2C%22%22logical_test3%22%22%2CFALSE%2C%22%22logical_test4%22%22%2CFALSE%2C%22%22logical_test5%22%22%2CFALSE%2C%22%22logical_test6%22%22%2CFALSE%2C%22%22logical_test7%22%22%2CFALSE%2C%22%22logical_test8%22%22%2CFALSE%2C%22%22logical_test9%22%22%2CFALSE%2C%22%22logical_test10%22%22%2CTRUE%2C%22%22logical_test11%22%22)%22)%0Alogical_test11%0A%3FEVALUATE(%22%3DIFS(FALSE%2C%22%22test1%22%22%2CFALSE%2C%22%22test2%22%22%2CFALSE%2C%22%22test3%22%22%2CFALSE%2C%22%22test4%22%22%2CFALSE%2C%22%22test5%22%22%2CFALSE%2C%22%22test6%22%22%2CFALSE%2C%22%22test7%22%22%2CFALSE%2C%22%22test8%22%22%2CFALSE%2C%22%22test9%22%22%2CFALSE%2C%22%22test10%22%22%2CFALSE%2C%22%22test11%22%22%2CTRUE%2C%22%22test12%22%22)%22)%0Atest12%3C%2FCODE%3E%3C%2FPRE%3E%3CP%3E%26nbsp%3B%3C%2FP%3E%3CP%3EI'm%20sure%20I'll%20find%20a%20way%20to%20work%20around%20this%20but%20sheesh%2C%20that's%20gotta%20just%20be%20an%20Excel%20bug.%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-3285133%22%20slang%3D%22en-US%22%3ERe%3A%20Evaluate%20Lambda%20in%20VBA%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-3285133%22%20slang%3D%22en-US%22%3EInteresting!%20Your%20simple%20example%20works%20find%20for%20me%20as%20well%2C%20so%20it's%20something%20about%20one%20of%20my%20lower%20level%20lambdas%20that%20the%20EVALUATE%20function%20doesn't%20like.%20It%20works%20fine%20in%20the%20cell%20but%20I%20get%20an%20Error%202015%20in%20VBA.%20Well%2C%20that%20promising...%20I'll%20have%20to%20dig%20in%20further%20and%20see%20if%20I%20can%20isolate%20the%20source%20of%20the%20problem.%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-3281717%22%20slang%3D%22en-US%22%3ERe%3A%20Evaluate%20Lambda%20in%20VBA%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-3281717%22%20slang%3D%22en-US%22%3E%3CP%3E%3CA%20href%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fuser%2Fviewprofilepage%2Fuser-id%2F847471%22%20target%3D%22_blank%22%3E%40ExcelRobot%3C%2FA%3E%26nbsp%3BIf%20I%20create%20a%20very%20simple%20lambda%3A%3C%2FP%3E%0A%3CP%3E%3CBR%20%2F%3EListOfNumbers%3A%20%3DLAMBDA(n%2CSEQUENCE(n%2C1%2C1%2C1))%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3Eand%26nbsp%3B%20execute%20this%20code%3A%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-applescript%22%3E%3CCODE%3ESub%20foobar()%0A%20%20%20%20Dim%20v%0A%20%20%20%20v%20%3D%20Evaluate(%22listofnumbers(10)%22)%0A%20%20%20%20Stop%0AEnd%20Sub%0A%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3Eand%20open%20the%20locals%20window%2C%20v%20is%20an%20array%20containing%20the%20numbers%201%20to%2010.%3C%2FP%3E%3C%2FLINGO-BODY%3E
Occasional Contributor

Q:  How can I evaluate an expression containing a custom Lambda call in VBA?

 

I've created a LAMBDA function that returns a column vector array that I would like to be able to evaluate in VBA passing it a parameter and return that array to a variant variable.  Something like this:

 

Dim v As Variant

v = Evaluate("MyLambda(" & param & ")")

 

But the Evaluate function chokes on the MyLambda with #NAME! error.  The same formula evaluates fine in a cell in the same workbook.

 

If it were a relatively simple Lambda, I could use Evaluate(Names("MyLambda").RefersTo&"(" & param & ")").  But My Lambda is fairly complex and it calls other Lambdas.  Once hacky workaround I came up with is to stick the =MyLambda(<param>) into a cell on a sheet, calculate, and then grab the array off the sheet, but I'd prefer to find a way that doesn't mess with the user's sheets.

 

Has anyone figured out a way to get this to work in VBA???

 

Thanks in advance,

Erik

5 Replies
best response confirmed by ExcelRobot (Occasional Contributor)
Solution

@ExcelRobot If I create a very simple lambda:


ListOfNumbers: =LAMBDA(n,SEQUENCE(n,1,1,1))

 

and  execute this code:

Sub foobar()
    Dim v
    v = Evaluate("listofnumbers(10)")
    Stop
End Sub

and open the locals window, v is an array containing the numbers 1 to 10.

Interesting! Your simple example works find for me as well, so it's something about one of my lower level lambdas that the EVALUATE function doesn't like. It works fine in the cell but I get an Error 2015 in VBA. Well, that promising... I'll have to dig in further and see if I can isolate the source of the problem.

@Jan Karel Pieterse 

Okay, so this is pretty bewildering. I've isolated the problem down to an IFS statement. This is a hugely simplified version, the simplest way I could find to demonstrate the problem in Immediate Window:

 

?EVALUATE("=IFS(FALSE,""logical_test1"",FALSE,""logical_test2"",FALSE,""logical_test3"",FALSE,""logical_test4"",FALSE,""logical_test5"",FALSE,""logical_test6"",FALSE,""logical_test7"",FALSE,""logical_test8"",FALSE,""logical_test9"",FALSE,""logical_test10"",FALSE,""logical_test11"",TRUE,""logical_test12"")")
Error 2015

 

The crazy thing is that these two both work fine.  Very minor differences that shouldn't make a difference.

?EVALUATE("=IFS(FALSE,""logical_test1"",FALSE,""logical_test2"",FALSE,""logical_test3"",FALSE,""logical_test4"",FALSE,""logical_test5"",FALSE,""logical_test6"",FALSE,""logical_test7"",FALSE,""logical_test8"",FALSE,""logical_test9"",FALSE,""logical_test10"",TRUE,""logical_test11"")")
logical_test11
?EVALUATE("=IFS(FALSE,""test1"",FALSE,""test2"",FALSE,""test3"",FALSE,""test4"",FALSE,""test5"",FALSE,""test6"",FALSE,""test7"",FALSE,""test8"",FALSE,""test9"",FALSE,""test10"",FALSE,""test11"",TRUE,""test12"")")
test12

 

I'm sure I'll find a way to work around this but sheesh, that's gotta just be an Excel bug.

Not that surprising, the Evaluate method accepts a string argument which is limited to 255 characters. See: https://docs.microsoft.com/en-us/office/vba/api/excel.application.evaluate
Bingo! So it seems that when a Lambda is evaluated using EVALUATE, it must be breaking the LET arguments down and evaluating them individually, so any LET variable assignments that are over 255 characters cause the whole EVALUATE to either fail or return unexpected results. So, moral of the story, if you want to use EVALUATE on Lambdas, the lambdas can be complex as whole but must be broken down into smaller calculation units within. Thanks Jan!