diff --git a/help/en/docs/functions.md b/help/en/docs/functions.md
index d79994fe3..29e05700a 100644
--- a/help/en/docs/functions.md
+++ b/help/en/docs/functions.md
@@ -22,14 +22,14 @@ Python (see [Python documentation](https://docs.python.org/3.11/)). Here are som
| Category | Functions |
| --- | --- |
| Grist | Record or rec, $Field or rec.Field, $group or rec.group, RecordSet, UserTable, all, lookupOne, lookupRecords |
-| Date | DATE, DATEADD, DATEDIF, DATEVALUE, DATE_TO_XL, DAY, DAYS, DTIME, EDATE, EOMONTH, HOUR, ISOWEEKNUM, MINUTE, MONTH, NOW, SECOND, TODAY, WEEKDAY, WEEKNUM, XL_TO_DATE, YEAR, YEARFRAC |
-| Info | CELL, CURRENT_CONVERSION, ISBLANK, ISEMAIL, ISERR, ISERROR, ISLOGICAL, ISNA, ISNONTEXT, ISNUMBER, ISREF, ISREFLIST, ISTEXT, ISURL, N, NA, PEEK, RECORD, REQUEST, TYPE |
+| Date | DATE, DATEADD, DATEDIF, DATEVALUE, DATE_TO_XL, DAY, DAYS, DTIME, EDATE, EOMONTH, HOUR, ISOWEEKNUM, MINUTE, MONTH, MOONPHASE, NOW, SECOND, TODAY, WEEKDAY, WEEKNUM, XL_TO_DATE, YEAR, YEARFRAC |
+| Info | CELL, ISBLANK, ISEMAIL, ISERR, ISERROR, ISLOGICAL, ISNA, ISNONTEXT, ISNUMBER, ISREF, ISREFLIST, ISTEXT, ISURL, N, NA, PEEK, RECORD, REQUEST, TYPE |
| Logical | AND, FALSE, IF, IFERROR, NOT, OR, TRUE |
| Lookup | lookupOne, lookupRecords, ADDRESS, CHOOSE, COLUMN, COLUMNS, CONTAINS, GETPIVOTDATA, HLOOKUP, HYPERLINK, INDEX, INDIRECT, LOOKUP, MATCH, OFFSET, ROW, ROWS, SELF_HYPERLINK, VLOOKUP |
-| Math | ABS, ACOS, ACOSH, ARABIC, ASIN, ASINH, ATAN, ATAN2, ATANH, CEILING, COMBIN, COS, COSH, DEGREES, EVEN, EXP, FACT, FACTDOUBLE, FLOOR, GCD, INT, LCM, LN, LOG, LOG10, MOD, MROUND, MULTINOMIAL, ODD, PI, POWER, PRODUCT, QUOTIENT, RADIANS, RAND, RANDBETWEEN, ROMAN, ROUND, ROUNDDOWN, ROUNDUP, SERIESSUM, SIGN, SIN, SINH, SQRT, SQRTPI, SUBTOTAL, SUM, SUMIF, SUMIFS, SUMPRODUCT, SUMSQ, TAN, TANH, TRUNC, UUID |
+| Math | ABS, ACOS, ACOSH, ARABIC, ASIN, ASINH, ATAN, ATAN2, ATANH, CEILING, COMBIN, COS, COSH, DEGREES, EVEN, EXP, FACT, FACTDOUBLE, FLOOR, GCD, INT, LCM, LN, LOG, LOG10, MOD, MROUND, MULTINOMIAL, NUM, ODD, PI, POWER, PRODUCT, QUOTIENT, RADIANS, RAND, RANDBETWEEN, ROMAN, ROUND, ROUNDDOWN, ROUNDUP, SERIESSUM, SIGN, SIN, SINH, SQRT, SQRTPI, SUBTOTAL, SUM, SUMIF, SUMIFS, SUMPRODUCT, SUMSQ, TAN, TANH, TRUNC, UUID |
| Schedule | SCHEDULE |
| Stats | AVEDEV, AVERAGE, AVERAGEA, AVERAGEIF, AVERAGEIFS, AVERAGE_WEIGHTED, BINOMDIST, CONFIDENCE, CORREL, COUNT, COUNTA, COVAR, CRITBINOM, DEVSQ, EXPONDIST, FDIST, FISHER, FISHERINV, FORECAST, F_DIST, F_DIST_RT, GEOMEAN, HARMEAN, HYPGEOMDIST, INTERCEPT, KURT, LARGE, LOGINV, LOGNORMDIST, MAX, MAXA, MEDIAN, MIN, MINA, MODE, NEGBINOMDIST, NORMDIST, NORMINV, NORMSDIST, NORMSINV, PEARSON, PERCENTILE, PERCENTRANK, PERCENTRANK_EXC, PERCENTRANK_INC, PERMUT, POISSON, PROB, QUARTILE, RANK, RANK_AVG, RANK_EQ, RSQ, SKEW, SLOPE, SMALL, STANDARDIZE, STDEV, STDEVA, STDEVP, STDEVPA, STEYX, TDIST, TINV, TRIMMEAN, TTEST, T_INV, T_INV_2T, VAR, VARA, VARP, VARPA, WEIBULL, ZTEST |
-| Text | CHAR, CLEAN, CODE, CONCAT, CONCATENATE, DOLLAR, EXACT, FIND, FIXED, LEFT, LEN, LOWER, MID, PHONE_FORMAT, PROPER, REGEXEXTRACT, REGEXMATCH, REGEXREPLACE, REPLACE, REPT, RIGHT, SEARCH, SUBSTITUTE, T, TEXT, TRIM, UPPER, VALUE |
+| Text | CHAR, CLEAN, CODE, CONCAT, CONCATENATE, DOLLAR, EXACT, FIND, FIXED, LEFT, LEN, LOWER, MID, PHONE_FORMAT, PROPER, REGEXEXTRACT, REGEXMATCH, REGEXREPLACE, REPLACE, REPT, RIGHT, SEARCH, SUBSTITUTE, T, TASTEME, TEXT, TRIM, UPPER, VALUE |
@@ -67,8 +67,8 @@ Access the field named "Field" of the current record. E.g. `$First_Name` or `rec
In a [summary table](summary-tables.md), `$group` is a special field
-containing the list of Records that are summarized by the current summary line. E.g. the formula
-`len($group)` counts the number of those records being summarized in each row.
+containing the list of Records that are summarized by the current summary line. E.g. the
+formula `len($group)` counts the number of those records being summarized in each row.
See [RecordSet](#recordset) for useful properties offered by the returned object.
@@ -136,15 +136,21 @@ sum(r.Population for r in Countries.all)
UserTable.__lookupOne__(Field_In_Lookup_Table=value, ...)
-Returns a [Record](#record) matching the given field=value arguments. The value may be any expression,
+Returns a [Record](#record) matching the given field=value arguments. The value may be any
+expression,
most commonly a field in the current row (e.g. `$SomeField`) or a constant (e.g. a quoted string
-like `"Some Value"`). If multiple records are found, the first match is returned. You may set the optional `sort_by` parameter to the column ID by which to sort multiple matching results, to determine which of them is returned. You can prefix the column ID with "-" to reverse the order.
+like `"Some Value"`). If multiple records are found, the first match is returned.
+
+You may set the optional `sort_by` parameter to the column ID by which to sort multiple matching
+results, to determine which of them is returned. You can prefix the column ID with "-" to
+reverse the order.
For example:
```
People.lookupOne(First_Name="Lewis", Last_Name="Carroll")
People.lookupOne(Email=$Work_Email)
-People.lookupOne(Email=$Work_Email, sort_by="Date")
+Tickets.lookupOne(Person=$id, sort_by="Date") # Find the first ticket for the person
+Tickets.lookupOne(Person=$id, sort_by="-Date") # Find the last ticket for the person
```
Learn more about [lookupOne](references-lookups.md#lookupone).
@@ -154,16 +160,21 @@ Learn more about [lookupOne](references-lookups.md#lookupone).
UserTable.__lookupRecords__(Field_In_Lookup_Table=value, ...)
-Returns a [RecordSet](#recordset) matching the given field=value arguments. The value may be any expression,
+Returns a [RecordSet](#recordset) matching the given field=value arguments. The value may be
+any expression,
most commonly a field in the current row (e.g. `$SomeField`) or a constant (e.g. a quoted string
like `"Some Value"`) (examples below).
-If `sort_by=field` is given, sort the results by that field.
+
+You may set the optional `sort_by` parameter to the column ID by which to sort multiple matching
+results, to determine which of them is returned. You can prefix the column ID with "-" to
+reverse the order.
For example:
```
People.lookupRecords(Email=$Work_Email)
People.lookupRecords(First_Name="George", Last_Name="Washington")
People.lookupRecords(Last_Name="Johnson", sort_by="First_Name")
+Orders.lookupRecords(Customer=$id, sort_by="-OrderDate")
```
See [RecordSet](#recordset) for useful properties offered by the returned object.
@@ -621,6 +632,57 @@ Same as `date.month`.
1
```
+
+
+#### MOONPHASE
+__MOONPHASE__(date, output='emoji')
+
+
+Returns the phase of the moon on the given date. The output defaults to a moon-phase emoji.
+
+- With `output="days"`, the output is the age of the moon in days (new moon being 0).
+- With `output="fraction"`, the output is the fraction of the lunar month since new moon.
+
+The calculation isn't astronomically precise, but good enough for wolves and sailors.
+
+Do NOT! use `output="lunacy"`.
+
+
+```python
+>>> MOONPHASE(datetime.date(1900, 1, 1), "days")
+0.0
+```
+
+```python
+>>> MOONPHASE(datetime.date(1900, 1, 1), "fraction")
+0.0
+```
+
+```python
+>>> MOONPHASE(datetime.datetime(1900, 1, 1)) == '🌑'
+True
+```
+
+```python
+>>> MOONPHASE(datetime.date(1900, 1, 15)) == '🌕'
+True
+```
+
+```python
+>>> MOONPHASE(datetime.date(1900, 1, 30)) == '🌑'
+True
+```
+
+```python
+>>> [MOONPHASE(DATEADD(datetime.date(2023, 4, 1), days=4*n)) for n in range(8)] == ['🌔', '🌕', '🌖', '🌗', '🌘', '🌑', '🌒', '🌓']
+True
+```
+
+```python
+>>> [round(MOONPHASE(DATEADD(datetime.date(2023, 4, 1), days=4*n), "days"), 1) for n in range(8)]
+[10.4, 14.4, 18.4, 22.4, 26.4, 0.9, 4.9, 8.9]
+```
+
#### NOW
@@ -867,14 +929,6 @@ Returns the requested information about the specified cell. This is not implemen
NoteThis function is not currently implemented in Grist.
-
-#### CURRENT_CONVERSION
-__CURRENT_CONVERSION__(rec)
-
-
-Internal function used by Grist during column type conversions. Not available for use in
-formulas.
-
#### ISBLANK
__ISBLANK__(value)
@@ -1339,7 +1393,7 @@ RECORD(People.lookupRecords(Department="HR"))
#### REQUEST
-__REQUEST__(url, params=None, headers=None)
+__REQUEST__(url, params=None, headers=None, method='GET', data=None, json=None)
@@ -1568,32 +1622,45 @@ True
UserTable.__lookupOne__(Field_In_Lookup_Table=value, ...)
-Returns a [Record](#record) matching the given field=value arguments. The value may be any expression,
+Returns a [Record](#record) matching the given field=value arguments. The value may be any
+expression,
most commonly a field in the current row (e.g. `$SomeField`) or a constant (e.g. a quoted string
-like `"Some Value"`). If multiple records match, returns one of them. If none match, returns the
-special empty record.
+like `"Some Value"`). If multiple records are found, the first match is returned.
+
+You may set the optional `sort_by` parameter to the column ID by which to sort multiple matching
+results, to determine which of them is returned. You can prefix the column ID with "-" to
+reverse the order.
For example:
```
People.lookupOne(First_Name="Lewis", Last_Name="Carroll")
People.lookupOne(Email=$Work_Email)
+Tickets.lookupOne(Person=$id, sort_by="Date") # Find the first ticket for the person
+Tickets.lookupOne(Person=$id, sort_by="-Date") # Find the last ticket for the person
```
+
+Learn more about [lookupOne](references-lookups.md#lookupone).
#### lookupRecords
UserTable.__lookupRecords__(Field_In_Lookup_Table=value, ...)
-Returns a [RecordSet](#recordset) matching the given field=value arguments. The value may be any expression,
+Returns a [RecordSet](#recordset) matching the given field=value arguments. The value may be
+any expression,
most commonly a field in the current row (e.g. `$SomeField`) or a constant (e.g. a quoted string
like `"Some Value"`) (examples below).
-If `sort_by=field` is given, sort the results by that field.
+
+You may set the optional `sort_by` parameter to the column ID by which to sort multiple matching
+results, to determine which of them is returned. You can prefix the column ID with "-" to
+reverse the order.
For example:
```
People.lookupRecords(Email=$Work_Email)
People.lookupRecords(First_Name="George", Last_Name="Washington")
People.lookupRecords(Last_Name="Johnson", sort_by="First_Name")
+Orders.lookupRecords(Customer=$id, sort_by="-OrderDate")
```
See [RecordSet](#recordset) for useful properties offered by the returned object.
@@ -1601,6 +1668,8 @@ See [RecordSet](#recordset) for useful properties offered by the returned object
See [CONTAINS](#contains) for an example utilizing `UserTable.lookupRecords` to find records
where a field of a list type (such as `Choice List` or `Reference List`) contains the given
value.
+
+Learn more about [lookupRecords](references-lookups.md#lookuprecords).
#### ADDRESS
@@ -2588,6 +2657,37 @@ Returns the factorial of the sum of values divided by the product of the values'
13860
```
+
+
+#### NUM
+__NUM__(value)
+
+
+For a Python floating-point value that's actually an integer, returns a Python integer type.
+Otherwise, returns the value unchanged. This is helpful sometimes when a value comes from a
+Numeric Grist column (represented as floats), but when int values are actually expected.
+
+
+```python
+>>> NUM(-17.0)
+-17
+```
+
+```python
+>>> NUM(1.5)
+1.5
+```
+
+```python
+>>> NUM(4)
+4
+```
+
+```python
+>>> NUM("NA")
+'NA'
+```
+
#### ODD
@@ -3223,10 +3323,12 @@ digits.
Generate a random UUID-formatted string identifier.
+
Since UUID() produces a different value each time it's called, it is best to use it in
[trigger formula](formulas.md#trigger-formulas) for new records.
-This would only calculate UUID() once and freeze the calculated value. By contrast, a regular formula
-may get recalculated any time the document is reloaded, producing a different value for UUID() each time.
+This would only calculate UUID() once and freeze the calculated value. By contrast, a regular
+formula may get recalculated any time the document is reloaded, producing a different value for
+UUID() each time.
### Schedule
@@ -4959,6 +5061,13 @@ u'tel:+33-2-34-56-78-90'
u'+12345678901'
```
+```python
+>>> PHONE_FORMAT(33234567890)
+Traceback (most recent call last):
+...
+TypeError: Phone number must be a text value. If formatting a value from a Numeric column, convert that column to Text first.
+```
+
#### PROPER
@@ -5316,6 +5425,29 @@ u'Text'
u''
```
+
+
+#### TASTEME
+__TASTEME__(food)
+
+
+For any given piece of text, decides if it is tasty or not.
+
+This is not serious. It appeared as an Easter egg, and is kept as such. It is in fact a puzzle
+to figure out the underlying simple rule. It has been surprisingly rarely cracked, even after
+reading the source code, which is freely available and may entertain Python fans.
+
+
+```python
+>>> TASTEME('Banana')
+True
+```
+
+```python
+>>> TASTEME('Garlic')
+False
+```
+
#### TEXT
@@ -5323,7 +5455,8 @@ u''
Converts a number into text according to a specified format. It is not yet implemented in
-Grist.
+Grist. You can use the similar Python functions str() to convert numbers into strings, and
+optionally format() to specify the number format.
NoteThis function is not currently implemented in Grist.