Visual Basic 6.0 (VB6) 程式語言案例學習 (06. 中藥店管理系統)
Visual Basic 6.0 (VB6) 程式語言案例學習 (06. 中藥店管理系統)¶
6.1 問題¶
這是一家歷史悠久的中藥店,由於新一代接手,想採用電腦化管理,因此提出需求。我們有許多老顧客,常常跟我們訂藥,由於有些是長期的藥單,我們希望能夠很簡單的調出顧客資料和配藥的藥單,不要很麻煩去設定一堆東西,只要越簡單越好,中藥材有很多,要可以新增、刪除、修改藥材或者是藥單,藥材分類最好是用看的懂的方式來做,可以由筆劃或者是注音來選擇。顧客的資料都要能夠留下來,可以以後查詢。配藥的藥方要顯示適應症,可供參考。未來可能要做網路版本,讓分店也可以下載到最新藥單或顧客資料。
6.2 需求¶
表格 6‑1 「中藥店管理系統」系統目的分析表
版本:1.0 | 要做什麼 | 不要做什麼(不要做不代表不會做) |
---|---|---|
能做什麼 | (第一格:必要項目) | (第二格:次要項目) |
顧客資料管理要能很簡單的新增、刪除、修改、查詢。 | 保留網路版的功能,預留藥單或顧客資料下載更新。 | |
顧客的購買紀錄必須要能保留下來,方便以後查詢。 | 自動分析藥材的注音順序,藥材自動分類。 | |
藥材以注音的方式分類,要能夠新增、刪除、修改。 | 自動分析藥單的筆劃順序,藥單自動分類。 | |
藥單要能夠記錄所有的藥材,也要能夠新增、刪除、修改。 | 統計週、月、半年、年報表。 | |
藥單以筆劃的方式做分類。 | ||
購買清單要可以列印給客戶。 | ||
不能做什麼(不能做代表不需要做) | (第三格:不必要項目) | (第四格:不需要項目) |
建立多國語系的程式。 | 以資料探勘預測顧客購買需求。 | |
統計顧客購買藥材數量,以匯總成報表。 |
表格 6‑2 「中藥店管理系統」系統目標分析表
版本: | 重要 | 不重要 |
---|---|---|
優先 | (重) | (急) |
顧客資料管理要能很簡單的新增、刪除、修改、查詢。 | 藥材以注音的方式分類,要能夠新增、刪除、修改。 | |
顧客的購買紀錄必須要能保留下來,方便以後查詢。 | 藥單要能夠記錄所有的藥材,也要能夠新增、刪除、修改。 | |
藥單以筆劃的方式做分類。 | ||
不急迫 | (輕) | (緩) |
購買清單要可以列印給客戶。 | 建立多國語系的程式。 | |
保留網路版的功能,預留藥單或顧客資料下載更新。 |
表格 6‑3 「中藥店管理系統」系統規格表
規格項目 | 規格內容 | 備註 |
---|---|---|
藥名分類 | 以注音分類方式,可以新增、刪除、修改。 | … |
以拖曳的方式加入藥單。 | ||
方劑分類 | 以筆劃分類方式,可以新增、刪除、修改。 | … |
以拖曳的方式加入藥單。 | ||
點選方劑可以帶出適應症資料。 | ||
顧客資料 | 可以帶出顧客基本資料。 | … |
可以新增、刪除、修改顧客資料。 | ||
顧客清單 | 可以新增、刪除、修改顧客清單。 | … |
可以用電話、地址、姓名查詢。 | ||
當點選顧客清單項目時,可以關聯到顧客資料、購買紀錄、購買清單。 | ||
購買紀錄 | 可以依照顧客項目搜尋購買紀錄。 | … |
可以依照日期區間搜尋購買紀錄。 | ||
可以輸入備註內容。 | ||
購買清單 | 藥單可以新增、修改、刪除、列印。 | … |
並且能夠接受藥名和方劑拖曳過來的項目。 | ||
線上更新 | 預留線上更新按鈕。 | … |
多國語言 | 預留多國語言載入功能。 | … |
6.3 特色¶
以樹狀目錄管理藥材,並且可以自訂獨家藥方,透過拖曳的方式,替客戶打包藥材,並且有客戶管理及訂單管理。介面會隨著視窗大小自動調整,也就是說可以隨時調整視窗大小,而視窗內的控制項也會依照比例去做縮放的動作。
6.4 使用工具¶
語言 | 軟體 |
---|---|
MS Visual Basic 6.0 | MS Visual Basic 6.0、MS Access |
6.5 系統架構¶
筆者在分析的時候,就在思考一個問題,要如何將操作變得簡單易懂呢?最後採取的方式就是拖曳,這個由來已久的操作模式,是廣大使用者最熟悉的方式,因此筆者將想法融入藥材管理程式中。無論是藥材或者是方劑,我們都必須讓使用者能夠以拖曳的方式,加項目加入藥單中,這是最熟悉的操作模式。因為在Windows的檔案總管管理檔案的方式,幾乎是使用拖曳來完成的。其他資料庫管理的部分,就只是基本的資料庫管理工作而已,並不太難。
6.6 程式實作¶
Step 1:如圖 6-1 所示,我們在左邊安排藥名樹狀清單,而右邊安排方劑樹狀清單,中間則是顧客資料項目,一開始我們以英文命名,這是為了製作多國語系而設計的,也許將來可能有簡體中文版或是其他語文版本。而最底下則是顯示適應症的文字框。
圖 6‑1
Step 2:請參考以下程式碼,由於程式碼很多,因此只列出重點部分,以及副程式或函式的功用說明。原始程式碼放置在教材檔案中,請讀者參考。
'要求變數宣告才能使用 Option Explicit '記錄表單的寬度 Public frmMM_PrevResizeX As Long '記錄表單的高度 Public frmMM_PrevResizeY As Long '客戶資料模式 Public strCICD_Mode As String '採購清單模式 Public strCISL_Mode As String '採購紀錄模式 Public strCIBH_Mode As String '藥名模式 Public strItem_Mode As String '方劑模式 Public strClass_Mode As String '程式初始 Private Sub Form_Initialize() ‘... End Sub
'視窗起始載入 Private Sub Form_Load() '設定日期範圍 dtpBH_SD.Value = Date dtpBH_ED.Value = Date '載入藥名框顯示模式 Call load_fraItem_Mode("") '載入藥名下拉式選單 Call load_cboItem_Class '載入方劑框顯示模式 Call load_fraClass_Mode("") '載入方劑下拉式選單 Call load_cboClass_Class '載入語言 Call load_Language(strDefineLanguage) '載入客戶 Call load_lvwCAB '載入預設客戶的個人資料 Call load_CD '載入預設客戶的採購紀錄 Call load_BH '載入預設客戶的採購清單 Call load_SL '載入客戶詳細資料框,設定樣式 Call load_fraCICD("") '設定頁籤簽換至採購清單 tspCI.Tabs(4).Selected = True Me.Show '載入藥名 Call load_fraItem '載入方名 Call load_fraClass '呼叫調整大小函式 frmMM_ResizeAll frmMM Me.Show End Sub
'釋放程式事件副程式 Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer) End End Sub ‘結束程式事件副程式 Private Sub Form_Terminate() End End Sub '視窗大小更動時 Private Sub Form_Resize() '當表單最小化時不處理 If frmMM.WindowState = 1 Then Exit Sub End If '限制了表單的最小高度及寬度 If frmMM.Width < 12120 Then frmMM.Width = 12120 End If If frmMM.Height < 9405 Then frmMM.Height = 9405 End If '呼叫調整大小函式 frmMM_ResizeAll frmMM End Sub
'調整視窗大小 Public Function frmMM_ResizeAll(tmpForm As Form) '錯誤處理 '當控制項無法改變大小或長寬時,就略過不處理 On Error Resume Next '宣告區 Dim tmpControl As Control '紀錄表單原來大小 If frmMM_PrevResizeX = 0 Then '如果 frmMM_PrevResizeX = 0 表示第一次執行這個 Function '就先給定 frmMM_PrevResizeX 及 frmMM_PrevResizeY 的初值, '記錄表單原來的大小,然後結束這個 Function frmMM_PrevResizeX = tmpForm.ScaleWidth frmMM_PrevResizeY = tmpForm.ScaleHeight Exit Function End If '設定表單修改大小 For Each tmpControl In tmpForm '逐一處理這個表單中的所有控制項 If TypeOf tmpControl Is Line Then '檢查控制項的物件類別, 如果是 Line , 就改變 X1, X2, Y1, Y2 的值 tmpControl.X1 = tmpControl.X1 / frmMM_PrevResizeX * tmpForm.ScaleWidth tmpControl.X2 = tmpControl.X2 / frmMM_PrevResizeX * tmpForm.ScaleWidth tmpControl.Y1 = tmpControl.Y1 / frmMM_PrevResizeY * tmpForm.ScaleHeight tmpControl.Y2 = tmpControl.Y2 / frmMM_PrevResizeY * tmpForm.ScaleHeight '上面這四行會自動根據控制項和表單的相對比例 '自動調整控制項的位置及大小 ElseIf TypeOf tmpControl Is ComboBox Then '如果是其他的物件類別, 則改變控制項的 left, top, Width, and height tmpControl.Left = tmpControl.Left / frmMM_PrevResizeX * tmpForm.ScaleWidth tmpControl.Top = tmpControl.Top / frmMM_PrevResizeY * tmpForm.ScaleHeight tmpControl.Width = tmpControl.Width / frmMM_PrevResizeX * tmpForm.ScaleWidth tmpControl.Height = tmpControl.Height / frmMM_PrevResizeY * tmpForm.ScaleHeight Else tmpControl.Move (tmpControl.Left / frmMM_PrevResizeX * tmpForm.ScaleWidth), _ (tmpControl.Top / frmMM_PrevResizeY * tmpForm.ScaleHeight), _ (tmpControl.Width / frmMM_PrevResizeX * tmpForm.ScaleWidth), _ (tmpControl.Height / frmMM_PrevResizeY * tmpForm.ScaleHeight) '上面這四行會自動根據控制項和表單的相對比例 '自動調整控制項的位置及大小 End If Next tmpControl '紀錄修改後大小 '重新給定 frmMM_PrevResizeX 及 frmMM_PrevResizeY 的值 frmMM_PrevResizeX = tmpForm.ScaleWidth frmMM_PrevResizeY = tmpForm.ScaleHeight End Function
'載入顯示語系 Private Sub load_Language(Optional strSS As String) ‘... End Sub '載入藥名 Private Sub load_fraItem() ‘... End Sub '載入方名 Private Sub load_fraClass() ‘... End Sub '點選採購紀錄 Private Sub lvwBH_ItemClick(ByVal Item As MSComctlLib.ListItem) '載入預設客戶的採購清單 Call load_SL '載入備註 txtBH_Note.Text = Trim(Item.SubItems(1) & "") End Sub '點選客戶 Private Sub lvwCAB_ItemClick(ByVal Item As MSComctlLib.ListItem) '載入預設客戶的個人資料 Call load_CD '載入預設客戶的採購紀錄 Call load_BH '載入預設客戶的採購清單 Call load_SL End Sub '刪除採購單上的項目 Private Sub lvwSL_KeyDown(KeyCode As Integer, Shift As Integer) ‘... End Sub '設定採購單上項目的數量 Private Sub lvwSL_KeyPress(KeyAscii As Integer) ‘... End Sub '工具按鈕 Private Sub tbrMM_ButtonClick(ByVal Button As MSComctlLib.Button) ‘... End Sub '工具按鈕 Private Sub tbrMM_ButtonMenuClick(ByVal ButtonMenu As MSComctlLib.ButtonMenu) ‘... End Sub '切換頁籤 Private Sub tspCI_Click() ‘... End Sub ' 載入客戶資料 Private Sub load_lvwCAB() ‘... End Sub '點選方劑帶出適應症 Private Sub tvwClass_NodeClick(ByVal Node As MSComctlLib.Node) ‘... End Sub '禁止地址輸入 Private Sub txtCAddr_KeyDown(KeyCode As Integer, Shift As Integer) KeyCode = 0 End Sub '禁止地址輸入 Private Sub txtCAddr_KeyPress(KeyAscii As Integer) KeyAscii = 0 End Sub '客戶資料操作模式 Private Sub load_fraCICD(strMode As String) ‘... End Sub '按下新增客戶 Private Sub cmdCD_Add_Click() ‘... End Sub '按下修改客戶 Private Sub cmdCD_Edit_Click() ‘... End Sub '按下刪除客戶 Private Sub cmdCD_Delete_Click() ‘... End Sub '在客戶模式按下確定 Private Sub cmdCD_Yes_Click() ‘... End Sub '在客戶模式按下取消 Private Sub cmdCD_No_Click() ‘... End Sub '新增客戶 Private Function fCICD_Add() As String ‘... End Function '修改客戶 Private Function fCICD_Edit() As String ‘... End Function '刪除客戶 Private Function fCICD_Delete() As String ‘... End Function '點選藥名樹狀目錄中的藥名 Private Sub tvwItem_NodeClick(ByVal Node As MSComctlLib.Node) ‘... End Sub '由藥名樹狀目錄中拖曳至採購清單 Private Sub tvwItem_OLEStartDrag(Data As MSComctlLib.DataObject, AllowedEffects As Long) Data.SetData tvwItem.SelectedItem.Key, 1 End Sub '由方劑樹狀目錄中拖曳至採購清單 Private Sub tvwClass_OLEStartDrag(Data As MSComctlLib.DataObject, AllowedEffects As Long) Data.SetData tvwClass.SelectedItem.Key, 1 End Sub '採購單載入拖曳的藥名 Private Sub lvwSL_OLEDragDrop(Data As MSComctlLib.DataObject, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single) ‘... End Sub '採購資料操作模式 Private Sub load_fraCISL(strMode As String) ‘... End Sub '按下新增採購 Private Sub cmdSL_Add_Click() strCISL_Mode = "add" Call load_fraCISL(strCISL_Mode) End Sub '按下修改採購 Private Sub cmdSL_Edit_Click() strCISL_Mode = "edit" Call load_fraCISL(strCISL_Mode) End Sub '按下刪除採購 Private Sub cmdSL_Delete_Click() strCISL_Mode = "delete" Call load_fraCISL(strCISL_Mode) End Sub '按下列印採購 Private Sub cmdSL_Print_Click() frmPM.Show 1 End Sub '在採購模式按下確定 Private Sub cmdSL_Yes_Click() ‘... End Sub '在採購模式按下取消 Private Sub cmdSL_No_Click() ‘... End Sub '新增採購 Private Function fCISL_Add() As String ‘... End Function '修改採購 Private Function fCISL_Edit() As String ‘... End Function '刪除採購 Private Function fCISL_Delete() As String ‘... End Function '禁止適應症文字框輸入 Private Sub txtSD_KeyDown(KeyCode As Integer, Shift As Integer) KeyCode = 0 End Sub '禁止適應症文字框輸入 Private Sub txtSD_KeyPress(KeyAscii As Integer) KeyAscii = 0 End Sub '採購單備忘 Private Sub txtBH_Note_KeyPress(KeyAscii As Integer) ‘... End Sub '載入藥名類別 Public Sub load_cboItem_Class() ‘... End Sub '載入方劑類別 Public Sub load_cboClass_Class() ‘... End Sub '載入預設客戶的個人資料 Public Sub load_CD() ‘... End Sub '載入預設客戶的採購紀錄 Public Sub load_BH() ‘... End Sub '載入預設客戶的採購清單 Public Sub load_SL() ‘... End Sub '當啟始日期被改變 Private Sub dtpBH_SD_Change() '載入預設客戶的採購紀錄 Call load_BH '載入預設客戶的採購清單 Call load_SL End Sub '當結束日期被改變 Private Sub dtpBH_ED_Change() '載入預設客戶的採購紀錄 Call load_BH '載入預設客戶的採購清單 Call load_SL End Sub '查詢客戶資料 Private Sub cmdFind_Click() ‘... End Sub '查詢文字框 Private Sub txtCAB_KeyPress(KeyAscii As Integer) ‘... End Sub '購買紀錄依照客戶過濾 Private Sub chkBH_Custom_Click() '載入依照過濾的採購紀錄 Call load_BH End Sub '採購紀錄操作模式 Private Sub load_fraCIBH(strMode As String) ‘... End Sub '按下編輯備註 Private Sub cmdBH_EditNote_Click() ‘... End Sub '在採購紀錄按下確定 Private Sub cmdBH_Yes_Click() ‘... End Sub '在採購紀錄按下取消 Private Sub cmdBH_No_Click() ‘... End Sub '編輯備註 Private Function fCIBH_EditNote() As String ‘... End Function '設定藥名框顯示模式 Sub load_fraItem_Mode(strMode As String) ‘... End Sub '按下藥名框新增按鈕 Private Sub cmdItem_Add_Click() ‘... End Sub '按下藥名框修改按鈕 Private Sub cmdItem_Edit_Click() ‘... End Sub '按下藥名框刪除按鈕 Private Sub cmdItem_Delete_Click() ‘... End Sub '按下藥名框確定按鈕 Private Sub cmdItem_Yes_Click() ‘... End Sub '按下藥名框取消按鈕 Private Sub cmdItem_No_Click() ‘... End Sub '新增藥名 Private Function fcmdItem_add() As String ‘... End Function '修改藥名 Private Function fcmdItem_edit() As String ‘... End Function '刪除藥名 Private Function fcmdItem_delete() As String ‘... End Function '設定藥名類別索引 Private Sub cboItem_Class_Click() ‘... End Sub '設定藥名類別索引 Private Sub cboItem_Class_KeyPress(KeyAscii As Integer) ‘... End Sub '設定方劑框顯示模式 Sub load_fraClass_Mode(strMode As String) ‘... End Sub '按下方劑框新增按鈕 Private Sub cmdClass_Add_Click() ‘... End Sub '按下方劑框修改按鈕 Private Sub cmdClass_Edit_Click() ‘... End Sub '按下方劑框刪除按鈕 Private Sub cmdClass_Delete_Click() ‘... End Sub '按下方劑框確定按鈕 Private Sub cmdClass_Yes_Click() ‘... End Sub '按下方劑框取消按鈕 Private Sub cmdClass_No_Click() ‘... End Sub '新增方劑 Private Function fcmdClass_add() As String ‘... End Function '修改方劑 Private Function fcmdClass_edit() As String ‘... End Function '刪除方劑 Private Function fcmdClass_delete() As String ‘... End Function '設定方劑類別索引 Private Sub cboClass_Class_KeyPress(KeyAscii As Integer) ‘... End Sub '將藥名樹狀目錄中的藥名移入方劑藥名清單中 Private Sub lvwClass_List_OLEDragDrop(Data As MSComctlLib.DataObject, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single) ‘... End Sub '刪除方劑藥名清單上的項目 Private Sub lvwClass_List_KeyDown(KeyCode As Integer, Shift As Integer) ‘... End Sub
Step 3:請看程式執行結果,如圖 6-2。
圖 6‑2 中藥店管理程式執行結果
6.7 修改重點¶
由於線上更新的部分,必須牽涉到虛擬主機空間,這對於讀者來說太不方便了,因此筆者把這一段拿掉了。若讀者想要修改為網路版本,就要先有網路空間,筆者不認為使用點對點(P2P)的方式比較好,因為你必須先以電話連絡,兩台電腦要開機進入程式,這才能運作。而透過24小時運作的網路空間,就不會有這樣的問題,將更新過後的檔案,上傳到虛擬主機上,供其他分店的程式下載,解壓縮更新資料庫。這樣會是比較好的做法。
除此之外,報表的部分因為客戶需求不大,因此只有單純的列印藥單而已,若讀者有需求分析報表,修改這個部分,增加報表功能,會使得這系統更加完整。
最後,使用資料探勘的方式,就可以預測顧客的需求,而這個演算法已經是非常普及的,能夠預測顧客需求,將有助於備料、庫存、CRM管理,而系統也進入更高一層次。
6.8 結論¶
這個案主的需求非常的簡單,只是資料庫管理的功能,筆者認為最主要的關鍵就是在於介面設計,一個符合使用者需求的介面,才是本程式成功的關鍵,有時候分析系統的時候,必須要能夠從不同的角度做切入,是著變換你所扮演的角色,以便找出接近使用著需求的項目,再以系統分析的角色來進行分析,這樣將有助於拉近需求與系統的距離。
Lai Tai-Yu (賴岱佑)