Skip to main content

Excel Formula Mode (Formula cards & Rule formulas)

warning

This is an experimental feature. That means we’re still working on finishing it. There may be bugs, missing functionality or incomplete documentation, and we may decide to remove the feature in a future release. If you have any feedback, please comment on this feedback issue or post a message in the Discord.

warning

All functionality described here may not be available in the latest stable release. See Experimental Features for instructions to enable experimental features. Use the edge images for the latest implementation.

Excel formula mode adds two related features:

  • Formula cards: a dashboard/report card that evaluates an Excel-style formula, including totals from custom queries.
  • Rule formulas: in the Rules editor, some “set field” actions can be driven by a formula instead of a fixed value.

Under the hood, Actual evaluates formulas using HyperFormula. Formulas must start with =.

Enable the feature

Go to Settings -> Show advanced settings -> Experimental features and enable:

  • Excel formula mode (Formula cards & Rule formulas)

Placeholder: enable Excel formula mode toggle

Formula cards

Add a Formula card

  1. Go to Reports
  2. Click Edit dashboard
  3. Click Add widget
  4. Choose Formula card

Click the card to open the editor (where you can save the widget).

Placeholder: add Formula card from Reports dashboard

Write a formula

  • Start with = (example: =SUM(1, 2, 3))
  • You can use typical Excel-style functions (autocomplete and hover help are built into the editor).

Function reference (autocomplete)

This list documents the functions that appear in the in-app autocomplete/hover popover for formulas.

tip

If a function isn’t listed here, it still might work. Actual uses HyperFormula under the hood, so you can also refer to HyperFormula’s built-in functions list.

FunctionAvailable inDescriptionSyntax exampleOptional params
ABSQuery, RulesReturns the absolute value of a number.=ABS(-42)
ANDQuery, RulesReturns TRUE if all arguments are TRUE.=AND(1=1, 2=2)Accepts more than 2 conditions
AVERAGEQueryReturns the average of all numbers in a range.=AVERAGE(1, 2, 3)Accepts more than 2 values
AVERAGEAQueryReturns the average, including text and logical values.=AVERAGEA(1, TRUE, "2")Accepts more than 2 values
CEILINGQuery, RulesRounds up to nearest multiple of significance.=CEILING(10.2, 1)
CHARQuery, RulesConverts number to character.=CHAR(65)
CHOOSEQueryReturns value from list based on index.=CHOOSE(2, "A", "B", "C")Accepts more than 2 values
CLEANRulesRemoves non-printable characters from text.=CLEAN(notes)
CODEQuery, RulesReturns numeric code for first character.=CODE("A")
CONCATENATEQuery, RulesCombines several text strings into one.=CONCATENATE("Paid ", payee_name)Accepts more than 2 texts
COSQueryReturns the cosine of an angle.=COS(1)
COUNTQueryCounts the number of numeric values.=COUNT(1, 2, "x")Accepts more than 2 values
COUNTAQueryCounts non-empty values.=COUNTA(1, "", "x")Accepts more than 2 values
COUNTBLANKQueryCounts empty cells.=COUNTBLANK(A1:A10)
COUNTIFQueryCounts cells that meet a criteria.=COUNTIF(A1:A10, ">0")
COUNTIFSQueryCounts cells that meet multiple criteria.=COUNTIFS(A1:A10, ">0", B1:B10, "<=5")Repeat (range, criteria) pairs
DATEQuery, RulesReturns date as number of days since null date.=DATE(2025, 12, 16)
DATEDIFQuery, RulesCalculates distance between dates.=DATEDIF("2025-01-01", "2025-12-31", "D")
DATEVALUERulesParses a date string and returns it as a number.=DATEVALUE("2025-12-16")
DAYQuery, RulesReturns the day from a date.=DAY(date)
DAYSQuery, RulesCalculates difference between dates in days.=DAYS("2025-12-31", "2025-12-01")
EDATEQuery, RulesReturns date shifted by specified months.=EDATE(date, 1)
EOMONTHQuery, RulesReturns last day of month after specified months.=EOMONTH(date, 0)
EXACTQuery, RulesReturns TRUE if texts are exactly the same.=EXACT("A", "a")
EXPQueryReturns e raised to the power of number.=EXP(1)
FALSEQuery, RulesReturns the logical value FALSE.=FALSE()
FINDQuery, RulesFinds text within text (case-sensitive).=FIND("foo", notes)
FLOORQuery, RulesRounds down to nearest multiple of significance.=FLOOR(10.8, 1)
FVQueryCalculates future value of investment.=FV(0.05/12, 12, -100)
HLOOKUPQuerySearches horizontally in first row and returns value.=HLOOKUP("key", A1:D10, 2, TRUE)
IFQuery, RulesReturns one value if condition is TRUE, another if FALSE.=IF(amount<0, "Expense", "Income")
IFERRORQuery, RulesReturns value if no error, otherwise returns alternative.=IFERROR(1/0, 0)
IFNAQuery, RulesReturns value if not #N/A error, otherwise returns alternative.=IFNA(VLOOKUP("x", A1:B10, 2, FALSE), 0)
IFSQuery, RulesChecks multiple conditions and returns corresponding values.=IFS(amount<0, "Expense", amount>0, "Income")Repeat (condition, value) pairs
INDEXQueryReturns value at specified row and column.=INDEX(A1:C10, 2, 3)
INTEGER_TO_AMOUNTQuery, RulesConverts integer amount to decimal amount (e.g., 1234 -> 12.34).=INTEGER_TO_AMOUNT(amount, 2)decimal_places (default: 2)
INTRulesRounds down to nearest integer.=INT(10.9)
IRRQueryCalculates internal rate of return.=IRR(A1:A12)
ISEVENRulesReturns TRUE if number is even.=ISEVEN(10)
ISODDRulesReturns TRUE if number is odd.=ISODD(11)
ISBLANKQuery, RulesReturns TRUE if value is blank.=ISBLANK(notes)
ISERRORQuery, RulesReturns TRUE if value is any error.=ISERROR(1/0)
ISLOGICALQuery, RulesReturns TRUE if value is logical (TRUE/FALSE).=ISLOGICAL(TRUE())
ISNAQuery, RulesReturns TRUE if value is #N/A error.=ISNA(NA())
ISNUMBERQuery, RulesReturns TRUE if value is a number.=ISNUMBER(amount)
ISOWEEKNUMRulesReturns ISO week number.=ISOWEEKNUM(date)
ISREFQuery, RulesReturns TRUE if value is a reference.=ISREF(A1)
ISTEXTQuery, RulesReturns TRUE if value is text.=ISTEXT(notes)
LEFTQuery, RulesReturns leftmost characters from text.=LEFT(imported_payee, 10)
LENQuery, RulesReturns length of text.=LEN(notes)
LNQueryReturns the natural logarithm.=LN(10)
LOGQueryReturns the logarithm to specified base.=LOG(100, 10)
LOG10QueryReturns the base-10 logarithm.=LOG10(1000)
LOOKUPQueryLooks up values in a vector or array.=LOOKUP("x", A1:A10)
LOWERQuery, RulesConverts text to lowercase.=LOWER(notes)
MATCHQueryReturns position of value in array.=MATCH("x", A1:A10, 0)
MAXQueryReturns the maximum value.=MAX(1, 2, 3)Accepts more than 2 values
MAXAQueryReturns the maximum value, including text and logical values.=MAXA(1, TRUE, "2")Accepts more than 2 values
MEDIANQueryReturns the median value.=MEDIAN(1, 2, 100)Accepts more than 2 values
MIDQuery, RulesReturns substring from specified position.=MID(notes, 1, 10)
MINQueryReturns the minimum value.=MIN(1, 2, 3)Accepts more than 2 values
MINAQueryReturns the minimum value, including text and logical values.=MINA(1, TRUE, "2")Accepts more than 2 values
MODQuery, RulesReturns the remainder of division.=MOD(10, 3)
MODEQueryReturns the most frequently occurring value.=MODE(1, 1, 2)Accepts more than 2 values
MONTHQuery, RulesReturns the month from a date.=MONTH(date)
NRulesConverts value to a number.=N(TRUE())
NETWORKDAYSQueryReturns number of working days between dates.=NETWORKDAYS("2025-12-01", "2025-12-31")
NOTQuery, RulesReverses the logical value.=NOT(amount<0)
NOWQuery, RulesReturns current date and time.=NOW()
NPVQueryCalculates net present value.=NPV(0.1, -1000, 200, 300)Accepts more than 2 values
ORQuery, RulesReturns TRUE if any argument is TRUE.=OR(amount<0, amount>0)Accepts more than 2 conditions
PERCENTILEQueryReturns the k-th percentile.=PERCENTILE(A1:A100, 0.9)
PIQueryReturns the value of PI.=PI()
PMTQueryCalculates payment for a loan.=PMT(0.05/12, 60, 10000)
POWERQuery, RulesReturns base raised to the power of exponent.=POWER(2, 8)
PROPERQuery, RulesCapitalizes first letter of each word.=PROPER(notes)
PRODUCTQueryReturns the product of all numbers.=PRODUCT(2, 3, 4)Accepts more than 2 values
PVQueryCalculates present value of investment.=PV(0.05/12, 12, -100)
QUARTILEQueryReturns the quartile of a dataset.=QUARTILE(A1:A100, 1)
QUERYQueryExecute a query and return the result.=QUERY("expenses")
QUERY_COUNTQueryExecute a query and return the number of matching rows.=QUERY_COUNT("expenses")
RANKQueryReturns the rank of a number in a list.=RANK(10, A1:A10, 0)
RATEQueryCalculates interest rate per period.=RATE(60, -200, 10000)
REPLACEQuery, RulesReplaces substring at specified position.=REPLACE(notes, 1, 5, "")
REPTQuery, RulesRepeats text specified number of times.=REPT("*", 10)
RIGHTQuery, RulesReturns rightmost characters from text.=RIGHT(imported_payee, 4)
ROUNDQuery, RulesRounds a number to specified decimals.=ROUND(amount/100, 2)
ROUNDDOWNQuery, RulesRounds down to specified decimals.=ROUNDDOWN(amount/100, 0)
ROUNDUPQuery, RulesRounds up to specified decimals.=ROUNDUP(amount/100, 0)
SEARCHQuery, RulesFinds text within text (case-insensitive, supports wildcards).=SEARCH("foo", notes)
SIGNRulesReturns -1 for negative, 0 for zero, 1 for positive.=SIGN(amount)
SINQueryReturns the sine of an angle.=SIN(1)
SPLITRulesSplits text by space and returns part at index.=SPLIT(imported_payee, 0)
SQRTQuery, RulesReturns the square root.=SQRT(9)
STDEVQueryReturns the standard deviation of a sample.=STDEV(A1:A10)
STDEVPQueryReturns the standard deviation of a population.=STDEVP(A1:A10)
SUBSTITUTEQuery, RulesReplaces occurrences of text.=SUBSTITUTE(imported_payee, " 12345", "")
SUMQuery, RulesReturns the sum of all numbers in a range.=SUM(1, 2, 3)Accepts more than 2 values
SUMIFQuerySums cells that meet a criteria.=SUMIF(A1:A10, ">0", B1:B10)
SUMIFSQuerySums cells that meet multiple criteria.=SUMIFS(B1:B10, A1:A10, ">0", C1:C10, "X")Repeat (range, criteria) pairs
SUMPRODUCTQueryMultiplies corresponding elements and returns the sum.=SUMPRODUCT(A1:A10, B1:B10)Accepts more arrays
SUMSQQueryReturns the sum of the squares.=SUMSQ(1, 2, 3)Accepts more than 2 values
SWITCHQuery, RulesMatches expression against values and returns corresponding result.=SWITCH(category_name, "Groceries", "Food", "Fuel", "Transport")Repeat (value, result) pairs; default supported
TRulesReturns text if value is text, empty string otherwise.=T(notes)
TANQueryReturns the tangent of an angle.=TAN(1)
TEXTQuery, RulesConverts number to text with format.=TEXT(date, "MMMM yyyy")
TODAYQuery, RulesReturns current date.=TODAY()
TRIMQuery, RulesRemoves extra spaces from text.=TRIM(notes)
TRUNCRulesTruncates number to specified decimals.=TRUNC(amount/100, 0)
TRUEQuery, RulesReturns the logical value TRUE.=TRUE()
UPPERQuery, RulesConverts text to uppercase.=UPPER(notes)
VALUERulesConverts text to a number.=VALUE("123.45")
VARQueryReturns the variance of a sample.=VAR(A1:A10)
VARPQueryReturns the variance of a population.=VARP(A1:A10)
VLOOKUPQuerySearches vertically in first column and returns value.=VLOOKUP("key", A1:D10, 2, TRUE)
WEEKDAYQuery, RulesReturns day of week (1-7).=WEEKDAY(date, 1)
WEEKNUMQuery, RulesReturns week number of year.=WEEKNUM(date, 1)
XORQuery, RulesReturns TRUE if odd number of arguments are TRUE.=XOR(TRUE(), FALSE())Accepts more than 2 conditions
YEARQuery, RulesReturns the year from a date.=YEAR(date)

Use queries with QUERY("name") and QUERY_COUNT("name")

Formula cards can reference named queries that you define in the right-side panel (Query Definitions).

  • QUERY("myQuery") returns the sum of transaction amounts for that query’s filters and date range (returned in normal “money” units, e.g. -123.45).
  • If a query name doesn’t exist, it evaluates as 0.

Example:

=QUERY("income") - QUERY("expenses")

Define a query

In the Formula editor page, use Query Definitions:

  1. Add Query and give it a name (the name is what you reference in QUERY("..."))
  2. Set the date range:
    • Live: keeps the range moving (e.g. “last 3 months”)
    • Static: fixed start/end dates
  3. Add Filters (same style as report filters)

Placeholder: formula editor and Query Definitions panel

Optional: conditional color

Formula cards support an optional Conditional color formula (single line) that returns a color string like red or #ff0000.

  • Use the RESULT variable to reference the main formula result.

Rule formulas

Rule formulas let you compute a value from the current transaction and set a field to that computed result.

Note: rule formula inputs are single-line (line breaks are automatically replaced with spaces).

Where to find the formula toggle

In More -> Rules -> edit a rule, on a Set action:

  • Click the ƒ button to the right of the action input to enable/disable formula mode for that action.
  • Formula mode is not available for actions that set payee, category, or account (those values are IDs).
  • Rule action templating (the </> icon) and formulas are mutually exclusive: enabling one disables the other.

Placeholder: Rule action formula toggle (ƒ)

Available variables

Rule formulas evaluate with named variables from the transaction context, including:

Date variables:

  • today — Current date in YYYY-MM-DD format (e.g., "2025-12-19")
  • date — Transaction date in YYYY-MM-DD format (e.g., "2025-01-15")

Numeric variables (stored in cents):

  • amount — Transaction amount as an integer in cents (e.g., 12345 represents $123.45)
    • Positive for income, negative for expenses
    • To convert to dollars: =amount / 100
  • balance — Account balance after this transaction, as an integer in cents
    • Represents the running balance at this transaction
    • To convert to dollars: =balance / 100

Text variables:

  • notes — Transaction notes/memo field (string, may be empty)
  • imported_payee — Original payee name from import before any rules applied (string)
  • payee_name — Resolved payee name (string)
  • account_name — Account name where transaction exists (string)
  • category_name — Category name assigned to transaction (string)

Boolean variables:

  • cleared — Whether transaction is cleared (TRUE or FALSE)
  • reconciled — Whether transaction is reconciled (TRUE or FALSE)

Tip: if you want “dollars” from amount, use =amount / 100.

Result types

When a rule runs, Actual converts the formula result to the field type:

  • number fields: must produce a number (or a string that parses as a number)
  • date fields: must produce a valid date
  • boolean fields: TRUE/FALSE (or a string that equals "true"/"false")
  • string fields: converted with String(...)