陳宇 ,劉乾鵬,孫效玉,趙永嬌,張博
(1.東北大學, 遼寧 沈陽 110004;2.內蒙古平莊煤業(集團)有限責任公司, 內蒙古 赤峰市 024000;3.中國恩菲技術工程有限公司, 北京 100089)
報表是一種經過歸納、統計和整合的信息[1],礦山企業通常采用報表,輔以統計圖,形象直觀地展示產量、質量和設備等生產信息[2],報表已成為礦山企業管理的重要手段[3]。
平莊煤業有限公司的報表數據涉及到財務、人資、生產等8個職能部門和包括露天礦、井工礦在內的9座下屬礦山,經整理分析,將報表的類型按照其包含的單位種類分為以下2種。
(1)基礎報表。基礎報表是由集團公司下發指標,各礦相關人員填報相應數據而形成的報表,主要包含單個礦山的產量、效率、質量情況和材料消耗等基礎信息,以該企業的煤生8表為例,其樣式如圖1所示。將該報表表體區域的左側定義為統計指標目錄,隨著采礦方法、機械設備和材料種類等因素的變化,報表的指標也隨之變化,在該表中體現為采煤方法和煤層厚度、傾斜度統計指標發生變化。

圖1 煤生8表報表樣式
(2)綜合報表。綜合報表是所有基礎報表經過審核、整理和匯總后,按照礦山所屬組織進行分級排列而形成的集團公司的綜合統計報表,以原煤產量計劃表為例,其樣式如圖2所示。將該報表表體區域左側定義為報表結構目錄,該目錄包含集團公司下屬所有礦山,并將其按照所屬上級單位進行分級排列,隨著生產任務的變化和部門組織機構的變更,結構目錄也要隨之更新。

圖2 原煤產量計劃報表樣式
如果將報表設計為固定模式,即所有統計指標和結構目錄固定,這樣針對一張報表就需要一個專門的網頁,導致開發工作量增大,并且在報表目錄需求發生變更時,只能靠開發人員進行維護和重新設計。因此迫切需求一種能夠動態生成報表的方法,以滿足和適應不斷變化的報表需求,也就是開發者能夠為用戶提供可配置的報表,對報表進行個性化設置,生成用戶需要的形式[4]。
目前市面上流行的報表工具有 CrystalReport(水晶報表)、RDLC、帆軟等,基本都是基于控件開發,再綁定相應的數據集[5],在開發速度和交互性上應用效果良好,但是在報表需求發生變化時,需要開發人員重新設計和綁定數據集,無法滿足動態報表的需求[6]。報表目錄基本采用樹形結構來對數據進行整合[7],因此,有學者將所有可能出現的指標目錄全部羅列在一個樹形結構上,樹形結構的節點即為統計指標或單位名稱,通過勾選節點方式更新報表目錄,達到動態生成的效果[8]。但是該研究存在一些不足:無法對節點的名稱進行修改,即用戶無法更改報表的統計指標名稱;樹形分級結構固定,無法適應部門結構變更的情況。
本文針對礦山企業實際需求,結合企業綜合管理信息系統,在Web模式下,利用ASP.NET平臺,采用 JavaScript、HTML等技術開發動態報表,經平莊煤業實際應用證明,效果較為理想。
Web模式下,報表在前端的顯示是借助HTML語言中table元素,由th、td和tr等標簽構成報表的行和列,依次描述報表目錄。報表目錄的屬性信息存于數據庫中,在報表的樣式發生變化時,即報表目錄變更,需要從數據庫中提取相關數據信息,再使用HTML代碼重新進行描述。
借鑒 MVC開發模式[9],將動態報表的生成過程設計為由結構層、模板層和生成層組成的3層模型,如圖3所示。

圖3 動態報表生成模型
結構層:結構層主要用于整理和存儲用戶定義的報表指標目錄和報表結構目錄信息,該層提供可視化操作界面,由用戶定義報表指標和報表結構,并將定義后的報表目錄信息存儲于數據庫。
模板層:從數據庫中提取用戶定義的報表目錄信息,并綁定相應的參數,進而形成報表模板,為方便下一步生成報表,形成的模板為 DataTable數據類型,包含完整報表的所有信息。
生成層:生成層是利用HTML和CSS代碼對模板層進行修飾,并將其生成的報表顯示在前端頁面。
根據上述提到的報表的形式,制定 2種數據結構。
(1)基礎報表。基礎報表中的目錄為用戶制定的指標,指標可細分為次級指標,但不支持無限分級,根據相關報表統計工作的需要,將指標的最大分級設置為固定格式,以最多4級指標為例,數據表結構見表1。為方便用戶操作和更加直觀地展示指標的結構目錄,設計相關的交互頁面,以采煤方法/煤層厚度指標維護界面為例,如圖4所示。

圖4 采煤方法/煤層厚度指標維護頁面

表1 基礎報表結構
用戶能夠新增、修改和刪除指標。添加指標時在當前指標下方新增1條指標,一級指標不能為空;修改指標能夠更改當前指標的節點信息;刪除指標會在數據庫中刪除當前指標對應的數據行。
(2)綜合報表。綜合報表中的目錄為集團公司下屬各單位的樹形組織結構,各節點名稱對應著所屬部門和礦山名稱,該名稱由系統管理員指定,不允許統計人員隨意修改,但是可以更改節點的層級。
樹形結構中單個節點的層次可以由其父節點判斷,與其是否擁有子節點無關[10]。因此在數據庫中,將標志數據表唯一性的主鍵、父節點名稱、節點名稱和其它一些關聯屬性設計成關系型數據表,數據表結構見表2。

表2 樹形結構數據
由于不能隨意修改節點名稱,故在交互頁面上采用拖拽的方式進行編輯,如圖5所示。其中左側區域為參與生成目錄的區域,右側為未選中區域,在該頁面,用戶按住鼠標進行相關指標的拖拽即可完成綜合報表中報表結構目錄的制定。

圖5 單位名稱樹形目錄維護頁面
用戶在交互頁面上制定相應的報表目錄后,數據庫中存儲相應的結構屬性信息。后臺在頁面加載前,讀取數據庫并生成報表模板。根據交互頁面用戶操作的內容,主要有以下3個方面的模板更新。
2.2.1 基礎報表指標的更新
基礎報表指標在交互頁面顯示使用的是 table標簽,讀取數據庫中的信息時按照 ID排序生成DataTable數據表,循環該DataTable并添加HTML代碼和CSS樣式修飾,即可顯示圖2所示的效果。
點擊添加、修改或刪除時,利用JavaScript獲取當前數據行的焦點,再獲取該數據行其它信息,即一級指標、二級指標等,之后利用SQL語句即可獲取當前指標在數據庫中的存儲信息,使用INSERT、UODATE和DELETE即可實現當前模板的更新。
2.2.2 綜合報表的目錄更新
綜合報表的目錄在交互頁面顯示使用的是 ol標簽嵌套li標簽,實現樹形分級的效果。
利用SQL語句中的SELECT獲取數據庫中父節點信息和子節點信息,并生成相應的String類型的集合Parent和Children。某節點名稱只屬于Parent,則該節點為一級標題;某節點只屬于 Children,則該節點無子節點。生成一級標題之后,再使用SELECT語句,固定查詢條件Parent為當前一級標題名稱,即可查詢該一級標題下屬二級標題,根據部門分級限制,最多查詢到4級標題。將查詢到的標題信息添加HTML的ol標簽和li標簽進行修飾,顯示效果如圖5所示。
使用JS設置鼠標事件,按住鼠標時,li標簽設置為block屬性,隨鼠標進行移動,在鼠標抬起時,獲取移動之后的位置,根據當前位置插入該li標簽,再根據當前的整體結構更新數據庫中報表目錄信息,實現目錄的更新。
動態報表的生成首先需要根據結構表生成報表的目錄,綜合報表直接采用模板的結構即可。基礎報表先要將所有指標信息羅列出來,再去除其中的重復值,這是實現未分級的報表目錄,之后根據當前指標存儲在數據庫中的層級,設置相應的縮進,為了前端能夠直接識別,在指標前增加 字段。
生成報表的指標目錄后,還需要對該指標綁定數據,通過報表的名稱、指標名稱,在數據庫中找到所需的參數即可,最后生成的是一個包含層級、參數的DataTable,利用for循環遍歷該DataTable,增加tr、td和其它HTML標簽,生成String類型的字符串,在前端的指定位置使用InnerHtml函數插入該字符串,即可生成報表,效果如圖1和圖2所示。
本文提出了在 Web模式下實現動態報表的方法,該方法具有以下特點:
(1)用 3層結構模型處理動態報表的處理方式,具有較強的通用性和適應性,且可以很方便地對方法進行擴展,整個方法的核心模塊不需要進行任何修改,具有較好的擴展性和實用性;
(2)報表目錄管理界面直觀,用戶通過簡單的操作就可以快速實現各種報表目錄的制定,無需開發人員進行程序升級改造;
(3)報表的生成采用HTML代碼,較水晶報表等采用控件開發的方式,更容易對報表的內容進行擴充。