Skip to content

Instantly share code, notes, and snippets.

@ExcelRobot
Last active January 19, 2024 05:54
Show Gist options
  • Save ExcelRobot/54a58edba0a8b7ef8bd9138b5d22ba3e to your computer and use it in GitHub Desktop.
Save ExcelRobot/54a58edba0a8b7ef8bd9138b5d22ba3e to your computer and use it in GitHub Desktop.
Direct Precedents LAMBDA Function
/*
Name: Direct Precedents (DIRECTPRECEDENTS)
Description: Lists all direct precedents for specified cell.
Author: Excel Robot (@ExcelRobot)
Category: Formula
*/
DIRECTPRECEDENTS = LAMBDA(cell,LET(
tokens, TOKENIZEFORMULA(OFFSET(cell,0,0,1,1)),
isterm, INDEX(tokens,,1)="Term",
activesheetname, MID(CELL("filename",INDIRECT("$A$1")),FIND("]",CELL("filename",INDIRECT("$A$1")))+1,999),
cellsheetname, MID(CELL("filename",cell),FIND("]",CELL("filename",cell))+1,999),
isaddress, IFERROR(CELL("address",INDIRECT(INDEX(tokens,,2))),IFERROR(CELL("address",INDIRECT("'"&cellsheetname&"'!"&INDEX(tokens,,2))),""))<>"",
relativetocell, INDEX(FILTER(tokens,isterm*isaddress),,2),
relativetoactivesheet, IF(ISERROR(FIND("!",relativetocell)),IF(ISERROR(CELL("address",INDIRECT(cellsheetname&"!"&relativetocell))),"'"&cellsheetname&"'!",cellsheetname&"!")&relativetocell,relativetocell),
removeactivesheet, IF((LEFT(relativetoactivesheet,LEN(activesheetname&"!"))=activesheetname&"!")+(LEFT(relativetoactivesheet,LEN("'"&activesheetname&"!"))="'"&activesheetname&"'!"),MID(relativetoactivesheet,FIND("!",relativetoactivesheet)+1,999),relativetoactivesheet),
precedents, unique(removeactivesheet),
precedents
));
/*
Name: Tokenize Formula (TOKENIZEFORMULA)
Description: Takes the formula from a given cell and breaks down the formula text into
discrete tokenized parts. Supports the following token types: Argument Seperator,
Array Row Seperator, Close Array, Close Paren, Comparison, Formula Begin, Function,
Open Array, Open Paren, Operator, Term, White Space.
Author: Excel Robot (@ExcelRobot)
Category: Formula
*/
TOKENIZEFORMULA = LAMBDA(Cell,LET(
Formula, FORMULATEXT(Cell),
Chars, MID(Formula,SEQUENCE(LEN(Formula)),1),
PriorChars, IFERROR(MID(Formula,SEQUENCE(LEN(Formula),,0),1),""),
PriorPriorChars, IFERROR(MID(Formula,SEQUENCE(LEN(Formula),,-1),1),""),
NextChars, IFERROR(MID(Formula,SEQUENCE(LEN(Formula),,2),1),""),
IsQuote, Chars="""",
QuoteCount, SCAN(0,IsQuote,LAMBDA(tot,x,tot+x)),
NotInQuote, NOT(IF((QuoteCount=1)*IsQuote,FALSE,IF(ISODD(+QuoteCount),TRUE,IF(IsQuote*(NextChars="""")*(QuoteCount>0),TRUE,FALSE)))),
IsOpenParen, (Chars="(")*NotInQuote,
IsCloseParen, (Chars=")")*NotInQuote,
IsNotExponent, NotInQuote*(((Chars="+")+(Chars="-"))>0)*(PriorChars="E")*NOT(ISERROR(VALUE(PriorPriorChars)))*NOT(ISERROR(VALUE(NextChars)))=0,
IsComparison, ((Chars="<")+(Chars=">")+(Chars="="))*NotInQuote*(PriorChars<>"")>0,
OperatorList, {"+";"-";"*";"/";"^";"&"},
IsOperator, BYROW(Chars,LAMBDA(x,OR(x=OperatorList)))*NotInQuote*IsNotExponent<>0,
IsOpenArray, (Chars="{")*NotInQuote,
IsCloseArray, (Chars="}")*NotInQuote,
ArrayCount, SCAN(0,IsOpenArray-IsCloseArray,LAMBDA(tot,x,tot+x)),
InArray, ArrayCount>0,
IsArgSeperator, (Chars=",")*NotInQuote*(1-InArray)>0,
IsArrayColSeperator, (Chars=",")*InArray>0,
IsArrayRowSeperator, (Chars=";")*InArray>0,
IsWhiteSpace, ((Chars=" ")+(Chars=CHAR(10))+(Chars=CHAR(13)))*NotInQuote>0,
TokenTypePass1, IFS((Chars="=")*(PriorChars=""),"Formula Begin",IsOpenParen,"Open Paren",IsCloseParen,"Close Paren",IsComparison,"Comparison",IsOperator,"Operator",IsOpenArray,"Open Array",IsCloseArray,"Close Array",IsArgSeperator,"Argument Seperator",IsArrayColSeperator,"Array Column Seperator",IsArrayRowSeperator,"Array Row Seperator",IsWhiteSpace,"White Space",TRUE,"Term"),
TokenTypePass2, IF(SCAN(0,TokenTypePass1,LAMBDA(tot,x,SWITCH(x,"Term",0,"Open Paren",1,"Argument Seperator",1,"Array Row Seperator",1,"Array Column Seperator",1,"Operator",tot+1,tot)))>1,"Term",TokenTypePass1),
TokenIndex, SCAN(0,IF((INDEX(TokenTypePass2,SEQUENCE(ROWS(TokenTypePass2),,0))=TokenTypePass2)*(PriorChars<>"")*(((TokenTypePass2="Term")+(TokenTypePass2="Comparison")+(TokenTypePass2="White Space"))>0),0,1),LAMBDA(tot,x,tot+x)),
TokenTypes, LET(TokenTypeLookup,XLOOKUP(SEQUENCE(MAX(TokenIndex)),TokenIndex,TokenTypePass2),NextTokenType,XLOOKUP(SEQUENCE(MAX(TokenIndex))+1,TokenIndex,TokenTypePass2,""),IF((TokenTypeLookup="Term")*(NextTokenType="Open Paren"),"Function",TokenTypeLookup)),
Tokens, BYROW(SEQUENCE(MAX(TokenIndex)),LAMBDA(x,TEXTJOIN("",,FILTER(Chars,TokenIndex=x)))),
Tokenized, MAKEARRAY(ROWS(TokenTypes),2,LAMBDA(x,y,IF(y=1,INDEX(TokenTypes,x),INDEX(Tokens,x)))),
Tokenized
));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment