在PB中利用DDE

在PB中利用DDE


華中科技大學電子與信息工程系 郭小兵


PowerBuilder(以下稱PB)是一種強有力的企業級數據庫應用系統開發工具,利用它可以方便地開發出數據庫系統的前臺應用軟件。但由於用PB所開發的報表具有一定的侷限性:報表的表頭、列寬等都不能在應用程序中由用戶來進行調整,所以若用戶報表的格式有所變動,則必須在原程序中對報表進行調整,這在很大程度上降低了軟件的靈活性。
Excel是Microsoft公司的表格處理軟件,由於其簡單易用,近年來在各單位的報表處理中得到廣泛的應用。那麼,在應用程序中是否可以調用Excel,讓用戶在用PB開發的應用程序中管理數據庫中的數據,而在用戶熟悉的Excel表格處理軟件中調整並打印報表呢?
答案是肯定的,本文介紹如何利用動態數據交換DDE(Dynamic Data Exchange)技術,在PB中把數據庫中的數據傳送到Excel應用程序中,以便由用戶在Excel中調整打印報表。
DDE用於在Windows平臺上的兩個正在運行的應用程序之間動態交換數據,它是一種在Windows操作系統中基於消息的協議。動態數據交換總是發生在兩個正在運行的程序之間,在這兩個應用程序之間相互發送和接收命令及數據。這兩個正在運行的程序分別稱爲客戶程序和服務器程序,客戶程序就是請求服務的程序,而提供服務的程序稱爲服務器程序。

實現方法

DDE應用程序在開始交換數據以前必須由客戶端發出初始請求,建立與服務器端的DDE連接(又稱爲通道或會話)。在建立連接後客戶端可以連續向服務器發送數據請求和命令請求。
在本文的應用程序中,我們用Excel做DDE應用服務器程序,在PB中進行DDE連接。
1.啓動DDE服務器應用程序
Excel.exe可以在Windows環境下單獨啓動,也可以在PB中用run函數啓動。
PB中run函數的語法格式爲:
run(string{,windowstate})
●string:字符型,要執行的程序文件名;
●windowstate:枚舉型,程序啓動後的窗口狀態,可以是最小化(minimized!)、最大化(maxized!)或原尺寸(normal!)。
在本文中,我們從客戶程序PB中啓動服務器應用程序Excel.exe,並假設Excel.exe的路徑爲:
c:/program files/Microsoft office/office/Excel .exe
在PB中啓動服務器應用程序的命令爲:
run(“c:/program files/Microsoft office/office/Excel.exe”, minimized!)
2.建立DDE連接
在客戶程序和服務器程序均啓動之後,就必須建立客戶程序和服務器程序之間的連接。在客戶程序PB中,可以使用OpenChannel函數建立這種連接,打開一個從客戶程序到服務器程序的通道。
PB中OpenChannel函數的格式爲:
OpenChannel(appname,topicname{,windowhandle }))
●appname:服務器程序的應用程序名;
●topicname:主題名,即客戶端要使用的實例,如Word文檔或Excel文檔;
●windowhandle:客戶端的窗口句柄,如果客戶端程序打開了多個窗口,需要指定其中一個作爲客戶端窗口。
建立DDE連接的方式分爲冷連接、暖連接和熱連接:
●冷連接:是指運行中的客戶程序和服務器程序進行直接的數據交換,不需要建立通道或連接,每次操作都要指定應用程序名和項目名;
●暖連接:是指用OpenChannel函數建立的連接,它可以利用OpenChannel函數返回的句柄對指定的應用進行操作;
●熱連接:是指用StartHotLink建立的連接。
無論是冷連接還是暖連接都無法在客戶端知道服務器端是否修改了數據,同樣,在服務器端也無法知道客戶端的數據修改情況。而用熱連接就可以使服務器端和客戶端彼此知道數據是否被修改。
在本文中,只是在PB中調用Excel報表,並向其中傳遞數據庫數據,並不需要知道Excel中對數據的修改處理情況,所以選用暖連接方式比較合適。
3.從客戶端向服務器端發送數據
在建立起客戶程序和服務器程序的連接之後,就可以在客戶程序PB中用SetRemote函數向服務器應用程序的報表中發送數據庫數據,以生成完整的報表。
根據DDE連接方式的不同,SetRemote函數有兩種格式分別用於冷連接和暖連接。
冷連接:
SetRemote(location,value,applname,topicname)
暖連接:
SetRemote(location,value,handle{,windowhandle})
我們可以利用該函數讀取數據庫中的數據並寫入到Excel的報表文件中以待打印。
4.通過客戶端執行服務器端命令
在客戶程序向服務器Excel發送完數據後,用戶可以在Excel中對報表做適當的調整,然後打印調整過的報表,並且關閉Excel。
在應用程序的客戶端中可以以遠程方式執行服務器應用程序(Excel.exe)中的命令,執行遠程命令的函數爲ExecRemote。該函數也是根據DDE連接方式的不同有冷連接和暖連接兩種格式。
冷連接:
ExecRemote ( command , appname, topicname)
暖連接:
ExecRemote (command ,handle,{ windowhandle })
利用這個命令可以在PB客戶端執行Excel程序的保存、打印和關閉等操作。
5.結束DDE連接
當完成DDE的數據處理後,使用CloseChannel函數關閉DDE連接。該函數的語法格式爲:
CloseChannel ( handle, { windowhandle } )

編程實例

假設有某學校的成績管理系統,學生的成績報表格式如圖1。

XX班級考試成績一覽表
2000年XX月

姓名 語文 數學 英語 物理 化學 總分 平均
               
               
               
全班平均              
首先在Excel中按照上述格式做好報表grade1.xls,並且把全班的平均成績和表頭之間空餘100行(假設班級的學生人數不超過100人)。然後在Excel中設計好全班平均成績、個人總成績和個人平均成績的計算公式,以自動計算所需要的數值。最後從數據庫中檢索出數據並填充在數據窗口控件dw_1中。
部分源代碼如下:
int I,handle,n
string excel,road_excel
//得到Excel的路徑
registryget(“HKEY_CURRENT_USER/SOFTWARE/Microsoft/Office/8.0/”+&“Excel/microsoft Excel ”,“GalleryPath”,Regstring!, road_excel)
Excel=road_excel+“/Excel.exe”
//啓動服務器程序,並打開報表grade1.xls
run(Excel+“ grade1.xls ”)
//建立到服務器程序的連接通道
handle=OpenChannel(“Excel”,“ grade1.xls ”)
n= dw_1.count()
//向Excel報表傳遞數據
for I= 1 to n
handle=OpenChannel(“Excel”,“ grade1.xls”)
SetRemote(“r”+string(I+1)+“c1”,string(dw_1.getitemnumber(I+1)),handle)
SetRemote(“r”+string(I+2)+“c1”,string(dw_1.getitemnumber(I+2)),handle)
SetRemote(“r”+string(I+3)+“c1”,string(dw_1.getitemnumber(I+3)),handle)
SetRemote(“r”+string(I+4)+“c1”,string(dw_1.getitemnumber(I+4)),handle)
SetRemote(“r”+string(I+5)+“c1”,string(dw_1.getitemnumber(I+5)),handle)
next
//在客戶程序中打印Excel報表
ExecRemote(“[print()]”,“Excel”,“grade1.xls”)
//關閉並不保存grade.xls
ExecRemote(“[close(false)]”,“Excel”,“grade1.xls”)
//退出Excel
ExecRemote(“[quit()]”,“Excel”,“system”)
//關閉連接通道,結束DDE會話
Close(handle)
注意:從客戶程序中啓動Excel服務器程序與建立連接和傳遞數據之間必須要有一定的時間間隔,最好把啓動Excel放在一個事件中,把建立連接和傳遞數據放在另一個事件中,避免由於在建立連接和傳遞數據時Excel還沒有完全啓動,造成建立連接和傳遞數據不正常。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章