# 公式与函数
> 在制作表单时,可以设置控件与控件之间的数据联动关系。给例如编辑完单价和数量后,自动计算总价等这样的业务场景提供了支撑。
公式面板左侧可以选择**当前表单**控件所对应的*值*,以及**所有表单**控件所对应的*字段名*。被选择后,在公式面板中会以反引号包裹的形式显示。
**注意:函数在简道云里的设置是大写,即在运用函数的时候,请用纯大写字母。**
表单控件与其返回值的数据类型的对应关系如下表所示:
**这里要说明的是,使用公式时,该字段一定要对应返回的数据类型。字符串或数字,不能混淆。**
| 控件 | 返回数据类型 |
| --- | --- |
| 文本框 | 字符串 |
| 下拉框 | 字符串 |
| 单选按钮组 | 字符串 |
| 下拉复选框 | 数组 |
| 多选按钮组 | 数组 |
| 数字控件 | 数字 |
| 日期控件 | 时间戳(数字) |
公式面板除了支持基本的运算操作符`+`、`-`、`*`、`/`,还支持比较操作符 `>`、`<`、`>=`、`<=`、`==`,同时也支持类似Excel中的部分函数公式,所有支持的函数公式如下:
* [逻辑函数](http://help.jiandaoyun.com/chapters/advance/formula.html#logic)
* [ADD](http://help.jiandaoyun.com/chapters/advance/formula.html#and)
* [OR](http://help.jiandaoyun.com/chapters/advance/formula.html#or)
* [FALSE](http://help.jiandaoyun.com/chapters/advance/formula.html#false)
* [TRUE](http://help.jiandaoyun.com/chapters/advance/formula.html#true)
* [IF](http://help.jiandaoyun.com/chapters/advance/formula.html#if)
* [NOT](http://help.jiandaoyun.com/chapters/advance/formula.html#not)
* [XOR](http://help.jiandaoyun.com/chapters/advance/formula.html#xor)
* [文本函数](http://help.jiandaoyun.com/chapters/advance/formula.html#text)
* [CONCATENATE](http://help.jiandaoyun.com/chapters/advance/formula.html#concatenate)
* [EXACT](http://help.jiandaoyun.com/chapters/advance/formula.html#exact)
* [LEFT](http://help.jiandaoyun.com/chapters/advance/formula.html#left)
* [LEN](http://help.jiandaoyun.com/chapters/advance/formula.html#len)
* [LOWER](http://help.jiandaoyun.com/chapters/advance/formula.html#lower)
* [REPLACE](http://help.jiandaoyun.com/chapters/advance/formula.html#replace)
* [REPT](http://help.jiandaoyun.com/chapters/advance/formula.html#rept)
* [SEARCH](http://help.jiandaoyun.com/chapters/advance/formula.html#search)
* [RIGHT](http://help.jiandaoyun.com/chapters/advance/formula.html#right)
* [SPLIT](http://help.jiandaoyun.com/chapters/advance/formula.html#split)
* [TRIM](http://help.jiandaoyun.com/chapters/advance/formula.html#trim)
* [UPPER](http://help.jiandaoyun.com/chapters/advance/formula.html#upper)
* [MID](http://help.jiandaoyun.com/chapters/advance/formula.html#mid)
* [数学函数](http://help.jiandaoyun.com/chapters/advance/formula.html#math)
* [AVERAGE](http://help.jiandaoyun.com/chapters/advance/formula.html#average)
* [COUNT](http://help.jiandaoyun.com/chapters/advance/formula.html#count)
* [LARGE](http://help.jiandaoyun.com/chapters/advance/formula.html#large)
* [MAX](http://help.jiandaoyun.com/chapters/advance/formula.html#max)
* [MIN](http://help.jiandaoyun.com/chapters/advance/formula.html#min)
* [SMALL](http://help.jiandaoyun.com/chapters/advance/formula.html#small)
* [ABS](http://help.jiandaoyun.com/chapters/advance/formula.html#abs)
* [ROUND](http://help.jiandaoyun.com/chapters/advance/formula.html#round)
* [CEILING](http://help.jiandaoyun.com/chapters/advance/formula.html#ceiling)
* [FLOOR](http://help.jiandaoyun.com/chapters/advance/formula.html#floor)
* [INT](http://help.jiandaoyun.com/chapters/advance/formula.html#int)
* [LOG](http://help.jiandaoyun.com/chapters/advance/formula.html#log)
* [MOD](http://help.jiandaoyun.com/chapters/advance/formula.html#mod)
* [POWER](http://help.jiandaoyun.com/chapters/advance/formula.html#power)
* [PRODUCT](http://help.jiandaoyun.com/chapters/advance/formula.html#product)
* [SQRT](http://help.jiandaoyun.com/chapters/advance/formula.html#sqrt)
* [SUM](http://help.jiandaoyun.com/chapters/advance/formula.html#sum)
* [FIXED](http://help.jiandaoyun.com/chapters/advance/formula.html#fixed)
* [日期与时间函数](http://help.jiandaoyun.com/chapters/advance/formula.html#datetime)
* [DATE](http://help.jiandaoyun.com/chapters/advance/formula.html#date)
* [TIMESTAMP](http://help.jiandaoyun.com/chapters/advance/formula.html#timestamp)
* [TIME](http://help.jiandaoyun.com/chapters/advance/formula.html#time)
* [TODAY](http://help.jiandaoyun.com/chapters/advance/formula.html#today)
* [NOW](http://help.jiandaoyun.com/chapters/advance/formula.html#now)
* [DAY](http://help.jiandaoyun.com/chapters/advance/formula.html#day)
* [MONTH](http://help.jiandaoyun.com/chapters/advance/formula.html#month)
* [YEAR](http://help.jiandaoyun.com/chapters/advance/formula.html#year)
* [HOUR](http://help.jiandaoyun.com/chapters/advance/formula.html#hour)
* [MINUTE](http://help.jiandaoyun.com/chapters/advance/formula.html#minute)
* [SECOND](http://help.jiandaoyun.com/chapters/advance/formula.html#second)
* [DAYS](http://help.jiandaoyun.com/chapters/advance/formula.html#days)
* [DATEDELTA](http://help.jiandaoyun.com/chapters/advance/formula.html#datedelta)
* [高级函数](http://help.jiandaoyun.com/chapters/advance/formula.html#advance)
* [MAP](http://help.jiandaoyun.com/chapters/advance/formula.html#map)
## 逻辑函数
> 返回`true`或者`false`一类的函数方法。
### AND
##### AND(*logical1*, *[logical2]*, ...)
在参数组中,任何一个参数逻辑值为`false`,即返回`false`;只有当所有参数逻辑值为`true`,才返回`true`。
![](https://box.kancloud.cn/2015-08-20_55d56f7266762.png)
即是说,AND函数,是求括号里两个或多个逻辑式子共同满足true(逗号隔开的逻辑式子都满足)的时候,返回的结果为1,即true。
### OR
##### OR(*logical1*,*[logical2]*, ...)
在参数组中,任何一个参数逻辑值为`true`,即返回`true`;只有当所有逻辑参数值为`false`,才返回`false`。
和AND函数一样,不同的地方在于,括号里只要有1个逻辑式为true,返回的结果就是1,也就是true。
### FALSE
##### FALSE()
返回逻辑值`false`。
### TRUE
##### TRUE()
返回逻辑值`true`。
TRUE和FALSE一样,都是强制括号中的逻辑式为1或0。
### IF
##### IF(*判断条件*,*结果为true的返回值*, *结果为false的返回值*)
判断一个条件能否满足;如果满足返回一个值,如果不满足则返回另外一个值。
![](https://box.kancloud.cn/2015-08-20_55d56f72c5756.png)
在这个图里表示,如果数字1>0,那么返回1,否则返回0。可以写成IF(a,b,c),表示如果a,那么b,否则c。函数支持嵌套,IF函数多层嵌套也是很常用的,如下图:
![](https://box.kancloud.cn/2015-08-20_55d56f7302e2a.png)
如果数字1>0,那么返回1,如果数字10,返回2,否则返回3。
### NOT
##### NOT(*logical*)
对参数逻辑值求反。
NOT比较简单,就是把括号里为true的值变成false,括号里为false的值变为true。
### XOR
##### XOR(*logical1*,*[logical2]*, ...)
返回所有参数的异或值。
异或的含义是,两个值相同,返回0,两个值不同,返回1。
## 文本函数
> 处理字符串文本的一系列函数方法。
### CONCATENATE
##### CONCATENATE(*text1*,*[text2]*, ...)
将多个文本字符串合并成一个文本字符串。示例:
![](https://box.kancloud.cn/2015-08-20_55d56f73471fb.png)
### EXACT
##### EXACT(*text1*,*text2*)
比较两个字符串是否完全相同(区分大小写)。完全相同则返回`true`,否则返回`false`。示例:
![](https://box.kancloud.cn/2015-08-20_55d56f7393cbf.png)
### LEFT
##### LEFT(*text*,*[num_chars]*)
从一个文本字符串的第一个字符开始返回指定个数的字符。示例:
![](https://box.kancloud.cn/2015-08-20_55d56f73da295.png)
含义为,取字符串第1位开始的后面3位字符,即字符串1的第1到第3个字符。
### LEN
##### LEN(*text*)
返回文本字符串中的字符个数。示例:
![](https://box.kancloud.cn/2015-08-20_55d56f7436c70.png)
### LOWER
##### LOWER(*text*)
将一个文本字符串中的所有大写字母转换为小写字母。
### REPLACE
##### REPLACE(*old_text*, *start_num*, *num_chars*, *new_text*)
根据指定的字符数,将部分文本字符串替换为不同的文本字符串。
* *old_text:* 必需。要替换其部分字符的文本。
* *start_num:* 必需。`old_text` 中要替换为 `new_text` 的字符位置。
* *num_chars:* 必需。`old_text` 中希望使用 `new_text` 来进行替换的字符数。
* *new_text:* 必需。将替换 `old_text` 中字符的文本。
示例:
![](https://box.kancloud.cn/2015-08-20_55d56f7486d14.png)
意义为:将字符串1中的第2位之后的4位,用字符串2来替换。
### REPT
##### REPT(*text*, *number_times*)
将文本重复一定次数。
* *text:* 必需。需要重复显示的文本。
* *Number_times:* 必需。用于指定文本重复次数的正数。
### SEARCH
##### SEARCH(*find_text*,*within_text*,*[start_num]*)
在第二个文本字符串中查找第一个文本字符串,并返回第一个文本字符串的起始位置的编号,该编号从第二个文本字符串的第一个字符算起。返回`0`则表示未查找到。
* *find_text:* 必需。要查找的文本。
* *within_text:* 必需。要在其中搜索 `find_text` 参数的值的文本。
* *start_num:* 可选。`within_text` 参数中从之开始搜索的字符编号。
示例:
![](https://box.kancloud.cn/2015-08-20_55d56f74d52ac.png)
表示从字符串2中的第1位开始搜索字符串1。
### RIGHT
##### RIGHT(*text*,*[num_chars]*)
返回文本值中最右边的字符。
* *text:* 必需。包含要提取字符的文本字符串。
* *num_chars:* 可选。指定希望提取的字符数。
### SPLIT
##### SPLIT(*text*, *text_separator*)
将文本按指定字符串分割成数组。
### TRIM
##### TRIM(*text*)
删除文本中的空格。
### UPPER
##### UPPER(*text*)
将一个文本字符串中的所有小写字母转换为大写字母。
### MID
##### MID(*text*, *start_num*, *num_chars*)
返回文本字符串中从指定位置开始的特定数目的字符,该数目由用户指定。
* *text:* 必需。 包含要提取字符的文本字符串。
* *start_num:* 必需。 文本中要提取的第一个字符的位置。 文本中第一个字符的`start_num`为 1,以此类推。
* *num_chars:* 必需。 指定希望从文本中返回字符的个数。
这个函数将用的比较多,举一个在身份证号中提取生日的例子:
![](https://box.kancloud.cn/2015-08-20_55d56f753de4b.png)
这个函数用了一个嵌套,用了前面说的CONCATENATE连接字符串的函数。提取身份证号的第7到10位,后面接“-”,提取身份证号的11、12位,接“-”,最后提取身份证号的13、14位。我们看下结果:
![](https://box.kancloud.cn/2015-08-20_55d56f7a7b31a.png)完美展现。
### 字符串函数综合运用举例
这里给出一个,根据身份证号码自动算性别的函数,笔者水平有限,无法把各种函数的综合运用一一例举,这里用一个典型的函数来给大家启发。
![](https://box.kancloud.cn/2015-08-20_55d56f7ad2811.jpg)
在这个表单里我要输入身份证号码,自动生成生日和性别。单行文本“性别”字段的函数为:
![](https://box.kancloud.cn/2015-08-20_55d56f7b37eb2.png)
需要解释的是,身份证号码第17位为性别位,奇数为男性,偶数为女性。很多朋友提出为何不用MOD()函数(求余数的函数)来直接判断奇偶,而是要用这么复杂的一个IF()语句。因为身份证最后一位可能是X,也就是说用数字格式是不满足条件的。而且MID()取位函数只对字符串有效果,所以身份证号码本身是一个字符串,也就是单行文本控件,这是不支持数字运算的。所以MOD()函数不能用。
那么我们用OR()语句(或语句),就是说第17位为1,3,5,7,9的时候,返回“男”,否则返回“女”。我们看看效果:
![](https://box.kancloud.cn/2015-08-20_55d56f7b71747.jpg)
第17位为2,性别“女”,生日为1980-01-01,完美展现。
## 数学函数
> 处理数字的一系列函数方法。
>
> 数学函数比较简单,下面罗列出了每个数学函数的功能,理解起来也比较方便,就不再举例说明。
### AVERAGE
##### AVERAGE(*number1*, *[number2]*, ...)
返回参数的平均值(算术平均值)。
### COUNT
##### COUNT(*value1*, *[value2]*, ...)
统计参数个数。
### LARGE
##### LARGE(*array*,*k*)
返回数据集中第`k`个最大值。
* *Array:* 必需。 需要确定第 `k` 个最大值的数组或数据区域。
* *k:* 必需。 返回值在数组中的位置(从大到小排)。
### MAX
##### MAX(*number1*, *[number2]*, ...)
返回一组值中的最大值。
### MIN
##### MIN(*number1*, *[number2]*, ...)
返回一组值中的最小值。
### SMALL
##### SMALL(*array*,*k*)
返回数据集中第`k`个最小值。
* *Array:* 必需。 需要确定第 `k` 个最小值的数组或数据区域。
* *k:* 必需。 返回值在数组中的位置(从小到大排)。
### ABS
##### ABS(number)
返回数字的绝对值。
### ROUND
##### ROUND(*number*, *num_digits*)
将数字四舍五入到指定的位数。
* *number:* 必需。 要四舍五入的数字。
* *num_digits:* 必需。 要进行四舍五入运算的位数。
### CEILING
##### CEILING(*number*, *significance*)
返回将参数 number 向上舍入(沿绝对值增大的方向)为最接近的指定基数的倍数。
* *Number:* 必需。 要舍入的值。
* *significance:* 必需。 要舍入到的倍数。
### FLOOR
##### FLOOR(*number*, *significance*)
将参数 `number` 向下舍入(沿绝对值减小的方向)为最接近的 `significance` 的倍数。
* *number:* 必需。 要舍入的数值。
* *significance:* 必需。 要舍入到的倍数。
### INT
##### INT(*number*)
将数字向下舍入到最接近的整数。
### LOG
##### LOG(*number*, *[base]*)
根据指定底数返回数字的对数。
* *number:* 必需。 想要计算其对数的正实数。
* *base:* 可选。 对数的底数。 如果省略 base,则假定其值为 10。
### MOD
##### MOD(*number*, *divisor*)
返回两数相除的余数。 结果的符号与除数相同。
* *number:* 必需。 要计算余数的被除数。
* *divisor:* 必需。 除数。
### POWER
##### POWER(*number*, *power*)
返回数字乘幂的结果。
* *number:* 必需。 基数。 可为任意实数。
* *power:* 必需。 基数乘幂运算的指数。
### PRODUCT
##### PRODUCT(*number1*, *[number2]*, ...)
函数使所有以参数形式给出的数字相乘并返回乘积。
### SQRT
##### SQRT(*number*)
返回正的平方根。
### SUM
##### SUM(*number1*, *[number2]*, ...)
函数使所有以参数形式给出的数字相加并返回和。
### FIXED
##### FIXED(*number*, *[decimals]*)
将数字舍入到指定的小数位数,以十进制数格式对该数进行格式设置,并以文本形式返回结果。
* *number:* 必需。 要进行舍入并转换为文本的数字。
* *decimals:* 可选。 小数点右边的位数。
## 日期与时间函数
> 用于处理日期和时间的一系列函数方法。
**注意:日期控件的返回值为时间戳,单位是毫秒。而以下函数方法的参数大都是日期对象。所以可以用DATE函数处理成日期对象。**
**时间戳:时间戳是计算机记录时间的一种格式。通常是一个字符序列,唯一地标识某一刻的时间。数字时间戳技术是数字签名技术一种变种的应用。在简道云表单中,“日期时间”控件便是由这样的序列来存储的,因此在进行公式运算的时候要进行转换。**
**日期对象:日期对象的表示格式为“Sat Aug 01 2015 00:00:00 GMT+0800 (中国标准时间)”,即北京时间2015年8月1日00:00:00,这个日期对象可以进行各种运算,比如日期加减法等等。**
### DATE
##### DATE(*timestamp*)
将时间戳转换为日期对象。
* *timestamp:* 必需。时间戳。
##### DATE(*year*,*month*,*day*)
##### DATE(*year*,*month*,*day*,*hour*,*minute*,*second*)
将年月日时分秒转换为日期对象。
* *year:* 必需。年份。
* *month:* 必需。月份。
* *day:* 必需。天数。
* *hour:* 必需。小时。
* *minute:* 必需。分钟。
* *second:* 必需。秒。
例如,2015年12月1日的日期对象可以用如下表示:
~~~
DATE(2015,11,1)
DATE(1448899200000)
DATE(2015,11,1,0,0,0)
这三个都表示“Sun Nov 01 2015 00:00:00 GMT+0800 (中国标准时间)”
~~~
### TIMESTAMP
##### TIMESTAMP(*date*)
将日期对象转换成时间戳。
### TIME
##### TIME(*hour*, *minute*, *second*)
返回特定时间的十进制数字。时间值为日期值的一部分,并用十进制数表示(例如 12:00 PM 可表示为 0.5,因为此时是一天的一半)。
* *hour:* 必需。 0(零)到 32767 之间的数字,代表小时。 任何大于 23 的值都会除以 24,余数将作为小时值。 例如,TIME(27,0,0) = TIME(3,0,0) = .125
* *minute:* 必需。 0 到 32767 之间的数字,代表分钟。 任何大于 59 的值将转换为小时和分钟。 例如,TIME(0,750,0) = TIME(12,30,0) = .520833
* *second:* 必需。 0 到 32767 之间的数字,代表秒。 任何大于 59 的值将转换为小时、分钟和秒。 例如,TIME(0,0,2000) = TIME(0,33,22) = .023148
### TODAY
##### TODAY()
返回今天。
### NOW
##### NOW()
返回当前时间。与`TODAY`函数相同。
### DAY
##### DAY(*date*)
返回某日期的天数。 天数是介于 1 到 31 之间的整数。
### MONTH
##### MONTH(*date*)
返回某日期的月份。 月份是介于 1 到 12 之间的整数。
### YEAR
##### YEAR(*date*)
返回某日期的年份。
### HOUR
##### HOUR(*date*)
返回某日期的小时数。
### MINUTE
##### MINUTE(*date*)
返回某日期的分钟数。
### SECOND
##### SECOND(*date*)
返回某日期的秒数。
### DAYS
##### DAYS(*end_date*, *start_date*)
返回两个日期之间的天数。
* *end_date:* 必需。结束日期。
* *start_date:* 必需。起始日期。
### DATEDELTA
##### DATEDELTA(*date*, *deltadays*)
将指定日期加/减指定天数。
* *date:* 必需。初始日期。
* *deltadays:* 必需。需要加减的天数。正数为增加,负数为减少。
### 日期格式综合运用举例:
例:根据生日计算年龄。
![](https://box.kancloud.cn/2015-08-20_55d56f7bdac10.png)
这里是表单,我想输入日期,计算出实际年龄。这时候姓名和出生日期不用多说,年龄可以采用数字或单行文本格式。公式如下:
![](https://box.kancloud.cn/2015-08-20_55d56f7d476fd.png)
解析:TODAY()返回的是date,即日期对象;DATE('出生日期')返回的是date日期对象,然后都用YEAR()函数取年份,相减即可。
## 高级函数
> 用于获取表数据的一系列高级函数方法。
### MAP
###### MAP(*map_value*, *map_field*, *result_field*)
当指定表单的`map_field`列的值为`map_value`时,返回`result_field`的所有值,返回结果为数组。类似Excel的`LOOKUP`函数。
* *map_value:* 必需。条件字段值。
* *map_field:* 必需。条件字段名。
* *result_field:* 必需。结果字段名。
MAP函数是一个“跨表单”函数。即上面的所有函数都是在当前表单运算的函数,无法读取和调用已经提交的其他表单。MAP函数可以在一定程度上弥补这样的不足。
这里要区分一个概念。表单,正在编辑的表单,也叫表单,这里的跨表单可能指的是2个模板,在同一个应用里实现不同功能的字段都不是完全相同的模板。其实表单还有另外一个意思,2次提交同一个表单,拥有相同字段不同内容的两张表单。MAP函数应用的跨表单是后者,如果理解不了,只要记得MAP可以调用已填写的数据即可。
下面我们举例说明一下:
这里有一个选课表,课程信息字段里有几个可选择的课程,但是每个课程有人数限制,每当一个人报名,就要累加1个。
![](https://box.kancloud.cn/2015-08-20_55d56f7d7b17e.png)
对“我是第几个报名的”字段进行编辑函数:
![](https://box.kancloud.cn/2015-08-20_55d56f8034a29.png)
根据MAP函数的定义,括号里的第一个值为需要检索的值,第二个值为检索范围,第三个值为返回值。对于这个例子,可解释为:在所有录入过的“课程信息”字段里查找本次录入的“课程信息”,每找到一个本次录入的“课程信息”,就返回一个“我是第几个报名”,最后用COUNT函数统计一下返回了几个“我是第几个报名的”,当然这里用来计数的字段可以选择“请输入学号”或“姓名”。看一下效果:
![](https://box.kancloud.cn/2015-08-20_55d56f806b047.png) 选择了健身课,发现自己是第三个报名的,已经有2人报名。