經(jīng) 偉, 周國祥
(合肥工業(yè)大學計算機與信息學院,安徽合肥 230009)
隨著中小企業(yè)信息化的不斷深入,報表成為企業(yè)管理的基本工具。由于大型企業(yè)的業(yè)務多元化,較難建立滿足各方面需求的報表系統(tǒng);而中小企業(yè)制作的報表內(nèi)容單一,且樣式變化小,適合建立統(tǒng)一的報表系統(tǒng)進行管理。
當前流行的智能報表系統(tǒng)中,水晶報表作為國際性的商業(yè)智能軟件,能夠從任意數(shù)據(jù)源構造報表,并能以表格、圖表、分組等各種形式展現(xiàn),功能強大、彈性高。但由于我國報表的特點與國際上有所差異,水晶報表沒有考慮到這些特殊情況,也沒有充分了解報表制作人員的習慣等,在實際應用中無法滿足企業(yè)的需求[1-3]。國內(nèi)具有代表性的潤乾報表和用友華表,擁有優(yōu)秀的報表設計系統(tǒng),充分滿足了國內(nèi)企業(yè)對報表格式的需要,但功能單一,大部分是財務類報表,且很難制作格式靈活的報表,缺乏數(shù)據(jù)庫的數(shù)據(jù)分析功能[3-4]。
本文從B/S架構下智能報表系統(tǒng)的實際開發(fā)需求出發(fā),在充分研究國內(nèi)外企業(yè)報表系統(tǒng)基礎上,分析了國內(nèi)企業(yè)報表的內(nèi)在邏輯結構,提出一種報表定義和生成方法,并采用C#.net技術實現(xiàn)該智能報表系統(tǒng)。使用該系統(tǒng)提供的設計器,可以動態(tài)定義及修改報表內(nèi)在邏輯結構,生成器根據(jù)報表的定義信息實時生成報表,并以Excel報表文件形式存儲在服務器端。
一般報表在樣式上分成表頭、表體和表尾3個部分[1],如圖1所示。表頭包括標題欄和報表的統(tǒng)計時間區(qū)間;表體存放報表的所有內(nèi)容,由若干個報表分區(qū)組成,每個報表分區(qū)包含列行,每個列(行)包括名稱和數(shù)據(jù);表尾主要指腳注等。
由此發(fā)現(xiàn)表頭和表尾的內(nèi)容與格式比較固定,動態(tài)生成較為簡單。報體的基本數(shù)據(jù)單元是列(行),列(行)之間具有一定的邏輯關系,建立其完整的邏輯關系即可得到報表的表體數(shù)據(jù)。因而將定義報表的過程分成2個部分:① 報表列的屬性定義,每一個屬性列對應數(shù)據(jù)庫表中的任意一列;② 報表的顯示設計,按照設計好的展現(xiàn)形式,定義各個列的顯示位置和排列方式(水平或垂直)。
圖1 報表的結構
數(shù)據(jù)庫表設計如圖2所示,組合報表基本信息表中的一條記錄對應一個報表,通過關聯(lián)其他表構成一個報表的完整信息。
報表中直接與數(shù)據(jù)庫關聯(lián)的列按照相互之間的關系組成一個個基本表,每個基本表的列之間都是相關聯(lián)的,被存放在報表基本信息表和報表列信息表中,由于一張表可能存在多個基本表,它們與報表之間的關系信息在報表關聯(lián)表中定義。報表中的其他列作為組合列,由基本表列定義,數(shù)據(jù)存放在組合報表列信息表中。
報表列信息表、組合報表列信息表和報表列值信息表存放列的定義數(shù)據(jù),在研究大量報表列之后,本文將報表的列分成6種,即多選一列、累加列、計數(shù)列、數(shù)值分類計數(shù)列、多選一分類計數(shù)列和計算列。報表列信息表存放前5種列的信息,組合報表列信息表存放計算列的數(shù)據(jù)。報表列值信息表存放某些列的過濾值,指導報表生成器在生成過程中讀取數(shù)據(jù)庫中的合適數(shù)據(jù)。組合報表分段信息表、報表水平列信息表和報表垂直信息表存儲報表的排列格式。
圖2 報表定義的數(shù)據(jù)表關系
表格的生成過程就是設計一個邏輯完備的解析生成器,逐步分析報表的定義,讀取基本列對應的數(shù)據(jù)庫中的基本數(shù)據(jù),并按照各個列的計算規(guī)則統(tǒng)計得到組合數(shù)據(jù),最后按照顯示格式寫入Excel文件。整個過程分成基本表生成、組合表生成和報表數(shù)據(jù)的格式化顯示3個過程。如圖3所示,列屬性庫、列邏輯庫和報表顯示庫存放報表的定義數(shù)據(jù);組合、基本表數(shù)據(jù)結構,基本表數(shù)據(jù)集和組合表數(shù)據(jù)集是在報表的生成過程中臨時產(chǎn)生的數(shù)據(jù)。
圖3 報表的生成過程
一張報表中有若干個基本表,基本表的數(shù)據(jù)來源于數(shù)據(jù)庫,可以通過讀取數(shù)據(jù)庫直接得到。解析器首先讀取所有基本表的定義數(shù)據(jù),在內(nèi)存中構造基本表的數(shù)據(jù)結構;再順序分析每張基本表中的列定義。對于一張基本表中的各個列,在按照多選一列、累加列、計數(shù)列、數(shù)值分類計數(shù)列和多選一分類計數(shù)列排序后,讀取其在數(shù)據(jù)庫中對應列的數(shù)據(jù)。
每一列在解析的過程中,從當前基本表中讀取臨時數(shù)據(jù)集(已經(jīng)生成數(shù)據(jù)的所有列組成的數(shù)據(jù)集)中的一行數(shù)據(jù),作為查詢數(shù)據(jù)庫的條件。判斷這一列是否存在過濾值,若存在則不讀數(shù)據(jù)庫,直接將過濾值與臨時數(shù)據(jù)集做全連接,寫入臨時數(shù)據(jù)集;若不存在則構造查詢SQL語句,讀取數(shù)據(jù)。如果查詢結果為空,說明在當前的查詢條件下沒有值,刪除臨時數(shù)據(jù)集中的這行數(shù)據(jù);結果不為空則寫入臨時數(shù)據(jù)庫[5]。繼續(xù)讀取臨時數(shù)據(jù)集中的下一行數(shù)據(jù)作為查詢條件,循環(huán)生成當前列的數(shù)據(jù)。
在一個報表中僅有一個組合表,且表中的各列均為計算列。計算列一般關聯(lián)一個用戶自定義的數(shù)學表達式,即列的生成就是計算數(shù)學表達式的過程。表達式中的各個計算項來源于基本表的列,它可以是簡單表達式,也支持基本的統(tǒng)計計算,如份額、產(chǎn)出率等。
一般解析數(shù)學表達式分成數(shù)據(jù)替換和表達式計算2個部分,數(shù)據(jù)替換就是將表達式中ID號替換為基本列中的數(shù)據(jù)值。例如在數(shù)學表達式“([23]+[35])/[48]”中,“[23]”表示一個基本列,23為基本列的ID號。解析器分別定位表達式中各個ID號在臨時數(shù)據(jù)集中的位置,讀其數(shù)據(jù)并替換數(shù)學表達式中的ID號及兩邊的中括號,這樣就構造成一個數(shù)學表達式[6]。表達式的計算方式有2種:一般數(shù)學表達式通過使用棧數(shù)據(jù)結構,便能計算出結果;統(tǒng)計表達式則需要根據(jù)特殊符號的含義進行統(tǒng)計運算。因此,每一列的數(shù)據(jù)就是通過循環(huán)進行數(shù)據(jù)替換和表達式計算生成。
在對基本表和組合表進行解析和生成后,當前數(shù)據(jù)按照其邏輯結構順序存儲于內(nèi)存空間中,但是其結構十分復雜,數(shù)據(jù)冗余度大。直接寫入Excel文件將導致報表的可讀性差,因而在數(shù)據(jù)層設計一個報表顯示庫,使得報表數(shù)據(jù)可以根據(jù)設計格式化地顯示。
報表的格式化顯示生成過程是解析器讀取報表的格式定義及關聯(lián)的臨時數(shù)據(jù)集中的各列,依次將表體、表頭和腳注寫入Excel文件[7]。
表頭的生成需要確定整個報表的寬度,而整個報表的寬度由表體的內(nèi)容決定,因而需要首先將表體內(nèi)容寫入文件中,再讀取文件中表體使用的列數(shù),最后將表頭(標題和日期)寫入文件。腳注也是根據(jù)報表的寬度平均排列在表體底部。
表體一般由若干個報表分區(qū)組成,其報表分區(qū)有水平排列和垂直排列2種排列方式,表示臨時數(shù)據(jù)集中的各列數(shù)據(jù)在文件中排列方向。解析器按照報表分區(qū)的排序號,自上而下地將它們寫入文件。在確定排列方式后,順序讀取本分區(qū)的各列信息,寫入列名稱,同時讀取該列在臨時數(shù)據(jù)集中的列數(shù)據(jù),寫入文件。
本系統(tǒng)采用C#.NET集成開發(fā)環(huán)境實現(xiàn),系統(tǒng)的列屬性等3個報表結構庫和數(shù)據(jù)源均存儲在SQL SERVER 2005數(shù)據(jù)庫中。操作界面使用Ext.NET開源工具庫開發(fā),界面風格簡潔,便于操作,非技術人員在通過培訓后也可以自由地新建、修改報表的定義,并能夠快速地使用系統(tǒng)生成報表。
筆者設計了一個智能報表系統(tǒng)作為珠寶企業(yè)綜合管理系統(tǒng)下的子系統(tǒng),不僅實現(xiàn)了報表系統(tǒng)的基本定義與生成功能,也建立了報表的生成管理和權限管理。
如圖4所示,新增一個報表主要進行基本結構、邏輯及其顯示定義。
圖4 列的選擇及定義
其中基本結構定義用于設計基本列信息及其關系,主要有輸入基本信息、選擇基本列、選擇累加列和創(chuàng)建分類計數(shù)列。邏輯定義用于關聯(lián)各個基本結構,分成基本信息錄入、基本結構選擇、分區(qū)定義、列的選擇和過濾值設定5個部分。顯示定義用于控制在最終的報表文件中顯示或者隱藏數(shù)據(jù),包括垂直顯示定義和水平顯示定義。
報表生成管理就是用戶可以為部分屬性列提供過濾值,定制報表的生成數(shù)據(jù)。即在讀取或計算該列值時,若滿足用戶設定的過濾值則寫入報表中,反之則放棄。系統(tǒng)將過濾值的設定分成2個步驟。
(1)時間段的設定,限制讀取的數(shù)據(jù)必須在某個時間段范圍內(nèi)。
(2)報表部分列的過濾值設定,系統(tǒng)根據(jù)每個報表的列信息,選擇可設定過濾值的列,生成下拉列表,讓用戶選擇并輸入過濾值,添加過濾值即可[8-9]。導出報表流程,如圖5所示。
圖5 導出報表流程
報表權限用于控制上層系統(tǒng)的不同用戶組(部門)對本系統(tǒng)的訪問權限,本系統(tǒng)的主要權限有報表定義和生成2種權限。
由于企業(yè)的各個用戶組使用和管理的報表不同,在報表系統(tǒng)的默認狀態(tài),超級管理員用戶組只有定義權限,無生成權限,其他用戶組無定義和生成權限,每個用戶組的權限均由超級管理員用戶組中的用戶分配。
(1)報表定義權限的分配過程。選擇用戶組名稱,點擊選擇報表定義頁面,保存當前選擇即為該用戶組分配了定義權限。
(2)報表生成權限的分配過程。選擇用戶組名稱,復選報表名稱,點擊保存按鈕即分配了生成權限[10]。
本文提出并設計的智能報表系統(tǒng)已經(jīng)成功部署在一家珠寶企業(yè)中,能夠動態(tài)定義、修改報表的界面和邏輯結構,實時生成報表。用戶可以使用報表定義工具隨時增加新的報表,改變已有報表的顯示結構等,而不需要改變?nèi)魏未a,極大地減少報表系統(tǒng)的后續(xù)維護工作量。目前系統(tǒng)只能定義列表式和分組式報表等,無法定義圖表式報表,在今后的研究開發(fā)中需要進一步完善。
[1] 劉 瑤,孫玉芳.通用報表生成器的設計與實現(xiàn)[J].計算機科學,2000,27(2):73-75.
[2] 王光增,曹一家,戚 軍,等.電力企業(yè)通用報表綜合管理系統(tǒng)設計與實現(xiàn)[J].浙江大學學報:工學版,2009,43(11):2062-2066.
[3] 吳銀衛(wèi).通用報表生成技術研究與應用[D].北京:北京交通大學,2010.
[4] 潘福成,張士杰.基于XML的智能報表生成工具的研究[J].小型微型計算機系統(tǒng),2005,26(1):134-138.
[5] 李興勇,袁兆山,汪正海.復雜報表生成系統(tǒng)實現(xiàn)技術研究[J].計算機應用,2007,27(7):1821-1824.
[6] 王建軍,戴海金,朱方策.基于Excel Services報表系統(tǒng)的研究與實現(xiàn)[J].計算機工程與設計,2010,31(19):4305-4308.
[7] 張 利,吳傳勝,崔 雷,等.應用MVC模式構建Web信息系統(tǒng)框架研究[J].合肥工業(yè)大學學報:自然科學版,2007,30(7):829-832.
[8] 陳新林,張雙武.我國報表系統(tǒng)研究綜述[J].計算機系統(tǒng)應用,2007,16(12):113-117.
[9] 唐 敏,徐 瑋,李昭原.基于Web的報表工具的設計與實現(xiàn)[J].北京航空航天大學學報:自然科學版,2001,27(4):482-485.
[10] 陳傳波,黃 剛,劉清慧.一種基于ASP.NET的自定義報表的設計與實現(xiàn)[J].計算機工程與科學,2006,28(6):112-114.