# Formulas

Quadratic allows you to work with classic spreadsheet logic, including math operations, referencing cells, and writing formulas.

# Cells

Quadratic gives you the ability to write formulas on multiple lines using the built-in code editor. No more massive, single-line, indecipherable formulas!

## Referencing individual cells

To reference an individual cell, use the traditional `A1`

spreadsheet notation. Negative numbers start at `n1`

and count up while negative letters start at `nA`

and count to the left. For example:

Formula notation |
coordinate plane equivalent |

`A0` | `(0, 0)` |

`A1` | `(0, 1)` |

`B1` | `(1, 1)` |

`An1` | `(0, -1)` |

`nA1` | `(-1, 1)` |

`nAn1` | `(-1, -1)` |

Because `n`

is used for negative columns and rows, cell references are case-sensitive. For example, `AN1`

is `(39, 1)`

while `An1`

is `(1, -1)`

.

## Referencing a range of cells

To reference a range of cells, use the traditional spreadsheet notation that separates two distinct cells using a semicolon as a delimiter, e.g. `A1:D3`

# Operators

Quadratic’s formula language supports the following operators:

Precedence | Symbol | Description |

1 | `x%` | Percent (divides by 100) |

2 | `+x` | Positive |

`-x` | Negative | |

3 | `a:b` | Cell range |

4 | `a..b` | Numeric range |

5 | `a^b` or `a**b` | Exponentiation |

6 | `a*b` | Multiplication |

`a/b` | Division | |

7 | `a+b` | Addition |

`a-b` | Subtraction | |

8 | `a&b` | |

9 | `a=b` or `a==b` | Equal comparison |

`a<>b` or `a!=b` | Not-equal comparison | |

`a<b` | Less-than comparison | |

`a>b` | Greater-than comparison | |

`a<=b` | Less-than-or-equal comparison | |

`a>=b` | Greater-than-or-equal comparison |

Exponentiation is right-associative, so `a^b^c`

is the same as `a^(b^c)`

. All other binary operators are left-associative, so `a-b-c`

is the same as `(a-b)-c`

.

# Functions

Quadratic supports a number of functions commonly used in spreadsheets, with more soon to be added.

Function names are case-insensitive, so `sum()`

is the same as `SUM()`

.

## Mathematics functions

Function | Description |

`SUM([numbers...])` | Adds all values. Returns `0` if given no values. |

`SUMIF(eval_range, criteria, [numbers_range])` | Evaluates each value based on some criteria, and then adds the ones that meet those criteria. If `range_to_sum` is given, then values in `range_to_sum` are added instead wherever the corresponding value in `range_to_evaluate` meets the criteria. See the documentation for more details about how criteria work in formulas. |

`PRODUCT([numbers...])` | Multiplies all values. Returns `1` if given no values. |

`ABS(number)` | Returns the absolute value of a number. |

`SQRT(number)` | Returns the square root of a number. |

`PI()` | Returns π, the circle constant. |

`TAU()` | Returns τ, the circle constant equal to 2π. |

## Trigonometric functions

Function | Description |

`DEGREES(radians)` | Converts radians to degrees. |

`RADIANS(degrees)` | Converts degrees to radians. |

`SIN(radians)` | Returns the sine of an angle in radians. |

`ASIN(number)` | Returns the inverse sine of a number, in radians, ranging from 0 to π. |

`COS(radians)` | Returns the cosine of an angle in radians. |

`ACOS(number)` | Returns the inverse cosine of a number, in radians, ranging from 0 to π. |

`ATAN2(x, y)` | |

`TAN(radians)` | Returns the tangent of an angle in radians. |

`ATAN(number)` | Returns the inverse tangent of a number, in radians, ranging from -π/2 to π/2. |

`CSC(radians)` | Returns the cosecant of an angle in radians. |

`ACSC(number)` | Returns the inverse cosecant of a number, in radians, ranging from -π/2 to π/2. |

`SEC(radians)` | Returns the secant of an angle in radians. |

`ASEC(number)` | Returns the inverse secant of a number, in radians, ranging from 0 to π. |

`COT(radians)` | Returns the cotangent of an angle in radians. |

`ACOT(number)` | Returns the inverse cotangent of a number, in radians, ranging from 0 to π. |

`SINH(radians)` | Returns the hyperbolic sine of an angle in radians. |

`ASINH(number)` | Returns the inverse hyperbolic sine of a number, in radians. |

`COSH(radians)` | Returns the hyperbolic cosine of an angle in radians. |

`ACOSH(number)` | Returns the inverse hyperbolic cosine of a number, in radians. |

`TANH(radians)` | Returns the hyperbolic tangent of an angle in radians. |

`ATANH(number)` | Returns the inverse hyperbolic tangent of a number, in radians. |

`CSCH(radians)` | Returns the hyperbolic cosecant of an angle in radians. |

`ACSCH(number)` | Returns the inverse hyperbolic cosecant of a number, in radians. |

`SECH(radians)` | Returns the hyperbolic secant of an angle in radians. |

`ASECH(number)` | Returns the inverse hyperbolic secant of a number, in radians. |

`COTH(radians)` | Returns the hyperbolic cotangent of an angle in radians. |

`ACOTH(number)` | Returns the inverse hyperbolic cotangent of a number, in radians. |

## Statistics functions

Function | Description |

`AVERAGE([numbers...])` | Returns the arithmetic mean of all values. |

`AVERAGEIF(eval_range, criteria, [numbers_range])` | Evaluates each value based on some criteria, and then computes the arithmetic mean of the ones that meet those criteria. If `range_to_average` is given, then values in `range_to_average` are averaged instead wherever the corresponding value in `range_to_evaluate` meets the criteria. See the documentation for more details about how criteria work in formulas. |

`COUNT([numbers...])` | Returns the number of numeric values. |

`COUNTIF(range, criteria)` | Evaluates each value based on some criteria, and then counts how many values meet those criteria. See the documentation for more details about how criteria work in formulas. |

`COUNTBLANK([range...])` | Counts how many values in the range are empty. Cells with formula or code output of an empty string are also counted. |

`MIN([numbers...])` | Returns the smallest value. Returns +∞ if given no values. |

`MAX([numbers...])` | Returns the largest value. Returns -∞ if given no values. |

## Logic functions

These functions treat `FALSE`

and `0`

as "falsey" and all other values are "truthy."

When used as a number, `TRUE`

is equivalent to `1`

and `FALSE`

is equivalent to `0`

.

Function | Description |

`TRUE()` | Returns `TRUE` . |

`FALSE()` | Returns `FALSE` . |

`NOT(a)` | Returns `TRUE` if `a` is falsey and `FALSE` if `a` is truthy. |

`AND(a, b, ...)` | Returns `TRUE` if all values are truthy and `FALSE` if any values is falsey. \ Returns `TRUE` if given no values. |

`OR(a, b, ...)` | Returns `TRUE` if any value is truthy and `FALSE` if any value is falsey. Returns `FALSE` if given no values. |

`XOR(a, b, ...)` | Returns `TRUE` if an odd number of values are truthy and `FALSE` if an even number of values are truthy. Returns `FALSE` if given no values. |

`IF(cond, t, f)` | Returns `t` if `cond` is truthy and `f` if `cond` if falsey. |

## String functions

Function | Description |

`CONCAT(a, b, ...)` | Concatenates all values as strings. |

## Lookup functions

Function | Description |

`INDIRECT(cellref_string)` | Returns the value of the cell at a given location. |

### VLOOKUP

`VLOOKUP(search_key, search_range, output_col, [is_sorted])`

Examples:

`VLOOKUP(17, A1:C10, 3)`

`VLOOKUP(17, A1:C10, 2, FALSE)`

Searches for a value in the first vertical column of a range and return the corresponding cell in another vertical column, or an error if no match is found.

If `is_sorted`

is `TRUE`

, this function uses a binary search algorithm, so the first column of `search_range`

must be sorted, with smaller values at the top and larger values at the bottom; otherwise the result of this function will be meaningless. If `is_sorted`

is omitted, it is assumed to be `false`

.

If any of `search_key`

, `output_col`

, or `is_sorted`

is an array, then they must be compatible sizes and a lookup will be performed for each corresponding set of elements.

### HLOOKUP

`HLOOKUP(search_key, search_range, output_row, [is_sorted])`

Examples:

`HLOOKUP(17, A1:Z3, 3)`

`HLOOKUP(17, A1:Z3, 2, FALSE)`

Searches for a value in the first horizontal row of a range and return the corresponding cell in another horizontal row, or an error if no match is found.

If `is_sorted`

is `TRUE`

, this function uses a binary search algorithm, so the first row of `search_range`

must be sorted, with smaller values at the left and larger values at the right; otherwise the result of this function will be meaningless. If `is_sorted`

is omitted, it is assumed to be `false`

.

If any of `search_key`

, `output_col`

, or `is_sorted`

is an array, then they must be compatible sizes and a lookup will be performed for each corresponding set of elements.

### XLOOKUP

`XLOOKUP(search_key, search_range, output_range, [fallback], [match_mode], [search_mode])`

Examples:

`XLOOKUP("zebra", A1:Z1, A4:Z6)`

`XLOOKUP({"zebra"; "aardvark"}, A1:Z1, A4:Z6)`

`XLOOKUP(50, C4:C834, B4:C834, {-1, 0, "not found"}, -1, 2)`

Searches for a value in a linear range and returns a row or column from another range.

`search_range`

must be either a single row or a single column.

### Match modes

There are four match modes:

- 0 = exact match (default)
- 1 = next smaller
- 1 = next larger
- 2 = wildcard

See the documentation for more details about how wildcards work in formulas.

### Search modes

There are four search modes:

- 1 = linear search (default)
- 1 = reverse linear search
- 2 = binary search
- 2 = reverse binary search

Linear search finds the first matching value, while reverse linear search finds the last matching value.

Binary search may be faster than linear search, but binary search requires that values are sorted, with smaller values at the top or left and larger values at the bottom or right. Reverse binary search requires that values are sorted in the opposite direction. If `search_range`

is not sorted, then the result of this function will be meaningless.

Binary search is not compatible with the wildcard match mode.

### Result

If `search_range`

is a row, then it must have the same width as `output_range`

so that each value in `search_range`

corresponds to a column in `output_range`

. In this case, the **search axis** is vertical.

If `search_range`

is a column, then it must have the same height as `output_range`

so that each value in `search_range`

corresponds to a row in `output_range`

. In this case, the **search axis** is horizontal.

If a match is not found, then `fallback`

is returned instead. If there is no match and `fallback`

is omitted, then returns an error.

If any of `search_key`

, `fallback`

, `match_mode`

, or `search_mode`

is an array, then they must be compatible sizes and a lookup will be performed for each corresponding set of elements. These arrays must also have compatible size with the non-search axis of `output_range`

.

# Arrays

An array can be written using `{}`

, with `,`

between values within a row and `;`

between rows. For example, `{1, 2, 3; 4, 5, 6}`

is an array with two rows and three columns:

1 | 2 | 3 |

4 | 5 | 6 |

Arrays cannot be empty and every row must be the same length.

Numeric ranges (such as `1..10`

) and cell ranges (such as `A1:A10`

) also produce arrays. All operators and most functions can operate on arrays, following these rules:

- Operators always operate element-wise. For example,
`{1, 2, 3} + {10, 20, 30}`

produces`{11, 22, 33}`

. - Functions that take a fixed number of values operate element-wise. For example,
`NOT({TRUE, TRUE, FALSE})`

produces`{FALSE, FALSE, TRUE}`

. - Functions that can take any number of values expand the array into individual values. For example,
`SUM({1, 2, 3})`

is the same as`SUM(1, 2, 3)`

.

When arrays are used element-wise, they must be the same size. For example, `{1, 2} + {10, 20, 30}`

produces an error.

When an array is used element-wise with a single value, the value is expanded into an array of the same size. For example, `{1, 2, 3} + 10`

produces `{11, 12, 13}`

.

# Criteria

Some functions, such as `SUMIF()`

, take a **criteria** parameter that other values are compared to. A criteria value can be a literal value, such as `1`

, `FALSE`

, `"blue"`

, etc. A literal value checks for equality (case-insensitive). However, starting a string with a comparison operator enables more complex criteria:

Symbol | Description |

`"=blue"` or `"==blue"` | Equal comparison |

`"<>blue"` or `"!=blue"` | Not-equal comparison |

`"<blue"` | Less-than comparison |

`">blue"` | Greater-than comparison |

`"<=blue"` | Less-than-or-equal comparison |

`">=blue"` | Greater-than-or-equal comparison |

For example, `COUNTIF(A1:A10, ">=3")`

counts all values greater than or equal to three, and `COUNTIF(A1:A10, "<>blue")`

counts all values *not* equal to the text

`"blue"`

(excluding quotes).Numbers and booleans are compared by value (with `TRUE`

=1 and `FALSE`

=0), while strings are compared case-insensitive lexicographically. For example, `"aardvark"`

is less than `"Camel"`

which is less than `"zebra"`

. `"blue"`

and `"BLUE"`

are considered equal.

## Wildcards

**W**ildcard patterns can be used …

- … When using a criteria parameter with an equality-based comparison (
`=`

,`==`

,`<>`

,`!=`

, or no operator) - … When using the
`XLOOKUP`

function with a`match_mode`

of`2`

In wildcards, the special symbols `?`

and `*`

can be used to match certain text patterns: `?`

matches any single character and `*`

matches any sequence of zero or more characters. For example, `DEFEN?E`

matches the strings `"defence"`

and `"defense"`

, but not `"defenestrate"`

. `*ATE`

matches the strings `"ate"`

, `"inflate"`

, and `"late"`

, but not `"wait"`

. Multiple `?`

and `*`

are also allowed.

To match a literal `?`

or `*`

, prefix it with a tilde `~`

: for example, `COUNTIF(A1:A10, "HELLO~?")`

matches only the string `"Hello?"`

(and uppercase/lowercase variants).

To match a literal tilde `~`

in a string with `?`

or `*`

, replace it with a double tilde `~~`

. For example, `COUNTIF(A1:A10, "HELLO ~~?")`

matches the strings `"hello ~Q"`

, `"hello ~R"`

, etc. If the string does not contain any `?`

or `*`

, then tildes do not need to be escaped.