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