倉庫管理系統(tǒng)的VISAUL FOXPRO實現(xiàn) (下)
未知
4.4 設(shè)備還庫模塊的設(shè)計 在設(shè)備還庫模塊中將實現(xiàn)設(shè)備還庫數(shù)據(jù)的添加和修改庫存等功能,按照前面介紹的步驟設(shè)計設(shè)備還庫表。 設(shè)備還庫表所可能用到的控件的屬性如表所示:
(1)Form1控件的主要屬性:
select 現(xiàn)有庫存表 *先在該表單的數(shù)據(jù)環(huán)境中添加現(xiàn)有庫存表 getid=thisform.設(shè)備號1.text1.value set order to 設(shè)備號 seek getid *在現(xiàn)有庫存表中查找設(shè)備號等于getid的紀錄 if found() getnum=thisform.歸還數(shù)量1.text1.value update 現(xiàn)有庫存表; set 現(xiàn)有庫存=(現(xiàn)有庫存-getnum) where (設(shè)備號=getid) insert into 操作日志表(操作員,操作內(nèi)容,操作時間); values (thisform.歸還人1.text1.value,'設(shè)備還庫',date()) *如果庫存表中有該項設(shè)備,則更新庫存表,同時更新操作日志 else messagebox("出錯",1,"錯誤的設(shè)備號") *如果沒有該設(shè)備號則報告出錯信息 endif
保存后運行表單,可得到如圖所示的設(shè)備還庫表。
4.5 設(shè)備需求模塊的設(shè)計 在設(shè)備需求模塊中將實現(xiàn)設(shè)備需求數(shù)據(jù)的添加和保存日志等功能。首先通過Visual Foxpro的表單向?qū)伤璧脑O(shè)備需求表單,選擇部門需求表的所有可用字段,然后為保持程序風(fēng)格的一致,繼續(xù)采用表單的陰影式和圖片按鈕的風(fēng)格。在“步驟3-排序次序”時。選擇設(shè)備號的升序排列。最后單擊“完成”按鈕,把表單保存在“c:倉庫管理”目錄下,名為“設(shè)備需求.scx”。 通過表單向?qū)傻谋韱稳鐖D所示,我們可以調(diào)節(jié)控件的位置,修改表單中控件的屬性,最后結(jié)果所下圖所示:
在表單設(shè)計器中,雙擊“保存日志”命令按鈕。添加click事件代碼如下: insert into 操作日志表 (操作員,操作內(nèi)容,操作時間) values (username,'設(shè)備需求',date()) 雙擊回主界面命令按鈕,添加click事件代碼如下: thisform.release do form 倉庫管理 保存對表單所作的修改。 4.6 設(shè)備采購模塊的設(shè)計 在設(shè)備采購模塊中將實現(xiàn)設(shè)備采購數(shù)據(jù)的添加和保存日志等功能。 (1)由數(shù)據(jù)表生成表單 通過Visual Foxpro的表單向?qū)В稍O(shè)備采購計劃表單。在選擇數(shù)據(jù)庫和表時,選擇倉庫管理數(shù)據(jù)庫和設(shè)備采購計劃表。在選擇字段時,選擇所有可用字段,選擇陰影式和圖片按鈕作為設(shè)備采購計劃表的樣式。選擇計劃采購時間的升序排列作為設(shè)備采購計劃表的索引。 (2)為窗體修改和添加命令按鈕 添加2個命令按鈕“保存日志”和“回主界面”。設(shè)置表單中控件的屬性。下面的表列出了需要修改的控件的名稱以及屬性值。
(1)Form1控件的主要屬性:
(3)為按鈕添加click事件代碼: 在表單設(shè)計器中,雙擊保存日志命令按鈕。添加click事件代碼如下: insert into 操作日志表 (操作員,操作內(nèi)容,操作時間) values (username,"設(shè)備需求",date()) *把設(shè)備需求寫入操作日志表中 雙擊回主界面按鈕,添加click事件代碼如下: thisform.release *釋放本表單 do form 倉庫管理 *運行倉庫管理界面 保存對表單所作的修改,表單運行效果如圖所示:
4.7 顯示報表模塊的設(shè)計 在該模塊中,一共要顯示3個報表,分別提供庫存不足,庫存過多和操作日志等信息。
在如圖所示的空白表單中添加一個頁框控件,并按照下表設(shè)置頁框的屬性,同時在數(shù)據(jù)環(huán)境里添加現(xiàn)有庫存表和操作日志表。
操作日志表
設(shè)置表格控件的屬性,如表所示: grid1控件的主要屬性表:
2. 代碼設(shè)計 定義Pageframe1.Page1.grid1的init事件 運行“顯示報表”表單,界面所圖所示: local Custs1 select 設(shè)備號,最大庫存,現(xiàn)有庫存 from 現(xiàn)有庫存表 where (現(xiàn)有庫存>最大庫存) into cursor Custs1 thisform.頁框.庫存過多.庫存過多表.recordsource="Custs1" 定義Pageframe1.Page2.grid1的init事件 local Custs2 select 設(shè)備號,最小庫存,現(xiàn)有庫存 from 現(xiàn)有庫存表 where (現(xiàn)有庫存<最小庫存) into cursor Custs2 thisform.頁框.庫存不足.庫存不足表.recordsource="Custs2" 定義Pageframe1.Page3.grid1的init事件 local Custs3 select * from 操作日志表 into cursor Custs3 thisform.頁框.操作日志.操作日志表1.recordsource="Custs3" 運行“顯示報表”表單,界面如圖所示。
4.8 開發(fā)中的難點和解決技巧 Visual FoxPro6.0中的向?qū)Оū硐驅(qū)А?shù)據(jù)庫向?qū)А⒈韱蜗驅(qū)А⒉樵兿驅(qū)А蟊硐驅(qū)А?biāo)簽向?qū)А⑧]件合并向?qū)А?shù)據(jù)透視表向?qū)А?dǎo)入向?qū)А⑽臋n向?qū)А惭b向?qū)А⑸w向?qū)А?yīng)用程序向?qū)АEB發(fā)表向?qū)У取⑽覀兒侠響?yīng)用向?qū)Э梢栽诰幊讨刑岣咝省?為了快速開發(fā)高效的軟件,本設(shè)計中的多數(shù)表單的設(shè)計采用利用表單設(shè)計向?qū)桑缓笤谏傻谋韱蔚幕A(chǔ)上修改。 數(shù)據(jù)庫軟件用來管理數(shù)據(jù)的優(yōu)勢在于可以迅速從成千上萬的數(shù)據(jù)中找到我們需要的數(shù)據(jù),而查詢功能的設(shè)計也是數(shù)據(jù)庫應(yīng)用軟件設(shè)計過程中的重點也是難點。本設(shè)計過程中利用表單向?qū)姶蟮墓δ埽p松完成了數(shù)據(jù)的查詢功能。而且表單向?qū)傻牟樵児δ芊浅姶螅耆梢詽M足數(shù)據(jù)庫應(yīng)用軟件的需要。
第五章 系統(tǒng)的編譯和發(fā)行 5.1 設(shè)置主文件 用主圖標(biāo)標(biāo)記的文件是用戶在啟動.app或者.exe時被調(diào)用的文件。它可以是一個表單、菜單或者程序,建議使用程序作為主文件。 5.2 構(gòu)造主文件 如果主文件是一個程序,它將調(diào)用應(yīng)用程序框架中的各個功能組件,然后由這些組件調(diào)用應(yīng)用程序的其余部分。 如果要建立一個簡單的主程序,可以按下列步驟進行。 (1) 現(xiàn)設(shè)置應(yīng)用環(huán)境界面。 (2) 建立初始用戶界面。 (3) 建立事件循環(huán)。 (4) 恢復(fù)環(huán)境,退出應(yīng)用程序。 例如,可以建立下面的程序作為主程序:
為了避免無限循環(huán),必須在READ EVENTS命令之前安排CLEAR EVENTS命令。可以在主菜單或者主表單中添加一個“退出”項,該項發(fā)出CLEAR EVENTS命令。 5.3 在.app和.exe文件中包含和排除文件 如果在發(fā)布的應(yīng)用程序中不想再更改這些文件,可把它們放在項目中并設(shè)置為“包含”。那么這些文件變成只讀的,不能修改。如果想修改這些文件,把它們放在項目中并設(shè)置為“排除”,然后作為獨立文件隨著應(yīng)用程序一起發(fā)布。 在默認情況下,Visual FoxPro6.0在嵌放的過程中排除了數(shù)據(jù)庫、表格、成為.ff的c庫文件和.app文件。建議除了一些特定的表格,最好不要包含這類文件。數(shù)據(jù)庫和表格需要變化和添加,而如果編譯后包含自.exe或者是.app文件中,由于這二個文件被創(chuàng)建后都是靜態(tài)的,因此被包含的文件也是靜態(tài)的和只讀的。把數(shù)據(jù)庫和表格包含在這些文件中很明顯會帶來問題。 因為這些文件不能被包含在文件.exe或者是.app文件中,所以要在發(fā)布一個應(yīng)用程序之前為這些文件做好準(zhǔn)備。 如要排除可修改的文件,首先在項目管理器中,選擇可修改的文件,然后從“項目”菜單中選擇“排除”命令。在一個文件被排除后,則在文件的左方加入一個排除符號。 小結(jié) 一個完整的倉庫管理系統(tǒng)到此就制作完成了。在本例中詳細的講述了從創(chuàng)建數(shù)據(jù)庫到系統(tǒng)設(shè)計和各模塊的創(chuàng)建、面向?qū)ο蟮谋韱蔚脑O(shè)計、基本功能如查詢的實現(xiàn)、主程序的編寫。
致 謝
在本次畢業(yè)設(shè)計的過程中,我的導(dǎo)師和學(xué)院的老師們給了我很大的指導(dǎo)和幫助。不僅使我在規(guī)定的時間內(nèi)完成了系統(tǒng)的設(shè)計,同時還使我學(xué)到了很多有益的經(jīng)驗。在此, 我謹向他表示最衷心的感謝。 同時,學(xué)校給了我這次畢業(yè)設(shè)計的機會,使我得到了很好的鍛煉,在此,我也向?qū)W校的各位老師表示最誠摯的感謝。
附錄2:主要控件的源代碼清單: 1:主程序源代碼: SET TALK off set sysmenu off set cent on _screen.windowstate=2 _screen.icon="iconshappy.ico" _screen.maxbutton=0 _screen.minbutton=1 _screen.closable=.f. modify window screen noclose MODIFY WINDOW SCREEN TITLE " 倉庫管理信息系統(tǒng) " ZOOM WINDOW SCREEN MAX set default to data do form 登錄表單 read events clear close all return endif 2:登錄表單的確定按鈕控件的click源代碼:
locate for alltrim(用戶名)==alltrim(thisform.combo1.value) and alltrim(密碼)==alltrim(thisform.text1.value) if !eof() if alltrim(級別)=="管理員" public jb,username jb=1 username=alltrim(thisform.combo1.value) else public jb,username jb=0 username=alltrim(thisform.combo1.value) endif do menu.mpr thisform.release do form 倉庫管理 else #define missmatch_loc "用戶或口令錯,請重新登錄!" wait window missmatch_loc timeout 1 thisform.combo1.value='' thisform.text1.value='' thisform.text1.setfocus
numcount=numcount+1 if numcount=4 numcount=0 mess =messagebox("三次口令錯,將退出程序!",4+16+2,"退出") clear event release thisform endif endif 3:密碼修改表單的修改按鈕的click事件源代碼: if empty(thisform.text4.value) mess=messagebox("用戶名不能為空!",48,"警告") else if empty(thisform.text1.value) mess=messagebox("舊密碼不能為空!",48,"警告") else if empty(thisform.text2.value) mess=messagebox("新密碼不能為空!",48,"警告") else if empty(thisform.text3.value) mess=messagebox("重復(fù)密碼不能為空!",48,"警告") else if alltrim(thisform.text2.value)<>alltrim(thisform.text3.value) or len(alltrim(thisform.text2.value))<>len(alltrim(thisform.text3.value)) mess=messagebox("二次密碼不一致!",48,"警告") else locate for alltrim(用戶名)==alltrim(thisform.text4.value) and alltrim(密碼)==alltrim(thisform.text1.value) if eof() mess=messagebox("密碼錯誤,系統(tǒng)將取消你的修改權(quán)利!",48,"警告") thisform.release else repl 密碼 with alltrim(thisform.text3.value) mess=messagebox("密碼修改成功!",48,"信息") thisform.release endif 4:添加操作員表單的最首按鈕的click事件源代碼: go top thisform.grid1.setfocus thisform.grid1.refresh 5:添加操作員表單的上一個按鈕的click事件源代碼: skip-1 if bof() ?? chr(7) =messagebox("警告,這已經(jīng)是第一條記錄!",48,"信息窗口") go top endif thisform.grid1.setfocus thisform.grid1.refresh 6:添加操作員表單的下一個按鈕的click事件源代碼: skip if eof() ?? chr(7) =messagebox("警告,這已經(jīng)是最后一條記錄!",48,"信息窗口") go bottom endif thisform.grid1.setfocus thisform.grid1.refresh 7:添加操作員表單的最末按鈕的click事件源代碼: go bottom thisform.grid1.setfocus thisform.grid1.refresh 8:添加操作員表單的修改按鈕的click事件源代碼: if thisform.command5.caption='修改' thisform.text1.readonly=.f. thisform.text2.readonly=.f. thisform.text3.readonly=.f. thisform.combo1.readonly=.f. thisform.command5.caption='保存' thisform.command1.enabled=.f. thisform.command2.enabled=.f. thisform.command3.enabled=.f. thisform.command4.enabled=.f. thisform.command6.enabled=.f. thisform.command7.enabled=.f. thisform.command8.enabled=.f. else thisform.command5.caption='修改' thisform.text1.readonly=.t. thisform.text2.readonly=.t. thisform.text3.readonly=.t. thisform.combo1.readonly=.t. thisform.command1.enabled=.t. thisform.command2.enabled=.t. thisform.command3.enabled=.t. thisform.command4.enabled=.t. thisform.command6.enabled=.t. thisform.command7.enabled=.t. thisform.command8.enabled=.t. endif thisform.grid1.setfocus thisform.grid1.refresh 9:添加操作員表單的添加按鈕的click事件源代碼: if thisform.command6.caption='添加' thisform.text1.readonly=.f. thisform.text2.readonly=.f. thisform.text3.readonly=.f. thisform.combo1.readonly=.f. thisform.command6.caption='保存' thisform.command1.enabled=.f. thisform.command2.enabled=.f. thisform.command3.enabled=.f. thisform.command4.enabled=.f. thisform.command5.enabled=.f. thisform.command7.enabled=.f. thisform.command8.enabled=.f. appe blan else thisform.command6.caption='添加' thisform.text1.readonly=.t. thisform.text2.readonly=.t. thisform.text3.readonly=.t. thisform.combo1.readonly=.t. thisform.command1.enabled=.t. thisform.command2.enabled=.t. thisform.command3.enabled=.t. thisform.command4.enabled=.t. thisform.command5.enabled=.t. thisform.command7.enabled=.t. thisform.command8.enabled=.t. endif thisform.grid1.setfocus thisform.grid1.refresh 10:添加操作員表單的刪除按鈕的click事件源代碼: cMessageTitle='系統(tǒng)警告' cMessageText='確認要刪除嗎?' nDialogType=4+32 nanswer=messagebox(cMessageText,nDialogType,cMessageTitle) if nanswer=6 dele thisform.grid1.setfocus thisform.grid1.refresh endif 11:類baseform的picrecord的源代碼: IF TYPE("THIS.APP_MEDIATOR.BaseClass")#"C" RETURN ENDIF
IF THIS.APP_MEDIATOR.PickRecordToWorkOn() IF THIS.APP_MEDIATOR.lAdding AND !EMPTY(ALIAS()) THIS.REFRESH() * Check if we have blank record already from txtbtns IF GETFLDSTATE(1) #3 THIS.AddRecord() ENDIF ENDIF ENDIF 12:類baseform的queryunload的源代碼: IF TYPE("THIS.APP_MEDIATOR.BaseClass")#"C" IF !THIS.ResolveConflicts() NODEFAULT RETURN .F. ENDIF RETURN ENDIF IF DODEFAULT() IF NOT THIS.App_Mediator.QueryUnload() NODEFAULT RETURN .F. ENDIF ELSE NODEFAULT RETURN .F. ENDIF 13:類baseform的release的源代碼: IF !THIS.Queryunload() NODEFAULT RETURN .F. ENDIF 14:類baseform的resolveconflicts的源代碼: #DEFINE PROMPTTOSAVE_LOC "Data has been changed. Would you like to save changes?"
IF !THIS.lSaveBufferedData RETURN ENDIF
LOCAL nDECursors, aDECursors, cDataEnvRef, lPromptSave,lHadPrompt LOCAL lcAlias, lnFields, nPromptSave, i, loCurrentControl
* Flush current control IF TYPE("THIS.ActiveControl.baseclass")="C" AND; PEMSTATUS(THIS.ActiveControl,"value",5) AND; PEMSTATUS(THIS.ActiveControl,"controlsource",5) AND; !EMPTY(THIS.ActiveControl.controlsource) loCurrentControl = THIS.ActiveControl * Check if data actually changed IF !EVAL(loCurrentControl.controlsource)= loCurrentControl.Value loCurrentControl.Value = loCurrentControl.Value ENDIF loCurrentControl="" ENDIF
nDECursors = 0 cDataEnvRef = "" DIMENSION aDECursors[1] DO CASE CASE TYPE("THISFORM.DataEnvironment") = "O" nDECursors = AMEMBERS(aDECursors,THISFORM.DataEnvironment,2) cDataEnvRef = "THISFORM.DataEnvironment" CASE TYPE("THISFORMSET.DataEnvironment") = "O" nDECursors = AMEMBERS(aDECursors,THISFORMSET.DataEnvironment,2) cDataEnvRef = "THISFORMSET.DataEnvironment" CASE THIS.lUpdateAllBufferedTables nDECursors=AUSED(aDECursors) OTHERWISE IF !EMPTY(ALIAS()) aDECursors[1]=ALIAS() nDECursors=1 ENDIF ENDCASE
FOR i = 1 TO m.nDECursors IF EMPTY(m.cDataEnvRef) lcAlias = aDECursors[m.i] ELSE WITH EVAL(m.cDataEnvRef + "." + aDECursors[m.i]) IF ATC("CURSOR",.BaseClass)=0 &&skip relations LOOP ENDIF lcAlias = .ALIAS ENDWITH ENDIF
IF USED(lcAlias) AND CursorGetProp("sourcetype",lcAlias )=3 AND ; CursorGetProp("buffering",lcAlias )>1
IF !m.lHadPrompt IF CursorGetProp("buffering",lcAlias )>3 IF GETNEXTMODIFIED(0,lcAlias )=0 LOOP ENDIF ELSE lnFields = GETFLDSTATE(-1,lcAlias) IF REPLICATE("1",LEN(lnFields))=TRANS(lnFields) LOOP ENDIF ENDIF nPromptSave = MESSAGEBOX(PROMPTTOSAVE_LOC,35) IF nPromptSave=2 RETURN .F. ENDIF lPromptSave=(nPromptSave=6) lHadPrompt = .T. ENDIF IF m.lPromptSave TableUpdate(.T.,.T.,lcAlias) && update on exit ELSE TableRevert(.T.,lcAlias) && update on exit ENDIF ENDIF ENDFOR 15:類baseform的show的源代碼: LPARAMETERS nStyle LOCAL lcAppRef
IF TYPE("THIS.APP_MEDIATOR.BaseClass")#"C" OR !THIS.lShowFirstTime RETURN ENDIF
THIS.lShowFirstTime = .F. THIS.lSaveBufferedData = .F. THIS.PickRecord()