摘要:提出了一種實現通用報表的新思想:將Excel文件轉化生成自定義模板文件,模板文件包括報表的靜態及動態兩部分內容,靜態部分主要封裝了表格結構信息,動態部分主要封裝了SQL語句以及與靜態部分相關聯信息,模板文件可以存入服務器數據庫中;客戶端通過通用打印組件完成報表的輸出。
關鍵詞:通用報表;自定義模板;Excel文件;通用打印組件
引言
目前,通用報表組件有兩種常用開發方法:①利用第三方組件技術。第三方組件如水晶報表或國內的CELL系統軟件等,這些系統均包含可視化的報表生成器,可以用它們方便地生成報表模板文件,打印輸出則由系統提供的標準打印組件通過解釋模板文件來完成。這種方法的優點是:編程量很少,一般來說只需要知道如何調用標準打印組件接口和這些接口所需要的參數就可以了。但是如果計算機配置較低的話,打印響應速度稍慢。另外報表系統軟件價格較高。②完全重新開發,開發內容包括報表生成器及報表打印組件等。這種方法的優點是系統響應速度快,容易擴充。但是功能很難超越水晶報表等成熟軟件,而且開發費時費力。
本文提出的實現通用報表的方法巧妙地繼承了上述兩種方法的優點,又彌補了它們的不足。所用開發平臺是Visual C++6.0,數據庫是sQL Server 2000。
1 實現通用報表需解決的問題
通用報表開發的基本思路幾乎都是一致的:即采用模板技術,先生成空模板文件,再用程序把數據填充到模板上。模板文件主要包含以下兩部分內容:
靜態部分對大多數企事業單位的報表來說,每種業務對應的報表形式是固定的,如行數、列數、文字說明部分、邊框特征等,這些都屬于靜態框架描述部分。應用程序通過這些描述可以畫出表格的結構。
動態部分描述如何把數據庫相應內容或其它數據動態地填充到空表格上。
相比較而言,構造報表中的表格以及文字說明是比較煩瑣的。對表格邊框來說,有的是粗線,有的是細線,有的有邊框,有的無邊框或部分有邊框,有的是合并單元格;對文字說明來說,字體名稱、大小、對齊方式等等也是有多種變化的。動態填充部分的描述相對容易一些,一般來說只要把單元格位置與相應的SQL語句關聯起來就可以了。
2 通用報表設計思想
通用報表程序一般包括兩部分:報表生成器程序、打印組件程序。報表生成器完成報表模板的靜態及動態設計,生成模板文件;打印組件程序負責解析該模板,完成打印輸出。
本文所述通用報表設計的關鍵步驟如下:①充分利用Office軟件中Excel強大的報表功能,首先在Excel中繪制出表格形狀,即靜態框架部分的內容;再通過加批注方式加入動態填充部分的內容,之后保存此Excel模板文件。②用程序通過一定的方式解析此Excel模板文件,轉換成自定義格式的新的模板文件。③把獲得的自定義格式模板文件數據以二進制方式導入數據庫中。也就是說,數據庫中有一個報表描述表,僅含兩個字段,第一個是報表名稱,作為關鍵字;第二個字段是對應的模板數據。④客戶端應用程序通過報表名稱,調用打印組件程序,獲取服務器端對應的報表描述表中的自定義模板數據,通過解析該數據,完成報表的輸出。
該方法的優點在于:一是充分利用了Excel制表功能,省去了靜態框架部分的設計;二是自定義模板的文件格式是自定義的,因此可以在程序中靈活控制。
3 通用報表關鍵技術實現方法
3.1 靜態部分的實現
3.1.1 實現原理
實現靜態部分的關鍵在于如何抽象表格的問題。筆者把表格抽象成單元格,屏蔽了表頭、表體、表尾的差異,把它們均當做一個個的單元格來處理。這種處理方式與Excel系統軟件的處理相似,因此可以借助Excel文件生成自定義格式的靜態框架描述部分的內容。繪制一個表格,前提條件是要獲得表1中各變量的數值。

根據表中1、2兩項,可以知道表格的具體大小及每個單元格的具體位置。每個單元格邊框、字體、對齊方式、范圍等屬性是由表中3、4兩項決定的,非合并單元格僅含一個單元格,合并單元格包含至少兩個單元格。畫表格就是畫一個個單元格的過程。
3.1.2 單元格屬性參數的獲得
從Excel文件中獲得表1中單元格屬性的各參數值,常用方法有以下兩種。
(1)利用Excel讀寫組件
此組件是由北京用友華表軟件公司研制的,包含了大量的解析Excel文件的接口函數,可以讀取Excel文件,方便地獲取各參數值。這種方法方便、快捷、穩定性也比較好。
(2)利用COM技術
系統文件Exce19.olb滿足COM編程規范,通過用#import Exce19.olb語句可以導出與Excel應用程序通訊的所有OLE自動化接口類及相關函數,從中可以找到表1中內容所需的接口函數。
3.2 動態部分的實現
3.2.1 實現原理
在Excel中單元格加批注,加入動態數據導入表格的全部描述,選擇的單元格一般是第一個單元格,之后,用程序把批注內容轉換為自定義格式的模板文件的動態填充部分。
應用程序獲得批注內容的方法仍采用3.1.2中描述的方法:利用Excel讀寫組件或利用COM技術。
之所以用Excel軟件中的批注功能,是因為它不會影響Excel模板文件的報表外觀,只有鼠標移到加批注的單元格時,批注的內容才會以單獨的窗口顯示出來。
3.2.2 實觀類型
從上文描述知道:當把報表抽象成單元格時,則畫報表就變得容易多了,因為靜態框架描述部分的內容結構是確定的,但動態填充部分仍要分成表頭、表體、表尾三部分分別處理:
(1)表頭、表體均對應一條SQL語句
表頭一般是非正規表格,動態描述部分應為:標志位+表頭單元格填充坐標組+對應SQL語句。表體是正規的二維表格,描述內容應為:標志位+單元格填充起始坐標+對應SQL語句,當然還應該把一頁填充的記錄數加進去。標志位的作用是判斷報表的類型,以下同。
(2)表體對應一條SQL語句
描述結構為:標志位+單元格填充起始坐標+對應SQL語句+每頁記錄數。
(3)空表格
描述結構為空,僅有—個標志位。
(4)表格數據是人為添入的
描述結構為:標志位+單元格填充位置坐標組+儲存填充單元格信息的字符串數組。
以上是四種常用的表內動態數據導入方法,可以根據需要加以擴充。
3.2.3 應用方法
一般來說,在Excel批注功能中輸入的是文本內容,最好采用標準的INI文件格式,以3.2.2表內數據導入方法(2)為例,相應的INI文件格式如表2所示。

可以利用VC系統提供的GetPdvateProfileString函數得到動態數據導入所需的各屬性數值,非常方便。但是由于起始時僅是在內存中獲得了自定義模板數據中動態填充部分的內容,所以還必須先在客戶端生成標準INI格式的臨時文件,獲取信息后,再把它刪除。
3.3 通用報表打印組件類層次
無論報表多么復雜,本文所述通用報表靜態部分都是基于于單元格的,因此在基類中完成的功能是:根據靜態部分的內容畫出空表格。而動態部分可以有多種類型,則對應著多個派生類,完成的功能是:從動態部分描述的內容中獲取動態填充的初始化信息,如填充起始位置,SQL語句等,從而完成填充的全過程。
4 結束語
本文對通用報表提出了一種新的設計思想,指出了自定義模板文件應該包括的內容,人們可以根據這些內容形成具體格式的模板文件。本設計利用Excel簡化了報表生成器的工作量,僅需編制通用打印組件即可。本文的設計是基于C/S架構的,利用自定義模板數據,開發B/S模式下的通用打印組件,是今后需要解決的問題。