用delphi編寫醫院的複雜報表 |
|
AB
高階會員 發表:166 回覆:262 積分:125 註冊:2003-08-21 發送簡訊給我 |
用delphi編寫醫院的複雜報表
江蘇省無錫市中醫醫院電腦房 袁波
http://www.powerba.com/develop/delphi/article/20000929013.htm ----------------------------------------------------------------------
我院的資訊管理系統採用delphi編程,由於各科要求不同,報表形式也多種多樣,編寫起來讓人頭痛。delphi運行在WINDOWS平臺下,列印同DOS下完全不同,而Quick Report即難以控制又佔用資源,對於一個稍複雜的、有特殊要求的報表,Quick Report無法實現。這裏介紹幾個在編程中遇到的比較典型的報表的實現方法。 1、哪個單位的財務科都有幾本厚厚的台帳,我院財務科提出列印藥庫的台帳,好脫掉手工帳,也算是辦公現代化了,要求合情合理,院長也說應當如此。看著財務科提供的紅綠相間的、統一印製的、行間距3毫米的台帳專用小卡片,我不由想到中國人節儉的美德。考慮到每個藥品至少列印一張,而且表格線一個都不能少,加上中醫院藥品有二千多種,所以這個報表必須用雷射印表機來列印(至於如何讓院長同意購買雷射印表機,則是另一回事,辦公自動化哪能沒有代價呢)。程式實現的思路基本上是把打印紙當做畫布在上面畫一個個小矩形,具體由以下幾個過程實現:(設Form名爲Ttzview)。 先在程式中定義二個類: titlerecord=record Currect:Trect; Atitle:string; end; detailrecord=record Arect:Trect; alignment:word; end; ---- 再建立以下四個過程; RectDraw(Acanvas:Tcanvas;s:string;R:Trect;frame:boolean;position:word); 這個過程就是畫矩形用的,frame決定是否畫線(這裏當然要畫啦!); printinitit(firsttop,firstleft:integer); 這個過程是初始化用的,就是定義各個小矩形在紙上的位置; printtitle(acanvas:Tcanvas); 這個過程是列印表頭的,因爲表頭的字總是要大一些; printdetail(acanvas:Tcanvas;Qtz:Tdataset;acount:integer;firstpage:integer); 這個過程才是列印具體內容的,一頁列印40行,不夠就換頁,總之一頁只能是一個藥品; printhj(acanvas:Tcanvas); 一看就知道,這個過程就是列印合計的啦! 只要建個Botton,順序調用printinitit,printtitle,printdetail,printhj這四個過程就行了, (調用格式:printtitle(printer.canvas);) 對了,Qtz就是查詢出來的台帳資料,如何生成的這裏就不談了。 此程式在delphi1,delphi3版本WIN3.2,WIN95,WIN97,WIN98平臺下運行通過,順便提供台帳資料庫的庫結構 2、非常複雜,無法取巧的報表 我院腫瘤科需要列印病人的病案,這可是特色專科現代化建設的一部分,衛生局要來檢查的,所以必須完成任務。每一個病案有100多個專案,若用Qreport,中間如果要加減一個專案(這事常有),幾十個專案的調整排列會使人昏倒。我一下子建立100多個臨時變數,在虛擬的畫布上畫啊畫,運行在我的PII233,64M記憶體的機子上倒是順順當當的,不過換到腫瘤科的486,8M記憶體的機子上時(大家別笑),系統堆疊馬上溢出,所以只好祭出指標大法(我的編程水平好象又有長進,竊喜),方法如下: 先建立titleprint類: titleprint=^Titlerecord; titlerecord=record Currect:Trect; Atitle:string[50]; end; 再建立過程printnow(Form的名稱叫 zlk,printdot就是印表機的點數,一般針打是180); procedure Tzlk.printnow(acanvas:Tcanvas); var i,x,y,pc_count:integer; myprint:array[0..200] of titleprint; begin firsttop:=round(int(0.5/2.54*printdot)); firstleft:=round(int(0.1/2.54*printdot)); rowheight:=round(int(0.7/2.54*printdot)); x:=0 firstleft;y:=round(int (1.3/2.54*printdot)) firsttop; pc_count:=0; inc(pc_count); new(myprint[pc_count]); myprint[pc_count]^.currect:=rect (x round(int(0.1/2.54*printdot)) firstleft,y, x round(int(3.0/2.54*printdot)) firstleft, y firsttop round(int(0.5/2.54*printdot))); myprint[pc_count]^.atitle:=Lname. caption DBname.text; ACanvas.MoveTo(myprint[pc_count]^. currect.left, myprint[pc_count]^.currect.top-round (rowheight/5)); {下面的四行還要重復100多次,基本差不多, 就不都寫出來賺稿費了} inc(pc_count); new(myprint[pc_count]); myprint[pc_count]^.currect:=scalerect( myprint[pc_count-1]^.currect,round(int (2.5/2.54*printdot)),0); myprint[pc_count]^.atitle:=Lxb.caption Cxb.text; ACanvas.LineTo(myprint[i]^.currect.right, myprint[i]^.currect.top-round(rowheight/5)); ....... {列印} printtitle(acanvas); {這個函數就不提供了,表頭不要也沒關係} for i:=1 to pc_count do begin RectDraw(Acanvas,myprint[i]^.atitle, myprint[i]^.currect,false, dt_left or dt_singleline or dt_vcenter); end; dispose(myprint[pc_count]); {別忘了把指標佔用的記憶體釋放} end; 最後建個Botton,加個是否真的列印的判斷,再調用這幾個函數就行了。 (調用格式:printtitle(printer.canvas);) 看了以上兩個例子,是不是覺得WINDOWS下的列印其實很簡單,就跟你手工畫表一樣,而且表格內容的位置是居中、居左、還是居右,全由列印內容的Alignment決定,列印格式由內容的Display Format決定,用不著自己去算,方便極了。發表人 - ab 於 2003/11/29 13:43:25 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |