在通常的Server/Client方式MIS開發中,總是有沒完沒了的報表需要製作,調試報表花費的時間也是最多而且乏味,還常常不能滿足客戶的要求。要是能夠讓使用者自己調整報表的格式和內容,然後將它儲存下來,程式下次啟動時它自動調用儲存了的報表格式那有多好。本人通過如下方法最終實現了用的要求。
PB(PowerBuilder)有一種以PSR結尾的特殊的儲存報表的檔案格式(本文簡稱作PSR檔案)。根據資料視窗可以直接讀取PSR檔案產生報表的原理,程式通過產生PSR檔案,實現動態報表格式的儲存。
一、實現原理:
PB中的報表其實就相當於是資料視窗。
第一步,動態報表的實現。通過設定資料視窗對象(dataobject)中文本、列等的Resizeable和moveable屬性為1來實現對象位置的拖動控制,通過資料視窗的Modify函數實現對象值的更改(包括增加和刪除)。
第二步,報表格式的儲存。在一個應用當中,資料視窗對象的名稱總是唯一的,將每一個資料視窗對象轉化成PSR檔案存於資料庫表中。在視窗開啟時,程式先校正報表格式是否存在。如果存在,先將報表格式讀取出來放在一個臨時檔案當中,然後設定資料視窗(datawindow)的資料對象(dataobject)為這個報表檔案,然後提取資料;如果不存在,直接提取資料即可。
二、實現過程:
1、建立一個資料庫表用以儲存報表格式檔案。
| 表名:dyn_report |
| Dwobject |
Varchar2(20) |
資料視窗對象名稱 |
Primary key |
| Rptitle |
Varchar2(80) |
報表的標題名稱 |
|
| Memo |
Long raw |
報表格式 |
|
2、建立一個視窗w_temp。 定義執行個體變數如下:
string is_dwtype,is_dwobject //儲存報表中對象的類型及名稱
| 控制項名稱 |
控制項含義 |
| Dw_print |
資料視窗對象 |
| Cb_exit |
退出按鈕 |
| Cb_savereport |
報表格式儲存按鈕 |
3、在視窗的OPEN事件中加入如下代碼, 校正報表格式是否存在,如果存在讀取定義好的報表格式到資料視窗。
blob emp_pic long ll_handle string ls_dwobject,ls_reportfile,ls_path ls_dwobject = dw_print.dataobject //判斷是否存在該資料視窗的報表格式 select count(*) into:ll_count from dyn_report where dwobject =:ls_dwobject; if ll_count>0 then //讀取報表格式檔案到大文本變數 selectblob memo into:emp_pic from dyn_report where dwobject =:ls_dwobject; //建立psr臨時檔案到硬碟 ls_reportfile = '/temp7089.psr' ll_handle = FileOpen(is_reportfile,StreamMode!,write!,LockWrite!,Replace!) FileWrite(ll_handle,emp_pic) FileClose(ll_handle) dw_print.dataobject = ls_reportfile dw_print.settransobject(sqlca) else Dw_print.settransobject(sqlca) End if Dw_print.retrieve() 4、報表格式的儲存。通過Cb_savereport按鈕的clicked實現。 string ls_filename long ll_count blob Emp_id_pic ls_filename = "temp70201.psr" //儲存報表格式到硬碟臨時檔案 dw_print.saveas(ls_filename,PSReport! ,false) sqlca.autocommit = true select count(*) into :ll_count from dyn_report where dwobject =:is_dwobject; if ll_count =0 then insert into dyn_report(dwobject,rptitle) values(:is_dwobject,:ls_filename,:ls_path); end if //從硬碟臨時檔案讀取資料儲存到資料庫表中 emp_id_pic = of_readbmpfile(ls_filename)//該函數將二進位檔案內容讀到大文字物件中 //更新資料庫 UPDATEBLOB dyn_report SET memo = :Emp_id_pic where dwobject = :is_dwobject; sqlca.autocommit = false
|
5、動態報表的實現。通過資料視窗dw_print的clicked事件捕獲資料視窗中對象,並將對象名存放在實現變數is_dwobject中,為下一步修改報告作準備。
string ls_type,ls_dwoname //得到物件類型和名稱 ls_type = trim(upper(dwo.type)) ls_dwoname = trim(dwo.name) is_dwtype = ls_type choose case ls_type case "TEXT","CommandButton","GROUPBOX" is_dwobject = ls_dwoname //設定為可以拖動和改變大小,其它類同 this.modify(ls_dwoname+".Resizeable='"+"1'") this.modify(ls_dwoname+".moveable="+"1") case "LINE" //直線對象不能通過設定Resizeable和moveable屬性進行調整,必須通過其它路徑 is_dwobject = ls_dwoname case "RECTANGLE","ELLIPSE","GRAPH","BITMAP" is_dwobject = ls_dwoname this.modify(ls_dwoname+".Resizeable='"+"1'") this.modify(ls_dwoname+".moveable='"+"1'") case "COLUMN","COMPUTE" is_dwobject = ls_dwoname this.modify(ls_dwoname+".Resizeable='"+"1'") this.modify(ls_dwoname+".moveable='"+"1'") end choose |
然後再通過modify()函數可以實現基本的動態報表操作,這一類的文章較多,PB中也有大量的例子可直接使用,在此這不再累述。
6、在cb_exit按鈕的clicked()事件中加入:close(parent)。
7、在應用的open事件中加入: open(w_temp)。然後儲存並運行,大功告成啦!
8、本程式在PB7.0加Oracle8.05下調試通過。