倉庫管理系統的VISAUL FOXPRO實現 (下)
未知
4.4 設備還庫模塊的設計 在設備還庫模塊中將實現設備還庫數據的添加和修改庫存等功能,按照前面介紹的步驟設計設備還庫表。 設備還庫表所可能用到的控件的屬性如表所示:
(1)Form1控件的主要屬性:
select 現有庫存表 *先在該表單的數據環境中添加現有庫存表 getid=thisform.設備號1.text1.value set order to 設備號 seek getid *在現有庫存表中查找設備號等于getid的紀錄 if found() getnum=thisform.歸還數量1.text1.value update 現有庫存表; set 現有庫存=(現有庫存-getnum) where (設備號=getid) insert into 操作日志表(操作員,操作內容,操作時間); values (thisform.歸還人1.text1.value,'設備還庫',date()) *如果庫存表中有該項設備,則更新庫存表,同時更新操作日志 else messagebox("出錯",1,"錯誤的設備號") *如果沒有該設備號則報告出錯信息 endif
保存后運行表單,可得到如圖所示的設備還庫表。
4.5 設備需求模塊的設計 在設備需求模塊中將實現設備需求數據的添加和保存日志等功能。首先通過Visual Foxpro的表單向導生成所需的設備需求表單,選擇部門需求表的所有可用字段,然后為保持程序風格的一致,繼續采用表單的陰影式和圖片按鈕的風格。在“步驟3-排序次序”時。選擇設備號的升序排列。最后單擊“完成”按鈕,把表單保存在“c:倉庫管理”目錄下,名為“設備需求.scx”。 通過表單向導生成的表單如圖所示,我們可以調節控件的位置,修改表單中控件的屬性,最后結果所下圖所示:
在表單設計器中,雙擊“保存日志”命令按鈕。添加click事件代碼如下: insert into 操作日志表 (操作員,操作內容,操作時間) values (username,'設備需求',date()) 雙擊回主界面命令按鈕,添加click事件代碼如下: thisform.release do form 倉庫管理 保存對表單所作的修改。 4.6 設備采購模塊的設計 在設備采購模塊中將實現設備采購數據的添加和保存日志等功能。 (1)由數據表生成表單 通過Visual Foxpro的表單向導,生成設備采購計劃表單。在選擇數據庫和表時,選擇倉庫管理數據庫和設備采購計劃表。在選擇字段時,選擇所有可用字段,選擇陰影式和圖片按鈕作為設備采購計劃表的樣式。選擇計劃采購時間的升序排列作為設備采購計劃表的索引。 (2)為窗體修改和添加命令按鈕 添加2個命令按鈕“保存日志”和“回主界面”。設置表單中控件的屬性。下面的表列出了需要修改的控件的名稱以及屬性值。
(1)Form1控件的主要屬性:
(3)為按鈕添加click事件代碼: 在表單設計器中,雙擊保存日志命令按鈕。添加click事件代碼如下: insert into 操作日志表 (操作員,操作內容,操作時間) values (username,"設備需求",date()) *把設備需求寫入操作日志表中 雙擊回主界面按鈕,添加click事件代碼如下: thisform.release *釋放本表單 do form 倉庫管理 *運行倉庫管理界面 保存對表單所作的修改,表單運行效果如圖所示:
4.7 顯示報表模塊的設計 在該模塊中,一共要顯示3個報表,分別提供庫存不足,庫存過多和操作日志等信息。
在如圖所示的空白表單中添加一個頁框控件,并按照下表設置頁框的屬性,同時在數據環境里添加現有庫存表和操作日志表。
操作日志表
設置表格控件的屬性,如表所示: grid1控件的主要屬性表:
2. 代碼設計 定義Pageframe1.Page1.grid1的init事件 運行“顯示報表”表單,界面所圖所示: local Custs1 select 設備號,最大庫存,現有庫存 from 現有庫存表 where (現有庫存>最大庫存) into cursor Custs1 thisform.頁框.庫存過多.庫存過多表.recordsource="Custs1" 定義Pageframe1.Page2.grid1的init事件 local Custs2 select 設備號,最小庫存,現有庫存 from 現有庫存表 where (現有庫存<最小庫存) into cursor Custs2 thisform.頁框.庫存不足.庫存不足表.recordsource="Custs2" 定義Pageframe1.Page3.grid1的init事件 local Custs3 select * from 操作日志表 into cursor Custs3 thisform.頁框.操作日志.操作日志表1.recordsource="Custs3" 運行“顯示報表”表單,界面如圖所示。
4.8 開發中的難點和解決技巧 Visual FoxPro6.0中的向導包括表向導、數據庫向導、表單向導、查詢向導、報表向導、標簽向導、郵件合并向導、數據透視表向導、導入向導、文檔向導、安裝向導、升遷向導、應用程序向導、WEB發表向導等、我們合理應用向導可以在編程中提高效率。 為了快速開發高效的軟件,本設計中的多數表單的設計采用利用表單設計向導生成,然后在生成的表單的基礎上修改。 數據庫軟件用來管理數據的優勢在于可以迅速從成千上萬的數據中找到我們需要的數據,而查詢功能的設計也是數據庫應用軟件設計過程中的重點也是難點。本設計過程中利用表單向導強大的功能,輕松完成了數據的查詢功能。而且表單向導生成的查詢功能非常強大,完全可以滿足數據庫應用軟件的需要。
第五章 系統的編譯和發行 5.1 設置主文件 用主圖標標記的文件是用戶在啟動.app或者.exe時被調用的文件。它可以是一個表單、菜單或者程序,建議使用程序作為主文件。 5.2 構造主文件 如果主文件是一個程序,它將調用應用程序框架中的各個功能組件,然后由這些組件調用應用程序的其余部分。 如果要建立一個簡單的主程序,可以按下列步驟進行。 (1) 現設置應用環境界面。 (2) 建立初始用戶界面。 (3) 建立事件循環。 (4) 恢復環境,退出應用程序。 例如,可以建立下面的程序作為主程序:
為了避免無限循環,必須在READ EVENTS命令之前安排CLEAR EVENTS命令。可以在主菜單或者主表單中添加一個“退出”項,該項發出CLEAR EVENTS命令。 5.3 在.app和.exe文件中包含和排除文件 如果在發布的應用程序中不想再更改這些文件,可把它們放在項目中并設置為“包含”。那么這些文件變成只讀的,不能修改。如果想修改這些文件,把它們放在項目中并設置為“排除”,然后作為獨立文件隨著應用程序一起發布。 在默認情況下,Visual FoxPro6.0在嵌放的過程中排除了數據庫、表格、成為.ff的c庫文件和.app文件。建議除了一些特定的表格,最好不要包含這類文件。數據庫和表格需要變化和添加,而如果編譯后包含自.exe或者是.app文件中,由于這二個文件被創建后都是靜態的,因此被包含的文件也是靜態的和只讀的。把數據庫和表格包含在這些文件中很明顯會帶來問題。 因為這些文件不能被包含在文件.exe或者是.app文件中,所以要在發布一個應用程序之前為這些文件做好準備。 如要排除可修改的文件,首先在項目管理器中,選擇可修改的文件,然后從“項目”菜單中選擇“排除”命令。在一個文件被排除后,則在文件的左方加入一個排除符號。 小結 一個完整的倉庫管理系統到此就制作完成了。在本例中詳細的講述了從創建數據庫到系統設計和各模塊的創建、面向對象的表單的設計、基本功能如查詢的實現、主程序的編寫。
致 謝
在本次畢業設計的過程中,我的導師和學院的老師們給了我很大的指導和幫助。不僅使我在規定的時間內完成了系統的設計,同時還使我學到了很多有益的經驗。在此, 我謹向他表示最衷心的感謝。 同時,學校給了我這次畢業設計的機會,使我得到了很好的鍛煉,在此,我也向學校的各位老師表示最誠摯的感謝。
附錄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 " 倉庫管理信息系統 " 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("重復密碼不能為空!",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("密碼錯誤,系統將取消你的修改權利!",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("警告,這已經是第一條記錄!",48,"信息窗口") go top endif thisform.grid1.setfocus thisform.grid1.refresh 6:添加操作員表單的下一個按鈕的click事件源代碼: skip if eof() ?? chr(7) =messagebox("警告,這已經是最后一條記錄!",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='系統警告' 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()