# 公式與函數
> 在制作表單時,可以設置控件與控件之間的數據聯動關系。給例如編輯完單價和數量后,自動計算總價等這樣的業務場景提供了支撐。
公式面板左側可以選擇**當前表單**控件所對應的*值*,以及**所有表單**控件所對應的*字段名*。被選擇后,在公式面板中會以反引號包裹的形式顯示。
**注意:函數在簡道云里的設置是大寫,即在運用函數的時候,請用純大寫字母。**
表單控件與其返回值的數據類型的對應關系如下表所示:
**這里要說明的是,使用公式時,該字段一定要對應返回的數據類型。字符串或數字,不能混淆。**
| 控件 | 返回數據類型 |
| --- | --- |
| 文本框 | 字符串 |
| 下拉框 | 字符串 |
| 單選按鈕組 | 字符串 |
| 下拉復選框 | 數組 |
| 多選按鈕組 | 數組 |
| 數字控件 | 數字 |
| 日期控件 | 時間戳(數字) |
公式面板除了支持基本的運算操作符`+`、`-`、`*`、`/`,還支持比較操作符?`>`、`<`、`>=`、`<=`、`==`,同時也支持類似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`。

即是說,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的返回值*)
判斷一個條件能否滿足;如果滿足返回一個值,如果不滿足則返回另外一個值。

在這個圖里表示,如果數字1>0,那么返回1,否則返回0。可以寫成IF(a,b,c),表示如果a,那么b,否則c。函數支持嵌套,IF函數多層嵌套也是很常用的,如下圖:

如果數字1>0,那么返回1,如果數字10,返回2,否則返回3。
### NOT
##### NOT(*logical*)
對參數邏輯值求反。
NOT比較簡單,就是把括號里為true的值變成false,括號里為false的值變為true。
### XOR
##### XOR(*logical1*,*[logical2]*, ...)
返回所有參數的異或值。
異或的含義是,兩個值相同,返回0,兩個值不同,返回1。
## 文本函數
> 處理字符串文本的一系列函數方法。
### CONCATENATE
##### CONCATENATE(*text1*,*[text2]*, ...)
將多個文本字符串合并成一個文本字符串。示例:

### EXACT
##### EXACT(*text1*,*text2*)
比較兩個字符串是否完全相同(區分大小寫)。完全相同則返回`true`,否則返回`false`。示例:

### LEFT
##### LEFT(*text*,*[num_chars]*)
從一個文本字符串的第一個字符開始返回指定個數的字符。示例:

含義為,取字符串第1位開始的后面3位字符,即字符串1的第1到第3個字符。
### LEN
##### LEN(*text*)
返回文本字符串中的字符個數。示例:

### 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`?中字符的文本。
示例:

意義為:將字符串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`?參數中從之開始搜索的字符編號。
示例:

表示從字符串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:*?必需。 指定希望從文本中返回字符的個數。
這個函數將用的比較多,舉一個在身份證號中提取生日的例子:

這個函數用了一個嵌套,用了前面說的CONCATENATE連接字符串的函數。提取身份證號的第7到10位,后面接“-”,提取身份證號的11、12位,接“-”,最后提取身份證號的13、14位。我們看下結果:
完美展現。
### 字符串函數綜合運用舉例
這里給出一個,根據身份證號碼自動算性別的函數,筆者水平有限,無法把各種函數的綜合運用一一例舉,這里用一個典型的函數來給大家啟發。

在這個表單里我要輸入身份證號碼,自動生成生日和性別。單行文本“性別”字段的函數為:

需要解釋的是,身份證號碼第17位為性別位,奇數為男性,偶數為女性。很多朋友提出為何不用MOD()函數(求余數的函數)來直接判斷奇偶,而是要用這么復雜的一個IF()語句。因為身份證最后一位可能是X,也就是說用數字格式是不滿足條件的。而且MID()取位函數只對字符串有效果,所以身份證號碼本身是一個字符串,也就是單行文本控件,這是不支持數字運算的。所以MOD()函數不能用。
那么我們用OR()語句(或語句),就是說第17位為1,3,5,7,9的時候,返回“男”,否則返回“女”。我們看看效果:

第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:*?必需。需要加減的天數。正數為增加,負數為減少。
### 日期格式綜合運用舉例:
例:根據生日計算年齡。

這里是表單,我想輸入日期,計算出實際年齡。這時候姓名和出生日期不用多說,年齡可以采用數字或單行文本格式。公式如下:

解析: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個。

對“我是第幾個報名的”字段進行編輯函數:

根據MAP函數的定義,括號里的第一個值為需要檢索的值,第二個值為檢索范圍,第三個值為返回值。對于這個例子,可解釋為:在所有錄入過的“課程信息”字段里查找本次錄入的“課程信息”,每找到一個本次錄入的“課程信息”,就返回一個“我是第幾個報名”,最后用COUNT函數統計一下返回了幾個“我是第幾個報名的”,當然這里用來計數的字段可以選擇“請輸入學號”或“姓名”。看一下效果:
?選擇了健身課,發現自己是第三個報名的,已經有2人報名。