2017年4月6日
#
組織樹報表中由id與父id來實現組織樹報表,若層級數較多時,對每個單元格設置過濾條件和形態會比較繁瑣,因此FineReport提供了一種特殊的數據集——樹數據集,只需要簡單的設置就能自動遞歸出層級,方便的實現如下圖組織樹報表:
圖一

圖二

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


2)根據數據長度構建樹
使用情形:原始表結構中所有ID都在一列中,且沒有父ID字段,但是ID是有規律的,每組的長度相同,且子級的前N位就是父級編號,添加樹數據集,如下圖:


預覽樹數據集,可看到已自動生成遞歸樹數據,FR_GEN_0為最高層,依次往下,如下:

縱向組織樹編輯
按照下圖所示將對應的數據列拖入到單元格中,并將A2單元格的左父格設置為A1,A3單元格的左父格設置為A2:

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

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

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

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

打開報表
在參數面板添加一個標簽控件,控件名為lable,設置標簽控件不可見,控件值為“顯示”。

在參數面板添加一個按鈕控件,控件名為button,控件值為“只顯示合計數據”,并添加點擊事件。

編輯點擊事件,添加下面的JavaScript代碼:

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

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

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

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

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

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

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

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

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

用移動端登錄該系統,訪問該張模板,點擊地理位置按鈕獲取當前地理位置和當前時間,如下圖:

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


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


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


共享式集群
共享式文件集群系統:多臺計算機識別到同樣的存儲空間,并相互協調共同管理其上的文件,又被稱為共享文件系統;
設置tomcat1和tomcat2集群,tomcat1為主機,tomcat2為輔機,tomcat集群。
Web項目部署在不同的服務器上,一般服務器都在同一局域網,那么共享式文件集群該如何訪問呢?
這里通過共享局域網里某臺電腦上的工程文件夾,多個tomcat都從這個共享的工程文件夾里讀,如下圖:
文件夾共享后,局域網內的服務器均可通過\\IP\文件夾訪問共享的工程目錄

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

共享式的集群方式,因為本身就是指向同一個文件夾的,不需要我們來做文件的同步,這里插件的作用是負載均衡。如果需要用到決策平臺,需要將finebd遷移到其他數據庫,例如MySQL數據庫中。
2016年12月28日
#
最簡單的擴展列,擴展行的求“最大,最小,平均”值的例子
設計圖

效果圖
相關函數
=MAX(B2:E2)
=MIN(B2:E2)
=AVERAGE(B2:E2)
這個是(滿足條件)的固定列,擴展行的求和例子
設計圖
效果圖
相關函數
=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})
固定列擴展行表求滿足條件的(行/列)個數方法!
設計圖
效果圖
相關函數
=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})
擴展行擴展列求最大,最小,平均值!
設計圖
效果圖
相關函數
=MAX(B2)
=MIN(B2)
=AVERAGE(B2)