#
組織樹報(bào)表中由id與父id來實(shí)現(xiàn)組織樹報(bào)表,若層級(jí)數(shù)較多時(shí),對(duì)每個(gè)單元格設(shè)置過濾條件和形態(tài)會(huì)比較繁瑣,因此FineReport提供了一種特殊的數(shù)據(jù)集——樹數(shù)據(jù)集,只需要簡(jiǎn)單的設(shè)置就能自動(dòng)遞歸出層級(jí),方便的實(shí)現(xiàn)如下圖組織樹報(bào)表:
圖一

圖二

構(gòu)建樹
新建工作薄,添加數(shù)據(jù)集ds1取出原始數(shù)據(jù),SQL語句為SELECT * FROM 公司部門。
1)根據(jù)父字段構(gòu)建樹
使用情形:原始表結(jié)構(gòu)中符合ID、parentID結(jié)構(gòu),我們可以通過父ID這個(gè)字段生成樹,添加樹數(shù)據(jù)集,如下圖:


2)根據(jù)數(shù)據(jù)長度構(gòu)建樹
使用情形:原始表結(jié)構(gòu)中所有ID都在一列中,且沒有父ID字段,但是ID是有規(guī)律的,每組的長度相同,且子級(jí)的前N位就是父級(jí)編號(hào),添加樹數(shù)據(jù)集,如下圖:


預(yù)覽樹數(shù)據(jù)集,可看到已自動(dòng)生成遞歸樹數(shù)據(jù),F(xiàn)R_GEN_0為最高層,依次往下,如下:

縱向組織樹編輯
按照下圖所示將對(duì)應(yīng)的數(shù)據(jù)列拖入到單元格中,并將A2單元格的左父格設(shè)置為A1,A3單元格的左父格設(shè)置為A2:

有上面預(yù)覽數(shù)據(jù)可以看到從二層FR_GEN_1開始,就會(huì)有空白數(shù)據(jù),這是因?yàn)閿?shù)據(jù)庫中存儲(chǔ)的數(shù)據(jù)有上一級(jí)部門本身的部門名稱和部門ID,其上一級(jí)部門的部門級(jí)數(shù)會(huì)低一級(jí),比如說上述數(shù)據(jù)的第一行為總部,雖然總部下面有子部門,但是數(shù)據(jù)庫中還是要存儲(chǔ)總部這個(gè)部門的部門名稱和部門ID的,總部對(duì)應(yīng)的級(jí)數(shù)為一級(jí),那么其對(duì)應(yīng)的數(shù)據(jù)記錄行里面就只有FR_GEN_0層,下面的FR_GEN_1和FR_GEN_2這兩層就會(huì)沒有數(shù)據(jù),顯示為空白。
在模板制作過程中,從第二層級(jí)開始就會(huì)有空白數(shù)據(jù),需要將空白數(shù)據(jù)隱藏掉,選中A2和A3單元格,添加條件屬性,當(dāng)數(shù)據(jù)為空時(shí)隱藏該行,如下圖: 
如果組織結(jié)構(gòu)的層級(jí)結(jié)構(gòu)不確定,即有的層級(jí)有子層,有的層級(jí)沒有子層時(shí),其組織樹報(bào)表的實(shí)現(xiàn)方式請(qǐng)查看不規(guī)范組織樹報(bào)表
由于自動(dòng)生成的字段是編碼,可以使用數(shù)據(jù)字典將其轉(zhuǎn)為對(duì)應(yīng)的部門名稱,如下圖:
保存模板,點(diǎn)擊分頁預(yù)覽,效果如圖一。
橫向組織樹編輯
按照下圖所示將對(duì)應(yīng)的數(shù)據(jù)列拖入到單元格中,在右側(cè)單元格屬性表-擴(kuò)展屬性中將B1、C1單元格的擴(kuò)展方向設(shè)為橫向,
并將B1單元格的左父格設(shè)置為A1,C1單元格的左父格設(shè)置為B1:
有上面預(yù)覽數(shù)據(jù)可以看到從二層FR_GEN_1開始,就會(huì)有空白數(shù)據(jù),這是因?yàn)閿?shù)據(jù)庫中存儲(chǔ)的數(shù)據(jù)有上一級(jí)部門本身的部門名稱和部門ID,其上一級(jí)部門的部門級(jí)數(shù)會(huì)低一級(jí),比如說上述數(shù)據(jù)的第一列為總部,雖然總部下面有子部門,但是數(shù)據(jù)庫中還是要存儲(chǔ)總部這個(gè)部門的部門名稱和部門ID的,總部對(duì)應(yīng)的級(jí)數(shù)為一級(jí),那么其對(duì)應(yīng)的數(shù)據(jù)記錄列里面就只有FR_GEN_0層,下面的FR_GEN_1和FR_GEN_2這兩層就會(huì)沒有數(shù)據(jù),顯示為空白。
在模板制作過程中,從第二層級(jí)開始就會(huì)有空白數(shù)據(jù),需要將空白數(shù)據(jù)隱藏掉,選中B1和C1單元格,添加條件屬性,當(dāng)數(shù)據(jù)為空時(shí)隱藏該列,如下圖:

如果組織結(jié)構(gòu)的層級(jí)結(jié)構(gòu)不確定,即有的層級(jí)有子層,有的層級(jí)沒有子層時(shí),其組織樹報(bào)表的實(shí)現(xiàn)方式請(qǐng)查看不規(guī)則組織樹報(bào)表
由于自動(dòng)生成的字段是編碼,可以使用數(shù)據(jù)字典將其轉(zhuǎn)為對(duì)應(yīng)的部門名稱,如下圖:
保存模板,點(diǎn)擊分頁預(yù)覽,效果如圖二。
在企業(yè)應(yīng)用中,通常單個(gè)計(jì)算機(jī)的配置是有限的,而企業(yè)應(yīng)用又是高并發(fā)的需求,這個(gè)時(shí)候會(huì)通過計(jì)算機(jī)集群的方式來提高并發(fā)數(shù),從而提高整體應(yīng)用服務(wù)的性能。集群是將多臺(tái)計(jì)算機(jī)作為一個(gè)整體來提供相關(guān)應(yīng)用的服務(wù)。FineBI支持多計(jì)算機(jī)服務(wù)的集群部署,通過集群部署利用有限的計(jì)算機(jī)資源來有效提高整體應(yīng)用的并發(fā)性能。本文主要介紹整體FineBI集群的思路。
FineBI采用負(fù)載均衡集群的模式,將多臺(tái)服務(wù)器創(chuàng)建為一個(gè)集群服務(wù)器。這里碰到這幾個(gè)問題:1)web工程的存儲(chǔ)問題:FineBI在集群中,由于自身的問題需要多臺(tái)服務(wù)器讀取同一個(gè)web工程。因此要實(shí)現(xiàn)web工程分享。2)系統(tǒng)數(shù)據(jù)一致性:在FineBI的運(yùn)行過程中,存在讀寫的操作,同時(shí)有部分的數(shù)據(jù)的配置文件要寫入數(shù)據(jù)庫。需要保證集群的情況下,系統(tǒng)數(shù)據(jù)的一致性。3)負(fù)載均衡:一方面通過負(fù)載均衡來處理session的問題,另一方面達(dá)成負(fù)載均衡的集群環(huán)境,使用代理服務(wù)器可以將請(qǐng)求轉(zhuǎn)發(fā)給集群內(nèi)部的服務(wù)器,可以將負(fù)載均衡和代理服務(wù)器的高速緩存技術(shù)結(jié)合在一起,提供有益的性能。4)FS平臺(tái)集群:如FineBI使用FS平臺(tái),則FS平臺(tái)的各種配置也需要進(jìn)行集群配置。
如下圖是一個(gè)FineBI進(jìn)去的架構(gòu)的案例示意圖,這種方式通過NFS文件共享來處理web工程。

Web工程存儲(chǔ)問題
Web工程的存儲(chǔ),我們要解決的是多個(gè)服務(wù)器保證讀取同一個(gè)web工程。我們可以通過ceph做到多塊物理硬盤組件一塊邏輯硬盤,從而實(shí)現(xiàn)所有節(jié)點(diǎn)都是在訪問同一地址;也可以通過linux本身帶有的nfs共享文件服務(wù)來達(dá)成訪問同一web工程。無論使用哪一種方式,我們要保證:
<!--[if !supportLists]-->1)<!--[endif]-->訪問同一web工程
<!--[if !supportLists]-->2)<!--[endif]-->Cube存儲(chǔ)地址是一致的
因?yàn)橥粋€(gè)web工程下,要求cube的存儲(chǔ)地址是一致的,因此要求cube存儲(chǔ)地址一定要一樣。
而真正使用的時(shí)候,ceph的實(shí)現(xiàn)需要至少三臺(tái)計(jì)算機(jī)來實(shí)現(xiàn),而實(shí)際企業(yè)應(yīng)用中,比較少使用三臺(tái);而nfs均可以且是linux本身的,因此使用“nfs”方案。
系統(tǒng)數(shù)據(jù)配置
單節(jié)點(diǎn)的情況下,利用緩存和通過操作系統(tǒng)的文件系統(tǒng)來保存數(shù)據(jù)的方式,在集群模式下不再合適。主要原因在于數(shù)據(jù)的一致性問題,多個(gè)節(jié)點(diǎn)可能進(jìn)行同時(shí)讀寫,更改系統(tǒng)數(shù)據(jù),最終勢(shì)必會(huì)造成整體數(shù)據(jù)不一致。最好的解決方案是系統(tǒng)配置數(shù)據(jù)全部交給MySQL等關(guān)系型數(shù)據(jù)庫來管理。但由于這樣工程量好大,更主要的原因?yàn)樵S多代碼缺少維護(hù),貿(mào)然更改可能帶來意想不到的bug。于是我們采用一種折中的做法。在集群中選出一臺(tái)幾點(diǎn)作為主節(jié)點(diǎn),簡(jiǎn)稱M。其余節(jié)點(diǎn)擔(dān)當(dāng)子節(jié)點(diǎn),簡(jiǎn)稱S。當(dāng)S上所有與更改系統(tǒng)配置相關(guān)的操作,全部發(fā)送到M上進(jìn)行處理。M負(fù)責(zé)來更改系統(tǒng)狀態(tài),維護(hù)整個(gè)系統(tǒng)到底一致的狀態(tài)。S節(jié)點(diǎn)放棄全部的緩存數(shù)據(jù),讀取狀態(tài)的時(shí)候,不再通過讀取自身數(shù)據(jù),而是通過向M發(fā)送讀取請(qǐng)求,獲得M上的數(shù)據(jù)。M節(jié)點(diǎn)自身可以存在緩存數(shù)據(jù)。其他數(shù)據(jù)S節(jié)點(diǎn)與M節(jié)點(diǎn)時(shí)等同的,不存在從屬關(guān)系。

因此按上述原由我們提供如下解決方案:
<!--[if !supportLists]-->1)<!--[endif]-->mysql數(shù)據(jù)庫:原web工程中存在finedb的配置信息轉(zhuǎn)存到mysql數(shù)據(jù)庫中。因?yàn)閒inedb數(shù)據(jù)庫只能有一個(gè)連接,無法多節(jié)點(diǎn)同時(shí)讀取,而mysql數(shù)據(jù)庫則不存在。Logdb也需遷移;
<!--[if !supportLists]-->2)<!--[endif]-->主子節(jié)點(diǎn):我們使用主子節(jié)點(diǎn)的方式來配置集群,系統(tǒng)數(shù)據(jù)的更改均在主節(jié)點(diǎn)上進(jìn)行,子節(jié)點(diǎn)只讀取主節(jié)點(diǎn)上的數(shù)據(jù);
<!--[if !supportLists]-->3)<!--[endif]-->Zookeeper:為了保證讀寫情況下,主子節(jié)點(diǎn)保證數(shù)據(jù)一致性,還需要zookeeper進(jìn)行通信,充當(dāng)文件鎖的功能。
負(fù)載均衡
在FineBI的集群環(huán)境中,我們可以使用任何支持負(fù)載均衡的服務(wù)器來完成輪發(fā)的任務(wù),并保證session粘滯。此處我們使用的是nginx反向代理,使用IP標(biāo)識(shí)輪發(fā),保證同一個(gè)用戶在同一個(gè)session。(在一個(gè)服務(wù)器一個(gè)節(jié)點(diǎn)的情況下,同一個(gè)IP就保證session粘滯)。
FS平臺(tái)集群
使用FS平臺(tái)集群插件,將FS平臺(tái)配置能夠滿足集群需求。在FS平臺(tái)集群中,F(xiàn)S平臺(tái)的所有操作都是發(fā)到主節(jié)點(diǎn)上來操作;子節(jié)點(diǎn)只是作計(jì)算服務(wù)器。
報(bào)表服務(wù)器
安裝釘釘管理插件后,打開報(bào)表管理平臺(tái),管理系統(tǒng)下會(huì)增加釘釘管理節(jié)點(diǎn),釘釘相關(guān)的配置管理都將會(huì)放在這個(gè)節(jié)點(diǎn)中去配置:
同時(shí),設(shè)置定時(shí)任務(wù)的最后一步輸出設(shè)置中,會(huì)增加推送釘釘消息:
釘釘企業(yè)應(yīng)用
管理員登錄釘釘企業(yè)號(hào),進(jìn)入微應(yīng)用設(shè)置,需要關(guān)注的信息有:
CorpID:是企業(yè)在釘釘中的標(biāo)識(shí),每個(gè)企業(yè)擁有一個(gè)唯一的CorpID;
CorpSecret:是企業(yè)每個(gè)應(yīng)用的憑證密鑰
登錄FineReport管理平臺(tái),點(diǎn)擊管理系統(tǒng)>釘釘管理節(jié)點(diǎn):將釘釘中的CorpID和CorpSecret分別填到釘釘企業(yè)號(hào)ID和管理組憑證密碼中,設(shè)置Token獲取路徑,可以自定義獲取的url,如果不寫則采用內(nèi)置的方式獲取,保存,如下圖:
釘釘提供的獲取token接口本身有缺陷:
1)釘釘提供的接口,使用corpid和secret獲取token,默認(rèn)不會(huì)緩存,但是釘釘提倡做token緩存,2小時(shí)內(nèi)可以重復(fù)使用,這樣減少對(duì)釘釘服務(wù)器的訪問,以免出現(xiàn)問題;
2)釘釘中集成多個(gè)應(yīng)用的話,如果多個(gè)應(yīng)用都會(huì)用到corpid和secret獲取token,如果某個(gè)應(yīng)用緩存了token,就會(huì)沖突
例如:應(yīng)用a,做了緩存,第一次訪問后獲取到token1,應(yīng)用b使用會(huì)重新取token2,此時(shí)應(yīng)用a還是用的token就無法訪問了。
針對(duì)這種情況,處理方式是所有應(yīng)用統(tǒng)一到一個(gè)地方去取token,此時(shí)需要設(shè)置自定義token的獲取地址
在釘釘插件中,釘釘管理>基本信息>設(shè)置Token獲取路徑,可以自定義獲取的url,如果不寫則采用內(nèi)置的方式獲取
Token獲取接口規(guī)則:返回json類型的數(shù)據(jù),{access_token:"xxxxx", jsapi_ticket:"xxxxx"}
釘釘管理后臺(tái)創(chuàng)建FineReport報(bào)表微應(yīng)用時(shí),例如http://www.finereporthelp.com:8181/app2/ReportServer?op=fs&corpid=$CORPID$,后面要加上參數(shù)&corpid=$CORPID$,這樣后臺(tái)會(huì)獲取到cropid,然后取到釘釘userid,做單點(diǎn)登錄;
- 釘釘用戶與報(bào)表用戶關(guān)聯(lián)
按照釘釘提供的方法,讀取釘釘通訊錄的成員,需要的字段有uesrid,name,department進(jìn)入FineReport報(bào)表管理平臺(tái)fs,點(diǎn)擊釘釘管理節(jié)點(diǎn),除了基本信息外,增加了釘釘成員管理,點(diǎn)擊效果如下:
表格中會(huì)自動(dòng)讀取釘釘企業(yè)號(hào)通訊錄中的所有成員,并且在每次打開該頁面時(shí)刷新為最新的;默認(rèn)釘釘成員與報(bào)表用戶相同,因?yàn)榇蟛糠智闆r下,釘釘成員名和報(bào)表用戶名是統(tǒng)一的;
如果您的釘釘成員名與報(bào)表用戶名是不一樣的,此時(shí),可以取消勾選釘釘成員與報(bào)表用戶相同設(shè)置,此時(shí)報(bào)表用戶名,可以將釘釘成員與報(bào)表用戶進(jìn)行關(guān)聯(lián),如下圖:
釘釘提供免登服務(wù),與微信類似,通過code可以獲取當(dāng)前取號(hào)的userid,獲取到userid后,通過關(guān)聯(lián)關(guān)系自動(dòng)登錄報(bào)表后臺(tái)
開發(fā)服務(wù)器可以主動(dòng)的發(fā)送消息給企業(yè)成員,比如使用FineReport定時(shí)器生成報(bào)表后,發(fā)送消息給相應(yīng)的人員進(jìn)行查看。進(jìn)入FineReport管理平臺(tái),添加定時(shí)任務(wù):
到輸出設(shè)置這步,比如我們將定時(shí)生成的結(jié)果掛在其他這個(gè)目錄下面,并且命名為釘釘文檔測(cè)試:
通知與存檔選擇推送釘釘消息,企業(yè)應(yīng)用(AgentID)需要根據(jù)釘釘管理里的進(jìn)行填寫,例如下設(shè)置,這樣定時(shí)任務(wù)結(jié)束后,這個(gè)釘釘成員可以收到消息
定時(shí)生成結(jié)果的文件名:對(duì)應(yīng)發(fā)送消息的標(biāo)題名
企業(yè)應(yīng)用AgentID:發(fā)消息至哪個(gè)應(yīng)用
釘釘用戶:發(fā)消息給哪些成員,下拉框中會(huì)自動(dòng)讀取釘釘通訊錄中的所有成員,多個(gè)成員之間用|分割,比如Jane|Saber
部門ID:發(fā)消息給某個(gè)部門的所有成員,該屬性與釘釘用戶是并的關(guān)系,不同部門之間也用|分割
消息內(nèi)容:定義消息的正文內(nèi)容
定時(shí)結(jié)果訪問連接:勾選的話會(huì)在消息正文最后加上定時(shí)生成的結(jié)果連接,點(diǎn)擊后就可以直接打開定時(shí)結(jié)果;不選的話則只發(fā)送純文本消息。
定時(shí)任務(wù)設(shè)置好后,比如任務(wù)每天都會(huì)執(zhí)行,每次執(zhí)行后就會(huì)推送消息給對(duì)應(yīng)的成員,效果如下:
點(diǎn)擊連接,就可以看到定時(shí)生成的結(jié)果。
當(dāng)報(bào)表中列出數(shù)據(jù)太多時(shí),想通過顯示按鈕隱藏明細(xì)數(shù)據(jù)只顯示統(tǒng)計(jì)數(shù)據(jù)。如下圖示例,那么該如何實(shí)現(xiàn)呢?本文以FineReport為例,來講述JS如何實(shí)現(xiàn)點(diǎn)擊參數(shù)面板按鈕顯示或隱藏?cái)?shù)據(jù)。

打開報(bào)表
在參數(shù)面板添加一個(gè)標(biāo)簽控件,控件名為lable,設(shè)置標(biāo)簽控件不可見,控件值為“顯示”。

在參數(shù)面板添加一個(gè)按鈕控件,控件名為button,控件值為“只顯示合計(jì)數(shù)據(jù)”,并添加點(diǎn)擊事件。

編輯點(diǎn)擊事件,添加下面的JavaScript代碼:

/*獲取隱藏的標(biāo)簽控件的值*/
var label= this.options.form.getWidgetByName("label").getValue();
/*判斷標(biāo)簽控件的值*/
if(label=='顯示')
{
/*當(dāng)標(biāo)簽控件的值為顯示時(shí),則改為隱藏,并修改按鈕名稱為顯示所有數(shù)據(jù)*/
this.options.form.getWidgetByName("label").setValue("隱藏");
this.options.form.getWidgetByName("button").setValue("顯示所有數(shù)據(jù)");
}
else
{
/*當(dāng)標(biāo)簽控件的值不為顯示時(shí),則改為顯示,并修改按鈕名稱為只顯示合計(jì)數(shù)據(jù)*/
this.options.form.getWidgetByName("label").setValue("顯示");
this.options.form.getWidgetByName("button").setValue("只顯示合計(jì)數(shù)據(jù)");
}
/*執(zhí)行查詢*/
_g().parameterCommit();
點(diǎn)擊參數(shù)面板空白處,將“點(diǎn)擊查詢前不顯示報(bào)表內(nèi)容”屬性的勾去掉。

回到報(bào)表設(shè)計(jì)界面,右鍵B3單元格,添加條件屬性,設(shè)置行高為0毫米,添加公式條件為$label = '隱藏'。

保存模板,點(diǎn)擊分頁預(yù)覽即可看到上圖的效果。
數(shù)據(jù)的重要性不言而喻,已經(jīng)被越來越多的公司接受、熟知和應(yīng)用。那么關(guān)乎數(shù)據(jù),到底在哪些方面可以促進(jìn)業(yè)務(wù)的騰飛?或者換種說法,業(yè)務(wù)對(duì)數(shù)據(jù)有哪些層次的需求?還有,數(shù)據(jù)對(duì)管理有哪些方面的貢獻(xiàn)?
依據(jù)我多年在數(shù)據(jù)分析崗位上的工作經(jīng)驗(yàn)和對(duì)業(yè)務(wù)的理解,業(yè)務(wù)對(duì)數(shù)據(jù)的需求可歸納為四個(gè)層次。
第一層:知其然
就是知道數(shù)據(jù)是多少,發(fā)生了什么情況。就如目前大多數(shù)企業(yè)都會(huì)有自己的數(shù)據(jù)庫,嚴(yán)格一點(diǎn)會(huì)有對(duì)應(yīng)的系統(tǒng)對(duì)應(yīng)的業(yè)務(wù)數(shù)據(jù)庫,數(shù)據(jù)收集的工作已經(jīng)完備了,無論是通過報(bào)表還是數(shù)據(jù)分析的手段,都可以掌握發(fā)生了什么,程度如何,建立數(shù)據(jù)監(jiān)控體系,做到“知其然”。也有一些企業(yè),在管理內(nèi)部數(shù)據(jù)的同時(shí),也在考慮外部數(shù)據(jù)的引進(jìn),向第三方機(jī)構(gòu)買數(shù)據(jù),觀察行業(yè)整體趨勢(shì)、政策環(huán)境的影響,其次了解競(jìng)爭(zhēng)對(duì)手的表現(xiàn)。這樣的數(shù)據(jù)工作是長期的也可是周期性的管理。長期的可盡力數(shù)據(jù)展現(xiàn)模板,形成一定的管理規(guī)范,固化下來。短期性的比如監(jiān)測(cè)某次營銷活動(dòng)的情況,可聯(lián)合IT部門或者數(shù)據(jù)分析師自己動(dòng)手,做到嚴(yán)格的“自省”。
1、數(shù)據(jù)是散的,看數(shù)據(jù)需要有框架。
數(shù)據(jù)展現(xiàn)很有講究,把數(shù)據(jù)放到業(yè)務(wù)框架,能體現(xiàn)業(yè)務(wù)分析,才能發(fā)揮整體價(jià)值。所謂有效的框架至少包含兩重作用:
(1)不同層級(jí)的人對(duì)數(shù)據(jù)的需求不同。比如市場(chǎng)銷售數(shù)據(jù),業(yè)務(wù)層需要指導(dǎo)自己每日指標(biāo)的完成情況和等級(jí)排名,需要提交每日每周每月的數(shù)據(jù)。領(lǐng)導(dǎo)層需要知道固定周期的業(yè)績(jī)完成率,各地區(qū)銷售額,營銷成本和組內(nèi)業(yè)績(jī)排名。管理層,CEO級(jí)別的可能需要知道每個(gè)業(yè)務(wù)部門的一些關(guān)鍵指標(biāo),比如總營收,市場(chǎng)增長率,重要的研發(fā)進(jìn)度等等。有效的框架能夠讓不同的人各取所需。

(2)好的框架能定位問題,指導(dǎo)決策制定。例如電商銷售額下降了30%,業(yè)務(wù)很可能出現(xiàn)了重大問題。我們需要分析問題原因,但如果只從客單價(jià)、交易單數(shù)、轉(zhuǎn)化率難以說明問題,好的業(yè)務(wù)分析框架能夠支持我們往下鉆,從品類、流量渠道等找到問題所在,找到對(duì)應(yīng)負(fù)責(zé)人。這也是我們通常所說的,看數(shù)據(jù)要落地。
2、數(shù)據(jù),有對(duì)比才能考量。
日銷售額100萬,你說多還是少呢?一個(gè)孤零零的數(shù)據(jù)是很難說明問題的。數(shù)據(jù)判斷要么有一個(gè)參考的指標(biāo),要么有能準(zhǔn)確判斷趨勢(shì)的指標(biāo)數(shù)據(jù),如增長率上升率。這樣一個(gè)基準(zhǔn)可以是歷史總結(jié)的同期數(shù)據(jù),也可以是行業(yè)的平均水平,也可以是預(yù)先設(shè)定的而目標(biāo),一切脫離目標(biāo)的數(shù)據(jù)分析都是“耍流氓”。

第二層:知其所以然
遇到問題尋找原因這是很順當(dāng)?shù)你暯印5叩竭@一步還不夠,解決問題才是真理。數(shù)據(jù)結(jié)合業(yè)務(wù),找到數(shù)據(jù)表象背后的真正原因,解決之。解決問題的過程就會(huì)涉及數(shù)據(jù)整理、加工,還會(huì)涉及數(shù)據(jù)分析模型的建立和工具,這在以往的篇幅已經(jīng)介紹的夠多的了。
在第二層里也有兩點(diǎn)分享:
1、數(shù)據(jù)是客觀的,但對(duì)數(shù)據(jù)的解讀則可能帶有很強(qiáng)的主觀意識(shí)。
數(shù)據(jù)本身是客觀的,但解讀數(shù)據(jù)的人都是有主觀能動(dòng)性的。這樣的問題往往是因?yàn)槎鄶?shù)人通多數(shù)據(jù)先對(duì)問題定性,而不是通過問題解決問題,這樣的事兒總有發(fā)生。
2、懂業(yè)務(wù)才能真正懂?dāng)?shù)據(jù)。
筆者認(rèn)為,數(shù)據(jù)分析業(yè)務(wù)占6分,方法占4分。不懂業(yè)務(wù)無法理解數(shù)據(jù)的真正含義也是有理可尋的,這里特地拿出來強(qiáng)調(diào)一下。
第三層:輔助業(yè)務(wù),發(fā)現(xiàn)機(jī)會(huì)
利用數(shù)據(jù)可以幫助業(yè)務(wù)發(fā)現(xiàn)機(jī)會(huì)。舉個(gè)電商的例子,通過用戶搜索的關(guān)鍵詞與實(shí)際成交的數(shù)據(jù)比較,發(fā)現(xiàn)有很多需求并沒有被很好地滿足,反映出需求旺盛,但供給不足。假如發(fā)現(xiàn)了這樣的細(xì)分市場(chǎng),公布出來給行業(yè)小二,公布出來給賣家,是不是可以幫助大家更好地去服務(wù)消費(fèi)者呢?這個(gè)例子就是現(xiàn)在我們?cè)谧龅?#8220;潛力細(xì)分市場(chǎng)發(fā)現(xiàn)”項(xiàng)目。
講這個(gè)案例不是想吹牛數(shù)據(jù)有多厲害,而是想告訴大家:數(shù)據(jù)就在那里,有些人熟視無睹,但有些人卻可以從中挖出“寶貝”來。差異就在于商業(yè)感覺,對(duì)數(shù)據(jù)的直覺。搜索數(shù)據(jù)和成交數(shù)據(jù)很多人都能夠看到,但并沒有人把這兩份數(shù)據(jù)聯(lián)系在一起,這背后體現(xiàn)出的就是商業(yè)的感覺。
第四層:建立數(shù)據(jù)化運(yùn)營體系
我理解的數(shù)據(jù)化運(yùn)營,包含了兩重意思:數(shù)據(jù)作為直接生產(chǎn)力和間接生產(chǎn)力。
1、數(shù)據(jù)作為直接生產(chǎn)力。
數(shù)據(jù)作為直接生產(chǎn)力是指數(shù)據(jù)能將價(jià)值直接投入到前線,作用于消費(fèi)者,時(shí)髦點(diǎn)講就是“數(shù)據(jù)變現(xiàn)”,這也是大家最為關(guān)注的。以前有沃爾瑪將啤酒和尿布兩個(gè)產(chǎn)品關(guān)聯(lián)擺放,引出了商品關(guān)聯(lián)度的概念。如今,又有餐飲企業(yè)利用數(shù)據(jù)統(tǒng)計(jì)分析,選型餐廳面積,優(yōu)化前后廳布置,使得單位面積營收最大。
2、數(shù)據(jù)作為間接生產(chǎn)力。
所謂間接生產(chǎn)力,是指數(shù)據(jù)價(jià)值不直接傳遞給消費(fèi)者或企業(yè),而是需要通過一系列的分析,制定策略傳遞給消費(fèi)者,即通常所說的決策支持。數(shù)據(jù)工作者通常做的是產(chǎn)出報(bào)表、分析報(bào)告等供各級(jí)業(yè)務(wù)決策者參考。我們可以稱之為決策支持1.0模式。然而隨著業(yè)務(wù)開拓和業(yè)務(wù)人員對(duì)數(shù)據(jù)重要性理解的增強(qiáng),對(duì)數(shù)據(jù)的需求會(huì)如雨后春筍般冒出來,顯然單單依賴人數(shù)不多的分析師是滿足不了的。授人以魚不如授人以漁,讓業(yè)務(wù)人員能夠獨(dú)立地進(jìn)行數(shù)據(jù)分析,而不依賴于技術(shù)人員是我認(rèn)為的決策支持2.0模式。
實(shí)現(xiàn)決策支持2.0模式有兩個(gè)關(guān)鍵:工具和能力。
如果讓他們和數(shù)據(jù)從業(yè)者一樣,掌握SQL,學(xué)會(huì)SPSS,SAS甚至R和Python,大可不必要。現(xiàn)在自助型的BI工具等低門檻、用戶體驗(yàn)良好的數(shù)據(jù)產(chǎn)品完全可以讓用戶快速上手,比如自助式BI工具FineBI,最佳的使用方式是讓IT人員準(zhǔn)備好數(shù)據(jù),按照權(quán)限,業(yè)務(wù)人員可以自己決定分析維度,將分析字段拖入表中,類似excel的數(shù)據(jù)透視表。這是實(shí)現(xiàn)決策支持2.0模式的基礎(chǔ)。

當(dāng)然,這里講的產(chǎn)品,不僅僅是操作功能集,還需要承載分析思路和實(shí)際案例。數(shù)據(jù)分析的門檻還是有的,深入的分析還是得往數(shù)據(jù)分析師方向走,這就會(huì)對(duì)大家提出一些其他的基本能力,比如統(tǒng)計(jì)學(xué)知識(shí),數(shù)學(xué)能力等等。但是內(nèi)心若有強(qiáng)大的意愿,有持之以恒的毅力,那都不叫事兒。
對(duì)于企業(yè)大多數(shù)員工來說,由于其工作位置是固定的,可以有多種方式進(jìn)行上班打卡簽到以保證該員工有按時(shí)正常來上班,但是對(duì)于經(jīng)常需要出差,去客戶現(xiàn)場(chǎng)的員工來說,就無法保證他們是否有去上班,所以希望能通過手機(jī)位置定位來保證員工有正常上班。
上述情況可以通過FineReport模板添加一個(gè)按鈕控件,點(diǎn)擊該按鈕的時(shí)候,獲取當(dāng)前地理位置,并將該位置信息復(fù)制給某個(gè)單元格,最后員工填報(bào)當(dāng)前模板即可。
實(shí)現(xiàn)如下圖所示效果,點(diǎn)擊地理位置按鈕獲取當(dāng)前位置與當(dāng)前時(shí)間,并顯示下下方對(duì)應(yīng)的單元格中:

模板制作
打開設(shè)計(jì)器,新建一張模板,按照如下圖所示樣式設(shè)計(jì)模板,其中E2單元格為按鈕控件,控件名稱為地理位置,C5為下拉框控件,E5為時(shí)間控件:
獲取當(dāng)前地理位置
獲取當(dāng)前地理位置有兩種方式,一個(gè)是點(diǎn)擊按鈕獲取地理位置,一個(gè)是直接打開模板的時(shí)候就獲取位置,示例中,想實(shí)現(xiàn)通過點(diǎn)擊按鈕獲取地理位置。
1)通過點(diǎn)擊按鈕獲取地理位置
打開按鈕的控件位置,為該控件添加一個(gè)點(diǎn)擊事件,如下圖:

相應(yīng)代碼如下:
FR.location(function(status, message){ //獲取地理位置
if(status=="success") {
//定位成功,message返回經(jīng)緯度值
FR.Msg.alert("當(dāng)前位置是" + message);
contentPane.setCellValue(2, 3, message);
} else {
//定位失敗,message返回對(duì)應(yīng)的錯(cuò)誤信息
FR.Msg.alert(message); //定位失敗
}
});
FineReport通過FR.location方法獲取當(dāng)前位置,如果status值為success,則表示獲取地理位置成功,否則定位失敗,如果定位成功,則將返回的地理位置信息賦值給C4單元格。
要注意的是該方法只在移動(dòng)端有用,如果在web點(diǎn)擊該按鈕事件獲取地理位置,則直接提示定位失敗。
2)加載結(jié)束后獲取當(dāng)前位置
如果想在模板加載結(jié)束之后就獲取到當(dāng)前地理位置,那么只需要將上述代碼添加到加載結(jié)束后事件中即可,打開模板,點(diǎn)擊模板>模板web屬性>填報(bào)頁面設(shè)置,添加一個(gè)加載結(jié)束事件,如下圖:

獲取當(dāng)前時(shí)間
在模板中還需要將當(dāng)前簽到時(shí)間也賦值過去,所以還需要在按鈕的點(diǎn)擊事件中獲取到當(dāng)前時(shí)間,即給E2單元格再添加一個(gè)點(diǎn)擊事件,并賦值給E4單元格,代碼如下:
var myDate = new Date();
var mytime=myDate.getFullYear()+"-"+myDate.getMonth()+1+"-"+myDate.getDate()+" "+myDate.getHours()+":"+myDate.getMinutes()+":"+myDate.getSeconds(); //獲取當(dāng)前時(shí)間
contentPane.setCellValue(4, 3, mytime);
按鈕點(diǎn)擊事件全部代碼如下:
FR.location(function(status, message){ //獲取地理位置
if(status=="success") {
//定位成功,message返回經(jīng)緯度值
FR.Msg.alert("當(dāng)前位置是" + message);
contentPane.setCellValue(2, 3, message);
var myDate = new Date();
var mytime=myDate.getFullYear()+"-"+myDate.getMonth()+1+"-"+myDate.getDate()+" "+myDate.getHours()+":"+myDate.getMinutes()+":"+myDate.getSeconds(); //獲取當(dāng)前時(shí)間
contentPane.setCellValue(4, 3, mytime);
} else {
//定位失敗,message返回對(duì)應(yīng)的錯(cuò)誤信息
FR.Msg.alert(message); //定位失敗
}
});
效果查看
將該模板添加到數(shù)據(jù)決策系統(tǒng)的節(jié)點(diǎn)樹上,其中模板的預(yù)覽方式為填報(bào),如下圖:

用移動(dòng)端登錄該系統(tǒng),訪問該張模板,點(diǎn)擊地理位置按鈕獲取當(dāng)前地理位置和當(dāng)前時(shí)間,如下圖:

FineReport中獲取的地理位置是經(jīng)緯度,如果需要確定其具體位置的話,還需要另外轉(zhuǎn)換。
在報(bào)表填報(bào)成功后,發(fā)送消息至APP會(huì)提示數(shù)據(jù)已更新。再次期間用戶需要有查看該模板的權(quán)限,如果沒有的話,則無法接受到提示信息。那么在FineReport移動(dòng)端中,如何手動(dòng)推送APP消息呢?
具體用法
在報(bào)表填報(bào)成功后事件中添加js,使用ajac發(fā)送消息請(qǐng)求
FR.ajax({
url: 'http://192.168.1.120:8033/WebReport/ReportServer?cmd=send_messages&op=fs_mobile_main',
type: 'POST',
data: {user:'sunlin', text:'填報(bào)成功,模板A有數(shù)據(jù)更新',url:'http://192.168.1.120:8033/WebReport/ReportServer?reportlet=app.cpt&op=write',title:'app'},
success: function(msg){
alert( "提示" + msg );
}
});
User:接受消息的人,可以是多個(gè),多個(gè)用戶之間用逗號(hào)分割,如“A,B”(必填)
Text:消息內(nèi)容(必填)
Url:打開地址(選填),在點(diǎn)擊消息之后進(jìn)入app打開的地址
Title:打開地址的頁面標(biāo)題(選填)
示例
效果一、推送純文本消息
填報(bào)的模板,增加填報(bào)成功事件,示例代碼如下:
FR.ajax({url: 'http://192.168.1.120:8033/WebReport/ReportServer?cmd=send_messages&op=fs_mobile_main',
type: 'POST', data: {user:'sunlin', text:'填報(bào)成功,模板A有數(shù)據(jù)更新'},success: function(msg){ alert( "提示" + msg ); } });


效果二、點(diǎn)擊消息后,進(jìn)入app,并且打開地址頁面
填報(bào)的模板,增加填報(bào)成功事件,示例代碼如下:
FR.ajax({
url: 'http://192.168.1.120:8033/WebReport/ReportServer?cmd=send_messages&op=fs_mobile_main',
type: 'POST',
data: {user:'sunlin', text:'填報(bào)成功,模板A有數(shù)據(jù)更新',url:'http://192.168.1.120:8033/WebReport/ReportServer?reportlet=app.cpt&op=write',title:'app'},
success: function(msg){
alert( "提示" + msg );
}
});


多臺(tái)服務(wù)器集群后,配置權(quán)限、數(shù)據(jù)連接、模板、定時(shí)調(diào)度等,只能每臺(tái)服務(wù)器一個(gè)個(gè)配置,不會(huì)自動(dòng)同步到所有服務(wù)器。
針對(duì)上述情況,在FineReport中提供新集群部署插件,將xml配置文件、finedb/logdb數(shù)據(jù)(定時(shí)任務(wù)、報(bào)表目錄管理、批量導(dǎo)入、統(tǒng)計(jì)信息)的修改都對(duì)主機(jī)生效。其他輔機(jī)的信息讀取也都從主機(jī)讀取,保證了數(shù)據(jù)同步。
實(shí)現(xiàn)了災(zāi)備,即主機(jī)當(dāng)即后,次主機(jī)會(huì)上位接替主機(jī)的工作,保證系統(tǒng)正常運(yùn)作。
同時(shí)還增加了集群災(zāi)備之文件同步,會(huì)將主機(jī)的finedb、xml、模板、jar包、插件等等備份到其他節(jié)點(diǎn)的應(yīng)用上。支持可以手動(dòng)同步和自動(dòng)同步。
插件介紹
設(shè)計(jì)器插件、服務(wù)器插件安裝好之后,新集群部署,有主機(jī)、次主機(jī)、輔機(jī)之分,配置文件都從主機(jī)讀取,輔機(jī)只能用作計(jì)算引擎分擔(dān)壓力,有點(diǎn)事當(dāng)改配置文件的時(shí)候,不需要每個(gè)節(jié)點(diǎn)都去修改,直接改主機(jī)即可。
分布式集群
分布式集群文件系統(tǒng):每臺(tái)計(jì)算機(jī)各自提供自己的存儲(chǔ)空間,并各自協(xié)調(diào)管理所有計(jì)算機(jī)節(jié)點(diǎn)中的文件。
這里測(cè)試修改主機(jī)的報(bào)表管理目錄樹平臺(tái)標(biāo)題,然后可以看到輔機(jī)會(huì)同步修改的配置。其中報(bào)表管理目錄樹存在finedb中,平臺(tái)樣式的平臺(tái)標(biāo)題存在fsconfig.xml中。
設(shè)置tomcat1、tomcat2、tomcat3集群,tomcat1為主機(jī),tomcat2為輔機(jī),tomcat3為次主機(jī),tomcat集群。
WebReport工程分別放在tomcat下的webapps文件夾里
集群配置完成之后,修改將配置包resource文件夾下的cluster.xml打開,如果沒有這個(gè)文件的話,就新建一個(gè),基本內(nèi)容如下:
PublicURL是集群默認(rèn)跳轉(zhuǎn)地址,比如集群時(shí)對(duì)外地址是自定義端口的, ip:8888/WebReport/ReportServer?op=fs我們并不能獲取到這個(gè)8888端口,因此這里需要填寫實(shí)際的ip:端口號(hào),如果這段省略不寫,默認(rèn)跳轉(zhuǎn)80端口。
ServiceName是為tomcat的名字。
IP是該臺(tái)服務(wù)器內(nèi)網(wǎng)中的IP,就是其它服務(wù)器能與之通信的IP。
Port是報(bào)表應(yīng)用的端口號(hào),假如是部署在tomcat下,那么就是tomcat的端口號(hào),默認(rèn)是8080。例如我們的內(nèi)置服務(wù)器是8079.
WebAppName是報(bào)表應(yīng)用的名稱,我們默認(rèn)的是WebReport。
詳細(xì)代碼如下:
<?xml version="1.0" encoding="UTF-8" ?>
<ClusterConfig useCluster="true">
<PublicURL>
ip:端口
</PublicURL>
<ClusterService isMain="true">
<ServiceName>tomcat1</ServiceName>
<ip>192.168.101.82</ip>
<port>6080</port>
<WebAppName>WebReport</WebAppName>
</ClusterService>
<ClusterService>
<ServiceName>tomcat3</ServiceName>
<ip>192.168.101.82</ip>
<port>8080</port>
<WebAppName>WebReport</WebAppName>
</ClusterService>
<ClusterService isVice="true">
<ServiceName>tomcat2</ServiceName>
<ip>192.168.101.82</ip>
<port>7080</port>
<WebAppName>WebReport</WebAppName>
</ClusterService>
</ClusterConfig>
啟動(dòng)工程,等3分鐘后,關(guān)閉主機(jī),刷新fs和訪問模板,此時(shí)是失敗的,再等待3分鐘,主次機(jī)上位,再次刷新fs和訪問模板,此時(shí)是成功的。
集群同步設(shè)置
點(diǎn)擊管理系統(tǒng)-集群同步,點(diǎn)擊設(shè)置,選擇需要同步的內(nèi)容:配置文件(resources目錄)、模板(reportlets目錄)、插件和jar(plugins和lib文件夾),點(diǎn)擊確定,然后可以選擇手動(dòng)同步,或者設(shè)置定時(shí)同步,點(diǎn)擊保存即可,如下圖:


共享式集群
共享式文件集群系統(tǒng):多臺(tái)計(jì)算機(jī)識(shí)別到同樣的存儲(chǔ)空間,并相互協(xié)調(diào)共同管理其上的文件,又被稱為共享文件系統(tǒng);
設(shè)置tomcat1和tomcat2集群,tomcat1為主機(jī),tomcat2為輔機(jī),tomcat集群。
Web項(xiàng)目部署在不同的服務(wù)器上,一般服務(wù)器都在同一局域網(wǎng),那么共享式文件集群該如何訪問呢?
這里通過共享局域網(wǎng)里某臺(tái)電腦上的工程文件夾,多個(gè)tomcat都從這個(gè)共享的工程文件夾里讀,如下圖:
文件夾共享后,局域網(wǎng)內(nèi)的服務(wù)器均可通過\\IP\文件夾訪問共享的工程目錄

tomcat1和tomcat2下,修改conf里server.xml文件,添加一個(gè)Context,指向項(xiàng)目的目錄
集群配置完成之后,修改將配置包resource文件夾下的cluster.xml打開,如果沒有cluster.xml,則新建一個(gè),基本內(nèi)容如下:

共享式的集群方式,因?yàn)楸旧砭褪侵赶蛲粋€(gè)文件夾的,不需要我們來做文件的同步,這里插件的作用是負(fù)載均衡。如果需要用到?jīng)Q策平臺(tái),需要將finebd遷移到其他數(shù)據(jù)庫,例如MySQL數(shù)據(jù)庫中。
最簡(jiǎn)單的擴(kuò)展列,擴(kuò)展行的求“最大,最小,平均”值的例子
設(shè)計(jì)圖

效果圖
相關(guān)函數(shù)
=MAX(B2:E2)
=MIN(B2:E2)
=AVERAGE(B2:E2)
這個(gè)是(滿足條件)的固定列,擴(kuò)展行的求和例子
設(shè)計(jì)圖
效果圖
相關(guān)函數(shù)
=SUM(B2{B2 > 1} + C2{C2 > 1} + D2{D2 > 1} + E2{E2 > 1})
=SUM(B2{B2 < 1} + C2{C2 < 1} + D2{D2 < 1} + E2{E2 < 1})
=SUM(B2[!0]{B2 > 1})
=SUM(B2[!0]{B2 < 1})
固定列擴(kuò)展行表求滿足條件的(行/列)個(gè)數(shù)方法!
設(shè)計(jì)圖
效果圖
相關(guān)函數(shù)
=if(B2 > 1, 1, 0) + if(C2 > 1, 1, 0) + if(D2 > 1, 1, 0) + if(E2 > 1, 1, 0)
=count(greparray(B2:E2, item < 1))
=COUNT(B2{B2 > 1})
=COUNT(B2{B2 < 1})
擴(kuò)展行擴(kuò)展列求最大,最小,平均值!
設(shè)計(jì)圖
效果圖
相關(guān)函數(shù)
=MAX(B2)
=MIN(B2)
=AVERAGE(B2)