private sub combobox1_afterupdate()
on error goto baoloi
............
baoloi:
msgbox "Khong co trong danh muc"
end sub
Mục đích của code trên là khi combox1 cho giá trị đúng thì OK, còn khi cho giá trị không nằm trong Rowsource thì hien msgbox để thông báo. Tuy nhiên vấn đề của mình là khi chạy code này, combox1 cho giá trị đúng thì msgbox vẫn hiện lên. Mình không hiểu code có bị sai không nữa.
Các bạn chỉ giúp mình với
Cám ơn rất nhiều
private sub combobox1_afterupdate()
on error goto baoloi
............
baoloi:
msgbox "Khong co trong danh muc"
end sub
Mục đích của code trên là khi combox1 cho giá trị đúng thì OK, còn khi cho giá trị không nằm trong Rowsource thì hien msgbox để thông báo. Tuy nhiên vấn đề của mình là khi chạy code này, combox1 cho giá trị đúng thì msgbox vẫn hiện lên. Mình không hiểu code có bị sai không nữa.
Thường khi ta đã test hết các trường hợp mà ta nghĩ ra và giải quyết xong rồi thì mới dùng bẫy lỗi on error để dành cho các trường hợp còn lại. Bạn muốn test xem sai chỗ nào thì phải bỏ bẫy lỗi đi, chạy thử cho trường hợp có giá trị đúng mà chương trình không hiểu xem bạn sai tại đoạn code nào. Thân.
private sub combobox1_afterupdate()
on error goto baoloi
............
baoloi:
msgbox "Khong co trong danh muc"
end sub
Mục đích của code trên là khi combox1 cho giá trị đúng thì OK, còn khi cho giá trị không nằm trong Rowsource thì hien msgbox để thông báo. Tuy nhiên vấn đề của mình là khi chạy code này, combox1 cho giá trị đúng thì msgbox vẫn hiện lên. Mình không hiểu code có bị sai không nữa.
Các bạn chỉ giúp mình với
Cám ơn rất nhiều
Private Function Test() As Boolean
'******************************************************************************
'* *
'* Name: Test *
'* *
'* Purpose: Test only *
'* *
'* Returns: True if OK *
'* *
'******************************************************************************
On Error GoTo PROC_ERROR
'// Assume function fails
Test = False
'// Your code here...
'//...
If Not YourFunction() Then GoTo PROC_DONE '// This is a sample that show how to call another function which return True or False
'// Continue your code....
'// ...
'// All's well - return True
Test = True
PROC_DONE:
'// Release resource here
Exit Function
PROC_ERROR:
Call Process_Error(MODULE_NAME, "Test") '// This is the function that process the Error (may be raise the error msgbox)
Resume PROC_DONE
End Function
cái Process_Error nó được code như thế nào vậy bác?
P/s: à, em hiểu như thế này:
một sub nào đó, nhận module và tên sub rồi hiện lên thông báo rằng sub đó ở module đó bị lỗi trong quá trình thi hành. Phải vậy không bác.
À, đó là tớ guideline cách viết code mà theo tớ là khá "đẹp" chứ ko phải fix cái code ở bài 1. Để tớ ví dụ cho Bab 1 đoạn code thực tế và tương đối đẹp nhé:
Mã:
Private Function SaveData() As Boolean
'******************************************************************************
'* *
'* Name: SaveData *
'* *
'* Purpose: Save Detail and Master *
'* *
'* Returns: True ( SaveMaster = True AND SaveDetail = True ) *
'* *
'******************************************************************************
On Error GoTo SaveData_Error
'// Assume function fails
SaveData = False
'// Validation
If Not IsValid Then GoTo SaveData_Done
'// Save Master And Detail
If Not SaveMaster() Then GoTo SaveData_Done
If Not SaveDetail() Then
If mMode = fEditFormOnAdding Then Call DeleteMaster: GoTo SaveData_Done
End If
'// Prepare refresh parent list form
RefreshParent
'// All's well - return True
SaveData = True
SaveData_Done:
Exit Function
SaveData_Error:
Call Process_Error(MODULE_NAME, "SaveData")
Resume SaveData_Done
End Function
@SoiBien: Process_Error(...) là tùy theo cách mà mỗi người viết thôi. Tớ thì hay viết đơn giản thế này Copy this code to a module named: ErrorUI.bas
Mã:
Option Explicit
'******************************************************************************
'* *
'* Name: Error.bas *
'* *
'* Purpose: Used to process / handle all application errors. *
'* *
'*----------------------------------------------------------------------------*
'* Modification Log *
'* t 07-Jan-2002 Generated by VBeXpress 2000. *
'* *
'******************************************************************************
Private Const MODULE_NAME = "Error"
Public Const VALIDATION = "Validation"
Public Sub Process_Error(ByVal vstrModuleName As String, _
ByVal vstrProcName As String)
'******************************************************************************
'* *
'* Name: Process_Error *
'* *
'* Purpose: All errors are reported here. This procedure could be used to *
'* write error logs, send e-mail to support personel informing them *
'* of application errors, etc. *
'* *
'* Process_Error should be coded so that it will NEVER fail. *
'* Otherwise the error will not be reported. Also, it should not *
'* contain any error handling code. Otherwise the 'Err' object will *
'* be cleared and we won't be able get the error number or the error *
'* description. *
'* *
'******************************************************************************
Dim strMsg As String
'// Could be a validation message
If Err.Source = VALIDATION Then
Beep
MsgBox "Mã lỗi: " & Err.Number & vbCrLf & _
"Mô tả lỗi:" & Err.Description & vbCrLf & _
"Nguồn gây lỗi: " & Err.Source, vbExclamation, "ERROR"
Else
'// Setup message string
'//strMsg = "An error has occurred in the application in module" & vbCrLf & _
" '" & vstrModuleName & "' at procedure '" & vstrProcName & "'." & vbCrLf & vbCrLf & _
"Error Number: " & CStr(Err.Number) & vbCrLf & vbCrLf & Err.Description & vbCrLf & vbCrLf & _
"Please contact your system's administrator."
'// If splash screen open, close it. Otherwise, we won't be able to see the message
'// Note: Once we have the error number and description, it is ok to call other
'// procedures and clear the error object.
'>> If blnFormOpen("frmSplash") Then
'>> Unload frmSplash
'>> DoEvents
'>> End If
'// Inform user.
If Err.Number > 5000 Then
strMsg = Err.Description
MsgBox strMsg, vbExclamation, MSG_HDR_ERR_USER
Else
strMsg = "Lỗi xảy ra trong ứng dụng ở module" & vbCrLf & _
" '" & vstrModuleName & "' tại thủ tục '" & vstrProcName & "'." & vbCrLf & vbCrLf & _
"Mã lỗi: " & CStr(Err.Number) & vbCrLf & vbCrLf & Err.Description & vbCrLf & vbCrLf & _
"Hãy ghi lại các thông số về lỗi và thông báo cho người quản trị hệ thống hoặc liên lạc trực tiếp với tác giả."
MsgBox strMsg, vbCritical, MSG_HDR_ERR_APP
End If
Beep
End If
'// Add code to log errors, e-mail support, etc.
End Sub
Hầu hết tất cả những code trong chương trình tớ đều viết cùng 1 style và viết y chang như nhau (style này tớ áp dụng 1 add-ins tương đối nổi tiếng, và đại đa số là do máy sinh ra). Chính vì thế, sau 5 năm tớ đọc lại code vẫn còn nhớ nguyên si từng dòng lệnh có ý nghĩa như thế nào. Và tính thống nhất (consistency) được thể hiện trong tất cả các dự án (chứ ko chỉ trong 1 dự án hay trong 1 phần mềm cụ thể)
Thêm 1 guideline nữa là các bạn hãy cực kỳ cẩn thận khi viết code ở các event của controls vì rất có thể trùng lắp (chạy rất nhiều lần mà ko biết) và ko phải cái gì cũng nhét tá lả vào ..._AfterUpdate() hay vào ..._Change() được đâu.
Các bạn cũng luôn luôn nhớ là debug kỹ càng bằng cách sử dụng F9 (Bookmark), F8 (step by line), Shift F8 (by block step), Debug.Print v.v... để hiểu kỹ các events cùng các giá trị được thiết lập như thế nào trong chương trình của bạn.
Nhìn cái đoạn code nằm trong ..._AfterUpdate() ở trên (ở bài trên cùng gây ra lỗi mà bạn ko hiểu là lỗi gì đó) thì tớ cứ thấy có cảm giác cực kỳ bất an với chương trình của bạn mặc dù chưa nhìn thấy nó như thế nào. Nếu có viết thì hãy "vứt" cái đoạn code bên trong đó ra thành 1 thủ tục hay hàm nào đó để cho "đẹp". Đừng có viết code quá dài (hạn chế càng nhiều càng tốt) trong events của các controls.
Mã:
Private Sub kscFields_Click(Index As Integer)
MakeDirty enuMaster, True
If blnIsLoadingForm Then Exit Sub
If Index = CST_FLD_MASTER_STOREID Then
If kscFields(CST_FLD_MASTER_STOREID).ListIndex <> -1 Then
kscDetailItem(CST_FLD_DETAIL_STOREID).ListIndex = kscFields(CST_FLD_MASTER_STOREID).ListIndex
Else
kscDetailItem(CST_FLD_DETAIL_STOREID).ListIndex = ItemDataToListIndex(kscDetailItem(CST_FLD_DETAIL_STOREID), CST_DEF_STORE_VALUE) '// Default Store
End If
End If
End Sub
Ở đoạn code trên, các bạn chú ý các dòng như:
If blnIsLoadingForm Then Exit Sub '// Tức là ko chạy even này nếu form is loading. Điều này để tránh chạy lặp nếu .ListIndex <> -1 khi thiết lập ở 1 chỗ khác nếu có.
Hoặc If kscFields(CST_FLD_MASTER_STOREID).ListIndex <> -1 Then '// Chỉ thực hiện những đoạn lệnh tiếp theo khi ListIndex <> -1 (Đây là cái thường xuyên gây ra lỗi hoặc việc "chạy bất thường ko theo dự đoán" ở các chương trình mà mình thấy)
Tóm lại, khi viết mỗi 1 dòng code, bạn phải liên tục để ý những trường hợp khác xảy ra thì sẽ thế nào. Nếu có thói quen như vậy, chương trình của bạn sẽ hạn chế được rất nhiều lỗi "không thể chấp nhận được".
Sorry mọi người, FF browser của tớ hnay lại có vấn đề nên ko post bài cho đẹp được (code nó cứ thành 1 dòng). Thỉnh thoảng tớ cứ bị cãi lỗi này. Tiếc quá!