- {{ result }}
+
+
+
+ ERR!
+
+ {{ column.colOptions.error }}
+
+
@@ -21,6 +33,9 @@ import dayjs from 'dayjs'
export default {
name: 'FormulaCell',
props: { column: Object, row: Object, client: String },
+ data: () => ({
+ showEditFormulaWarning: false
+ }),
computed: {
result() {
if (this.client === 'pg') {
@@ -53,11 +68,25 @@ export default {
return val.replace(/((?:-?(?:[1-9][0-9]*)?[0-9]{4})-(?:1[0-2]|0[1-9])-(?:3[01]|0[1-9]|[12][0-9])T(?:2[0-3]|[01][0-9]):(?:[0-5][0-9]):(?:[0-5][0-9])(?:\.[0-9]+)?(?:Z|[+-](?:2[0-3]|[01][0-9]):[0-5][0-9]))/g, (i, v) => {
return dayjs(v).format('YYYY-MM-DD HH:mm')
})
+ },
+ showEditFormulaWarningMessage() {
+ this.showEditFormulaWarning = true
+ setTimeout(() => {
+ this.showEditFormulaWarning = false
+ }, 3000)
}
}
}
-
diff --git a/packages/nc-gui/helpers/formulaList.js b/packages/nc-gui/helpers/formulaList.js
index 0ed3f9777d..044764630c 100644
--- a/packages/nc-gui/helpers/formulaList.js
+++ b/packages/nc-gui/helpers/formulaList.js
@@ -1,62 +1,478 @@
-const validations = {
+const formulaTypes = {
+ NUMERIC: "numeric",
+ STRING: "string",
+ DATE: "date",
+ LOGICAL: "logical",
+ COND_EXP: "conditional_expression"
+}
+
+const formulas = {
AVG: {
+ type: formulaTypes.NUMERIC,
validation: {
- args: { min: 1 }
- }
+ args: {
+ min: 1
+ }
+ },
+ description: 'Average of input parameters',
+ syntax: 'AVG(value1, [value2, ...])',
+ examples: [
+ 'AVG(10, 5) => 7.5',
+ 'AVG({column1}, {column2})',
+ 'AVG({column1}, {column2}, {column3})'
+ ]
},
ADD: {
+ type: formulaTypes.NUMERIC,
+ validation: {
+ args: {
+ min: 1
+ }
+ },
+ description: 'Sum of input parameters',
+ syntax: 'ADD(value1, [value2, ...])',
+ examples: [
+ 'ADD(5, 5) => 10',
+ 'ADD({column1}, {column2})',
+ 'ADD({column1}, {column2}, {column3})'
+ ]
+ },
+ DATEADD: {
+ type: formulaTypes.DATE,
validation: {
- args: { min: 1 }
- }
+ args: {
+ rqd: 3
+ }
+ },
+ description: 'Adds a "count" units to Datetime.',
+ syntax: 'DATEADD(date | datetime, value, ["day" | "week" | "month" | "year"])',
+ examples: [
+ 'DATEADD({column1}, 2, "day")',
+ 'DATEADD({column1}, -2, "day")',
+ 'DATEADD({column1}, 2, "week")',
+ 'DATEADD({column1}, -2, "week")',
+ 'DATEADD({column1}, 2, "month")',
+ 'DATEADD({column1}, -2, "month")',
+ 'DATEADD({column1}, 2, "year")',
+ 'DATEADD({column1}, -2, "year")'
+ ]
},
- DATEADD: { validation: { args: { rqd: 3 } } },
AND: {
+ type: formulaTypes.COND_EXP,
validation: {
- args: { min: 1 }
- }
+ args: {
+ min: 1
+ }
+ },
+ description: 'TRUE if all expr evaluate to TRUE',
+ syntax: 'AND(expr1, [expr2, ...])',
+ examples: [
+ 'AND(5 > 2, 5 < 10) => 1',
+ 'AND({column1} > 2, {column2} < 10)'
+ ]
},
OR: {
+ type: formulaTypes.COND_EXP,
validation: {
- args: { min: 1 }
- }
+ args: {
+ min: 1
+ }
+ },
+ description: 'TRUE if at least one expr evaluates to TRUE',
+ syntax: 'OR(expr1, [expr2, ...])',
+ examples: [
+ 'OR(5 > 2, 5 < 10) => 1',
+ 'OR({column1} > 2, {column2} < 10)'
+ ]
},
CONCAT: {
- validation: { args: { min: 1 } }
+ type: formulaTypes.STRING,
+ validation: {
+ args: {
+ min: 1
+ }
+ },
+ description: 'Concatenated string of input parameters',
+ syntax: 'CONCAT(str1, [str2, ...])',
+ examples: [
+ 'CONCAT("AA", "BB", "CC") => "AABBCC"',
+ 'CONCAT({column1}, {column2}, {column3})'
+ ]
},
TRIM: {
- validation: { args: { min: 1 } }
+ type: formulaTypes.STRING,
+ validation: {
+ args: {
+ rqd: 1
+ }
+ },
+ description: 'Remove trailing and leading whitespaces from input parameter',
+ syntax: 'TRIM(str)',
+ examples: [
+ 'TRIM(" HELLO WORLD ") => "HELLO WORLD"',
+ 'TRIM({column1})'
+ ]
},
UPPER: {
- validation: { args: { rqd: 1 } }
- },
- LOWER: { validation: { args: { rqd: 1 } } },
- LEN: { validation: { args: { rqd: 1 } } },
- MIN: { validation: { args: { min: 1 } } },
- MAX: { validation: { args: { min: 1 } } },
- CEILING: { validation: { args: { rqd: 1 } } },
- FLOOR: { validation: { args: { rqd: 1 } } },
- ROUND: { validation: { args: { rqd: 1 } } },
- MOD: { validation: { args: { rqd: 2 } } },
- REPEAT: { validation: { args: { rqd: 2 } } },
- LOG: { validation: {} },
- EXP: { validation: {} },
- POWER: { validation: { args: { rqd: 2 } } },
- SQRT: { validation: { args: { rqd: 1 } } },
- ABS: { validation: { args: { rqd: 1 } } },
- NOW: { validation: { args: { rqd: 0 } } },
- REPLACE: { validation: { args: { rqd: 3 } } },
- SEARCH: { validation: { args: { rqd: 2 } } },
- INT: { validation: { args: { rqd: 1 } } },
- RIGHT: { validation: { args: { rqd: 2 } } },
+ type: formulaTypes.STRING,
+ validation: {
+ args: {
+ rqd: 1
+ }
+ },
+ description: 'Upper case converted string of input parameter',
+ syntax: 'UPPER(str)',
+ examples: [
+ 'UPPER("nocodb") => "NOCODB"',
+ 'UPPER({column1})'
+ ]
+ },
+ LOWER: {
+ type: formulaTypes.STRING,
+ validation: {
+ args: {
+ rqd: 1
+ }
+ },
+ description: 'Lower case converted string of input parameter',
+ syntax: 'LOWER(str)',
+ examples: [
+ 'LOWER("NOCODB") => "nocodb"',
+ 'LOWER({column1})'
+ ]
+ },
+ LEN: {
+ type: formulaTypes.STRING,
+ validation: {
+ args: {
+ rqd: 1
+ }
+ },
+ description: 'Input parameter character length',
+ syntax: 'LEN(value)',
+ examples: [
+ 'LEN("NocoDB") => 6',
+ 'LEN({column1})'
+ ]
+ },
+ MIN: {
+ type: formulaTypes.NUMERIC,
+ validation: {
+ args: {
+ min: 1
+ }
+ },
+ description: 'Minimum value amongst input parameters',
+ syntax: 'MIN(value1, [value2, ...])',
+ examples: [
+ 'MIN(1000, 2000) => 1000',
+ 'MIN({column1}, {column2})'
+ ]
+ },
+ MAX: {
+ type: formulaTypes.NUMERIC,
+ validation: {
+ args: {
+ min: 1
+ }
+ },
+ description: 'Maximum value amongst input parameters',
+ syntax: 'MAX(value1, [value2, ...])',
+ examples: [
+ 'MAX(1000, 2000) => 2000',
+ 'MAX({column1}, {column2})'
+ ]
+ },
+ CEILING: {
+ type: formulaTypes.NUMERIC,
+ validation: {
+ args: {
+ rqd: 1
+ }
+ },
+ description: 'Rounded next largest integer value of input parameter',
+ syntax: 'CEILING(value)',
+ examples: [
+ 'CEILING(1.01) => 2',
+ 'CEILING({column1})'
+ ]
+ },
+ FLOOR: {
+ type: formulaTypes.NUMERIC,
+ validation: {
+ args: {
+ rqd: 1
+ }
+ },
+ description: 'Rounded largest integer less than or equal to input parameter',
+ syntax: 'FLOOR(value)',
+ examples: [
+ 'FLOOR(3.1415) => 3',
+ 'FLOOR({column1})'
+ ]
+ },
+ ROUND: {
+ type: formulaTypes.NUMERIC,
+ validation: {
+ args: {
+ rqd: 1
+ }
+ },
+ description: 'Nearest integer to the input parameter',
+ syntax: 'ROUND(value)',
+ examples: [
+ 'ROUND(3.1415) => 3',
+ 'ROUND({column1})'
+ ]
+ },
+ MOD: {
+ type: formulaTypes.NUMERIC,
+ validation: {
+ args: {
+ rqd: 2
+ }
+ },
+ description: 'Remainder after integer division of input parameters',
+ syntax: 'MOD(value1, value2)',
+ examples: [
+ 'MOD(1024, 1000) => 24',
+ 'MOD({column}, 2)'
+ ]
+ },
+ REPEAT: {
+ type: formulaTypes.STRING,
+ validation: {
+ args: {
+ rqd: 2
+ }
+ },
+ description: 'Specified copies of the input parameter string concatenated together',
+ syntax: 'REPEAT(str, count)',
+ examples: [
+ 'REPEAT("A", 5) => "AAAAA"',
+ 'REPEAT({column}, 5)'
+ ]
+ },
+ LOG: {
+ type: formulaTypes.NUMERIC,
+ validation: {},
+ description: 'Logarithm of input parameter to the base (default = e) specified',
+ syntax: 'LOG([base], value)',
+ examples: [
+ 'LOG(2, 1024) => 10',
+ 'LOG(2, {column1})'
+ ]
+ },
+ EXP: {
+ type: formulaTypes.NUMERIC,
+ validation: {},
+ description: 'Exponential value of input parameter (e ^ power)',
+ syntax: 'EXP(power)',
+ examples: [
+ 'EXP(1) => 2.718281828459045',
+ 'EXP({column1})'
+ ]
+ },
+ POWER: {
+ type: formulaTypes.NUMERIC,
+ validation: {
+ args: {
+ rqd: 2
+ }
+ },
+ description: 'base to the exponent power, as in base ^ exponent',
+ syntax: 'POWER(base, exponent)',
+ examples: [
+ 'POWER(2, 10) => 1024',
+ 'POWER({column1}, 10)'
+ ]
+ },
+ SQRT: {
+ type: formulaTypes.NUMERIC,
+ validation: {
+ args: {
+ rqd: 1
+ }
+ },
+ description: 'Square root of the input parameter',
+ syntax: 'SQRT(value)',
+ examples: [
+ 'SQRT(100) => 10',
+ 'SQRT({column1})'
+ ]
+ },
+ ABS: {
+ type: formulaTypes.NUMERIC,
+ validation: {
+ args: {
+ rqd: 1
+ }
+ },
+ description: 'Absolute value of the input parameter',
+ syntax: 'ABS(value)',
+ examples: [
+ 'ABS({column1})'
+ ]
+ },
+ NOW: {
+ type: formulaTypes.DATE,
+ validation: {
+ args: {
+ rqd: 0
+ }
+ },
+ description: 'Returns the current time and day',
+ syntax: 'NOW()',
+ examples: [
+ 'NOW() => 2022-05-19 17:20:43'
+ ]
+ },
+ REPLACE: {
+ type: formulaTypes.STRING,
+ validation: {
+ args: {
+ rqd: 3
+ }
+ },
+ description: 'String, after replacing all occurrences of srchStr with rplcStr',
+ syntax: 'REPLACE(str, srchStr, rplcStr)',
+ examples: [
+ 'REPLACE("AABBCC", "AA", "BB") => "BBBBCC"',
+ 'REPLACE({column1}, {column2}, {column3})'
+ ]
+ },
+ SEARCH: {
+ type: formulaTypes.STRING,
+ validation: {
+ args: {
+ rqd: 2
+ }
+ },
+ description: 'Index of srchStr specified if found, 0 otherwise',
+ syntax: 'SEARCH(str, srchStr)',
+ examples: [
+ 'SEARCH("HELLO WORLD", "WORLD") => 7',
+ 'SEARCH({column1}, "abc")'
+ ]
+ },
+ INT: {
+ type: formulaTypes.NUMERIC,
+ validation: {
+ args: {
+ rqd: 1
+ }
+ },
+ description: 'Integer value of input parameter',
+ syntax: 'INT(value)',
+ examples: [
+ 'INT(3.1415) => 3',
+ 'INT({column1})'
+ ]
+ },
+ RIGHT: {
+ type: formulaTypes.STRING,
+ validation: {
+ args: {
+ rqd: 2
+ }
+ },
+ description: 'n characters from the end of input parameter',
+ syntax: 'RIGHT(str, n)',
+ examples: [
+ 'RIGHT("HELLO WORLD", 5) => WORLD',
+ 'RIGHT({column1}, 3)'
+ ]
+ },
LEFT: {
- validation: { args: { rqd: 1 } }
+ type: formulaTypes.STRING,
+ validation: {
+ args: {
+ rqd: 2
+ }
+ },
+ description: 'n characters from the beginning of input parameter',
+ syntax: 'LEFT(str, n)',
+ examples: [
+ 'LEFT({column1}, 2)',
+ 'LEFT("ABCD", 2) => "AB"'
+ ]
},
- SUBSTR: { validation: { args: { min: 2, max: 3 } } },
- MID: { validation: { args: { rqd: 1 } } },
- IF: { validation: { args: { min: 2, max: 3 } } },
- SWITCH: { validation: { args: { min: 3 } } },
- URL: { validation: { args: { rqd: 1 } } }
+ SUBSTR: {
+ type: formulaTypes.STRING,
+ validation: {
+ args: {
+ min: 2,
+ max: 3
+ }
+ },
+ description: 'Substring of length n of input string from the postition specified',
+ syntax: ' SUBTR(str, position, [n])',
+ examples: [
+ 'SUBSTR("HELLO WORLD", 7) => WORLD',
+ 'SUBSTR("HELLO WORLD", 7, 3) => WOR',
+ 'SUBSTR({column1}, 7, 5)'
+ ]
+ },
+ MID: {
+ type: formulaTypes.STRING,
+ validation: {
+ args: {
+ rqd: 3
+ }
+ },
+ description: 'Alias for SUBSTR',
+ syntax: 'MID(str, position, [count])',
+ examples: [
+ 'MID("NocoDB", 3, 2) => "co"',
+ 'MID({column1}, 3, 2)'
+ ]
+ },
+ IF: {
+ type: formulaTypes.COND_EXP,
+ validation: {
+ args: {
+ min: 2,
+ max: 3
+ }
+ },
+ description: 'SuccessCase if expr evaluates to TRUE, elseCase otherwise',
+ syntax: 'IF(expr, successCase, elseCase)',
+ examples: [
+ 'IF(5 > 1, "YES", "NO") => "YES"',
+ 'IF({column} > 1, "YES", "NO")'
+ ]
+ },
+ SWITCH: {
+ type: formulaTypes.COND_EXP,
+ validation: {
+ args: {
+ min: 3
+ }
+ },
+ description: 'Switch case value based on expr output',
+ syntax: 'SWITCH(expr, [pattern, value, ..., default])',
+ examples: [
+ 'SWITCH(1, 1, "One", 2, "Two", "N/A") => "One""',
+ 'SWITCH(2, 1, "One", 2, "Two", "N/A") => "Two"',
+ 'SWITCH(3, 1, "One", 2, "Two", "N/A") => "N/A"',
+ 'SWITCH({column1}, 1, "One", 2, "Two", "N/A")'
+ ]
+ },
+ URL: {
+ type: formulaTypes.STRING,
+ validation: {
+ args: {
+ rqd: 1
+ }
+ },
+ description: 'Convert to a hyperlink if it is a valid URL',
+ syntax: 'URL(str)',
+ examples: [
+ 'URL("https://github.com/nocodb/nocodb")',
+ 'URL({column1})'
+ ]
+ }
}
-export default Object.keys(validations)
-export { validations }
+export default Object.keys(formulas)
+export { formulas, formulaTypes }
diff --git a/packages/noco-docs/content/en/setup-and-usages/formulas.md b/packages/noco-docs/content/en/setup-and-usages/formulas.md
index c667cfb27c..c933063622 100644
--- a/packages/noco-docs/content/en/setup-and-usages/formulas.md
+++ b/packages/noco-docs/content/en/setup-and-usages/formulas.md
@@ -66,13 +66,13 @@ Example: ({Column1} + ({Column2} * {Column3}) / (3 - $Column4$ ))
| Name | Syntax | Sample | Output |
|-------------|----------------------------------|---------------------------------|---------------------------------------------------------------------------|
| **CONCAT** | `CONCAT(str1, [str2,...])` | `CONCAT({Column1}, ' ', {Column2})` | Concatenated string of input parameters |
-| **LEFT** | `LEFT(str1, [str2,...])` | `LEFT({Column}, 3)` | `n` characters from the beginning of input parameter |
+| **LEFT** | `LEFT(str1, n)` | `LEFT({Column}, 3)` | `n` characters from the beginning of input parameter |
| **LEN** | `LEN(str)` | `LEN({Column})` | Input parameter character length |
| **LOWER** | `LOWER(str)` | `LOWER({Column})` | Lower case converted string of input parameter |
-| **MID** | `SUBTR(str, position, [count])` | `MID({Column}, 3, 2)` | Alias for `SUBSTR` |
+| **MID** | `MID(str, position, [count])` | `MID({Column}, 3, 2)` | Alias for `SUBSTR` |
| **REPEAT** | `REPEAT(str, count)` | `REPEAT({Column}, 2)` | Specified copies of the input parameter string concatenated together |
| **REPLACE** | `REPLACE(str, srchStr, rplcStr)` | `REPLACE({Column}, 'int', 'num')` | String, after replacing all occurrences of `srchStr` with `rplcStr` |
-| **RIGHT** | `RIGHT(str, count)` | `RIGHT({Column}, 3)` | `n` characters from the end of input parameter |
+| **RIGHT** | `RIGHT(str, n)` | `RIGHT({Column}, 3)` | `n` characters from the end of input parameter |
| **SEARCH** | `SEARCH(str, srchStr)` | `SEARCH({Column}, 'str')` | Index of `srchStr` specified if found, 0 otherwise |
| **SUBSTR** | `SUBTR(str, position, [count])` | `SUBSTR({Column}, 3, 2)` | Substring of length 'count' of input string, from the postition specified |
| **TRIM** | `TRIM(str)` | `TRIM({Column})` | Remove trailing and leading whitespaces from input parameter |
@@ -83,11 +83,13 @@ Example: ({Column1} + ({Column2} * {Column3}) / (3 - $Column4$ ))
| Name | Syntax | Sample | Output | Remark |
|---|---|---|---|---|
-| **DATEADD** | `DATEADD({DATE_COL}, 1, 'day')` | `DATEADD(date, 1, 'day')` | Supposing {DATE_COL} is 2022-03-14. The result is 2022-03-15. | DateTime columns and negative values are supported. Example: `DATEADD(DATE_TIME_COL, -1, 'day')` |
-| | `DATEADD({DATE_COL}, 2, 'month')` | `DATEADD(date, 2, 'month')` | Supposing {DATE_COL} is 2022-03-14 03:14. The result is 2022-05-14 03:14. | DateTime columns and negative values are supported. Example: `DATEADD(DATE_TIME_COL, -2, 'month')` |
+| **NOW** | `NOW()` | `NOW()` | 2022-05-19 17:20:43 | Returns the current time and day |
| | `IF(NOW() < {DATE_COL}, "true", "false")` | `IF(NOW() < date, "true", "false")` | If current date is less than {DATE_COL}, it returns true. Otherwise, it returns false. | DateTime columns and negative values are supported. |
-| | `IF(NOW() < DATEADD({DATE_COL},10,'day'), "true", "false")` | `IF(NOW() < DATEADD(date,10,'day'), "true", "false")` | If the current date is less than {DATE_COL} plus 10 days, it returns true. Otherwise, it returns false. | DateTime columns and negative values are supported. |
-
+| **DATEADD** | `DATEADD(date \| datetime, value, ["day" \| "week" \| "month" \| "year"])` | `DATEADD(date, 1, 'day')` | Supposing {DATE_COL} is 2022-03-14. The result is 2022-03-15. | DateTime columns and negative values are supported. Example: `DATEADD(DATE_TIME_COL, -1, 'day')` |
+| | | `DATEADD(date, 1, 'week')` | Supposing {DATE_COL} is 2022-03-14 03:14. The result is 2022-03-21 03:14. | DateTime columns and negative values are supported. Example: `DATEADD(DATE_TIME_COL, -1, 'week')` |
+| | | `DATEADD(date, 1, 'month')` | Supposing {DATE_COL} is 2022-03-14 03:14. The result is 2022-04-14 03:14. | DateTime columns and negative values are supported. Example: `DATEADD(DATE_TIME_COL, -1, 'month')` |
+| | | `DATEADD(date, 1, 'year')` | Supposing {DATE_COL} is 2022-03-14 03:14. The result is 2023-03-14 03:14. | DateTime columns and negative values are supported. Example: `DATEADD(DATE_TIME_COL, -1, 'year')` |
+| | | `IF(NOW() < DATEADD(date,10,'day'), "true", "false")` | If the current date is less than {DATE_COL} plus 10 days, it returns true. Otherwise, it returns false. | DateTime columns and negative values are supported. |
### Logical Operators
| Operator | Sample | Description |
@@ -104,7 +106,7 @@ Example: ({Column1} + ({Column2} * {Column3}) / (3 - $Column4$ ))
| Name | Syntax | Sample | Output |
|------------|------------------------------------------------|---------------------------------------------|-------------------------------------------------------------|
-| **IF** | `IF(expr, successCase, [failCase])` | `IF({Column} > 1, Value1, Value2)` | successCase if `expr` evaluates to TRUE, elseCase otherwise |
+| **IF** | `IF(expr, successCase, elseCase)` | `IF({Column} > 1, Value1, Value2)` | successCase if `expr` evaluates to TRUE, elseCase otherwise |
| **SWITCH** | `SWITCH(expr, [pattern, value, ..., default])` | `SWITCH({Column}, 1, 'One', 2, 'Two', '--')` | Switch case value based on `expr` output |
| **AND** | `AND(expr1, [expr2,...])` | `AND({Column} > 2, {Column} < 10)` | TRUE if all `expr` evaluate to TRUE |
| **OR** | `OR(expr1, [expr2,...])` | `OR({Column} > 2, {Column} < 10)` | TRUE if at least one `expr` evaluates to TRUE |