1. 概述
在 FineReport 產品中提供了多種函式以便於滿足使用者在日常使用中的需求,同時擁有 公式不合法報錯 的功能,本文主要介紹函式在使用程式中常見的問題及解決方案。
2. 日期函式
2.1 日期公式組合
2.1.1 往前推三個工作日
問題描述
往前推三個工作日,比如現在週五,得到週三,週六和週日也是得到週三,也就是不計算週末(無法跨越節假日)
解決方案
datedelta(today(), 0 - indexof('5552224', weekday(today())))
2.1.2 獲取當年第一天
解決方案
format(CONCATENATE(CONCATENATE(year(now()),"01"),"01"),"yyyy-MM-dd")
2.1.3 獲取上個月今天
解決方案
format(MONTHDELTA(now(),-1),"yyyy-MM-dd")
2.1.4 獲取參數上一年的指定日期
解決方案
FORMAT(date(year($riqi)-1,month($riqi),25),"yyyy-MM-dd")
2.2 日曆範本
問題描述
選擇具體月份,顯示對應日期和星期
解決方案
獲取日期:RANGE(1, DAYSOFMONTH($月份 "-01"))
獲取日期對應的星期:SWITCH(WEEKDAY($月份 "-" FORMAT(A5, "00")), "1", "一", "2", "二", "3", "三", "4", "四", "5", "五", "6", "六", "0", "日")
2.3 給當前系統時間加8個小時
解決方案
format(year(today()) "-" month(today()) "-" day(today()) " " (HOUR(now(), "HH:mm:ss") 8) ":"
MINUTE(now(), "HH:mm:ss") ":" SECOND(now(), "HH:mm:ss"), "yyyy-MM-dd HH:mm:ss")
2.4 today()公式的顯示問題
問題描述
填報預覽模式下,儲存格放一個日期元件,設定格式是yyyy-MM-dd,儲存格寫公式today(),預覽格式是正常的,編輯之後格式又變成了時間型別的。
解決方案
儲存格顯示內容需要在「樣式」處單獨設定。
2.5 TODATE()函式
2.5.1 TODATE()的開始日期
問題描述
todate(0)的傳回結果是1970-01-01 08:00:00。如何更改?
解決方案
DATETONUMBER(date):傳回自 1970 年 1 月 1 日 00:00:00 GMT 經過的毫秒數。時區問題,改成經緯度0的時區重啟電腦。
2.5.2 TODATE()函式顯示空白
問題描述
TODATE('2020/4/10', 'mm/dd/yy')儲存格公式輸入後預覽最新的JAR顯示為空白。10.0-2019.07.03版本以及之前JAR顯示正常。
解決方案
最近版本改了邏輯:就是參數不匹配出錯的時候傳回空 ,之前參數不匹配是傳回當前時間。函式的詳細使用可參見:TODATE() 函式 。
2.6 week()函式
問題描述
week(today())計算在百度上4.13是第16週,使用內建函式是15週,開始的比百度上面的晚一週。
解決方案
目前的規則師按照國際標準來的,所以目前做不了相容。
2.7 日期元件預設值寫today取到昨天
問題描述
遠端設計時,日期元件寫預設值today函式,不管型別選什麼,都取到昨天;正文元件寫today或者now都可以取到今天;linux伺服器系統時間和硬體時間都是今天。
解決方案
範本請求的響應內容裏搜下 date_milliseconds ,然後在前端執行瀏覽器 console 那邊執行 new Date(上一步的值), 這個結果跟日期元件是一致的即可。
2.8 now()公式的時間不對
問題描述
本地環境是對的,遠端環境不對。
原因分析
docker部署的工程,docker中鏡像的系統時間存在問題。
解決方案
修改部署 FineReport 的鏡像中的時間即可。
2.9 yyyy-MM格式的日期求月份差值
問題描述
start 是開始日期元件名,end 是結束日期元件名,兩個日期元件格式都是 yyyy-MM。
解決方案
(year(format($end,"yyyy-MM-dd"))-year(format($start,"yyyy-MM-dd")))*12 (month(format($end,"yyyy-MM-dd"))-month(format($start,"yyyy-MM-dd")))
2.10 today 1-”08:00:00“無法識別
問題描述
使用範本參數,範本參數識別元件的值減去八個小時,today 1-”08:00:00“無法識別
解決方案
設定兩個範本參數,定義公式「不要寫8:00:00」
3. 數字
3.1 數字公式組合
3.1.1 判斷小數位數
解決方案
假如A1是小數所在儲存格,LEN(A1)-FIND(".",A1,1)
3.1.2 取絕對值最大的陣列裏的資料
解決方案
max(split(replace(ds1.select(1),"-",""),","))
3.1.3 獲取最小值但是不包括0
解決方案
INDEXOFARRAY(SORTARRAY(GREPARRAY(C2[!0], index!= 0)),1)
3.1.4 判斷是不是小數
解決方案
$$$-trunc($$$)>0
3.2 最小值
問題描述
A1:D1的儲存格手填的值為23、4、65、1,可以使用min(A1:D1)獲取最小值1,如果某個儲存格為空,這個方法傳回的值是0
解決方案
min(GREPARRAY(array(a1),len(item)!=0),
GREPARRAY(array(b1),len(item)!=0),
GREPARRAY(array(c1),len(item)!=0),
GREPARRAY(array(d1),len(item)!=0)
)
3.3 find函式16位以上識別不準確
問題描述
使用ds1.find函式識別位數超過16位時,位數不準確
解決方案
所有計算類函式精度都只支援到16位
3.4 判斷儲存格內容是否是純數字
解決方案
先提取字串中的數字,然後和原字串比較長度,長度一致傳回true,代表純數字,不一致false,代表非純數字
len(JOINARRAY(GREPARRAY(split(A1, ""), regexp(item, "[0-9]")), "")) = len(A1)
3.5 去掉小數位後面的0
解決方案
比如資料88.98705670000,希望轉換成88.9870567,使用:format("88.98705670000","#0.################")
4. 字串
4.1 去掉真實姓名參數中的(帳號)
解決方案
left($fine_display_name, find("(", $fine_display_name) - 1)
4.2 儲存格公式連接參數和字串,參數為空時,固定值也無法顯示
問題描述
參數本身格式是陣列,儲存格用公式獲取參數,並且連接其他固定字串。如果參數為空,整個儲存格都會顯示空白。場景如下拉複選框傳回值為陣列格式時,儲存格內固定值預覽不顯示
原因分析
字串 陣列 的運算採用的映射運算,比如"AA" 陣列(1,2)=陣列(AA1,AA2)。
內部邏輯是:先根據與之相加的陣列的長度屬性把"AA"轉成陣列(AA,AA)然後與陣列(1,2)進行映射。
這個邏輯就會導致如果陣列是空陣列,那麼第一步字串轉陣列就除了問題,因為陣列長度為0,塞不進去
解決方案
參數為陣列時,儲存格公式改為判斷, if(len($參數)==0,"",$參數)。或者用陣列公式處理,將參數轉換為字串。
4.3 公式對於0開頭的字串匹配
問題描述
IF('000'=='00F','相等','不相等')公式正常結果應該是不相等,實際結果確是相等
解決方案
0是比較特殊,可以使用IF(exact("000","00F"),"相等","不相等")公式,exact()函式替代。
5. 其他問題
5.1 value函式在決策報表中無聯動效果
問題描述
在決策報表中,設定一個參數,使用一個元件作為參數輸入值,在其他元件、報表塊、圖表塊中使用 value 函式 獲取參數值,當輸入參數值改變時,獲取值不會隨之改變,即無聯動效果。
解決方案
5.2 跨sheet或跨報表塊使用條件過濾無效
問題描述
無論是普通報表、複合式報表還是決策報表,當涉及跨 sheet 頁或跨報表塊使用函式過濾時,若公式中包含了{}這種大括號的條件,則公式無效
解決方案