เรียนรู้ Visual Basic 6.0 กับ ฐานข้อมูล MS Access ภาค 8

Category »  VB 6/VB.Net
โดย : Webmaster เมื่อ 2/2/2550 14:09:00
(อ่าน : 25283) 

จากตอนที่ผ่านมานั้นเราสามารถนำข้อมูล ที่มีการสร้างความสัมพันธ์ (แบบเด็กๆอนุบาลแมวเหมียว) ของตารางข้อมูล 2 ตาราง มาแสดงผลลงในตารางกริด พร้อมกับทำการค้นหาได้ด้วยเป็นที่เรียบร้อยแล้วนั้น ขั้นต่อไป ก็คืิอการเลือกข้อมูล (ที่เราต้องการ) เพื่อทำการปรับปรุง แก้ไข

ผลลัพธ์ที่จะได้จากภาคนี้

ผลลัพธ์ที่จะได้จากภาคนี้

สำหรับในภาคนี้ ผมจะขอเพิ่มเติมในเรื่องของการใช้งาน Combo Box ในอีกรูปแบบหนึ่งเข้ามาด้วยน่ะครับ โปรดสังเกตให้ดีๆ จากภาคก่อนๆนั้นเราจะเห็นได้ว่า Combo Box ที่ถูกใช้ในการแสดงผลรายชื่อจังหวัด เราไม่สามารถที่จะทำการแก้ไข หรือ เพิ่มเติมข้อมูลได้เลย (ผมตั้งใจเอง) แต่ในตอนนี้ Combo Box (cmbTitle) ที่ใช้ในการแสดงผลข้อมูลคำนำหน้าชื่อนั้น มันควรจะเป็นแบบไดนามิค ซึ่งมีการปรับเปลี่ยนได้ ดังนั้นเราจะตั้งค่าคุณสมบัติของ cmbTitle ให้ Style = 0 (Dropdown Combo) ดังภาพ

หน้าตาการออกแบบฟอร์มรอง

Design Time - ฟอร์มรอง
ดาวน์โหลด Source Code สำหรับ MS Visual Basic 6.0 - Service Pack 6
' จากฟอร์มหลัก โปรแกรมย่อยที่กดดับเบิ้ลคลิ๊กเมาส์ที่ MS FlexGrid ครับผม
Private Sub fgCustomer_DblClick()
    ' ดักความผิดพลาดที่อาจจะเกิดขึ้น โดยการตรวจสอบก่อนว่าส่งค่า CustomerID ออกไปจริงๆ
    If Val(fgCustomer.Text) <= 0 Or IsNull(fgCustomer.Text) Then Exit Sub
    ' เป็นการแก้ไขข้อมูล
    blnNewData = False
    ' ตั้งค่าเริ่มต้นเพื่อแจ้งกลับมาฟอร์มหลักว่าเกิดการเปลี่ยนแปลงข้อมูลหรือไม่ ?
    FormUpdate = False
    frmCustomer.Show vbModal  ' ให้ฟอร์มรองขึ้นมาแสดงผล
    If FormUpdate Then  ' หากมีการปรุงปรุงข้อมูล ต้องให้ทำการแสดงผลในตารางกริดใหม่
        Call SetupFgCustomer
        Call DisplayFgCustomer
    End If
End Sub

Private Sub cmdEdit_Click()
    Call fgCustomer_DblClick
End Sub
		

มาดูโค้ดในฟอร์มรองกันครับผม

Option Explicit
' ตัวแปรรับค่า CustomerID จากฟอร์มหลัก
Dim CusID As Long

Private Sub Form_Load()
    ' การหารตัดเศษเพื่อเอาเฉพาะเลขจำนวนเต็ม จะมีความเร็วกว่าการหาร / แบบนี้ที่จะได้จุดทศนิยมครับ ... พี่น้อง
    Me.Move (Screen.Width - Width) \ 2, (Screen.Height - Height) \ 2
    Call SetupScreen
    Call DisplayTitle
    Call DisplayProvince
    ' เราใช้ blnNewData ที่ถูกส่งมาจากฟอร์มหลัก เป็นการตรวจสอบว่าเพิ่มข้อมูลใหม่ หรือ แก้ไขข้อมูล
    If blnNewData = True Then
        txtCustomerID.Text = "[New]"
    Else  ' เป็นการแก้ไขข้อมูล
        CusID = Val(frmMainCustomer.fgCustomer.Text)  ' รับค่าจากตารางกริด (หลัก 0) ส่งให้กับตัวแปรแบบ Local  (CusID)
        ' เพื่อใช้งานเฉพาะในฟอร์มนี้
        Call RecordToScreen(CusID)  ' ส่งค่า CusID ไปโปรแกรมย่อย RecordToScreen เพื่อแสดงผล
        ' โปรแกรมย่อย RecordToScreen เคยอ้างถึงหลายครั้งแล้ว กรุณากลับไปอ่านด้วยครับ หากจำไม่ได้
    End If
End Sub

' เคลียร์รายการแสดงผลใหม่หน่อยครับ ... พี่น้อง
Sub SetupScreen()
    txtCustomerID.Text = ""
    cmbTitle.Clear
    txtFirstname.Text = ""
    txtLastname.Text = ""
    txtAddress.Text = ""
    txtAmphur.Text = ""
    cmbProvince.Clear
    txtPostCode.Text = ""
    txtTelephone.Text = ""
    txtFacsimile.Text = ""
End Sub

' Load รายการคำนำหน้า
Sub DisplayTitle()
Dim Add$
    Set DS = New ADODB.Recordset
    ' อันนี้ต้องการให้เรียงตามตัวอักษร เพราะจะมีฟังค์ชั่นตรวจสอบไว้อยู่แล้ว
    Statement = "SELECT * FROM tblTitle ORDER BY TitleName"
    Set DS = ConnMyDB.Execute(Statement, , adCmdText)
    cmbTitle.Clear
    Do Until DS.EOF
        Add$ = "" & Trim(DS("TitleName"))
        cmbTitle.AddItem Add$
        DS.MoveNext
    Loop
    DS.Close
    Set DS = Nothing
End Sub

' Load รายการจังหวัด --- ไม่ขอบรรยายมากน่ะครับ
Sub DisplayProvince()
Dim Add$
    Set DS = New ADODB.Recordset
    Statement = "SELECT * FROM tblProvince ORDER BY ProvinceID"
    Set DS = ConnMyDB.Execute(Statement, , adCmdText)
    cmbProvince.Clear
    Do Until DS.EOF
        Add$ = "" & Trim(DS("ProvinceName"))
        cmbProvince.AddItem Add$
        DS.MoveNext
    Loop
    DS.Close
    Set DS = Nothing
End Sub
		

ไคลแมกซ์ของท้องเรื่องล่ะครับ ...

Private Sub cmdSave_Click()
' ตรวจสอบข้อมูลที่ต้องการให้ผู้ใช้งานต้องคีย์ลงไปด้วยก่อนล่ะกัน
If Trim(txtFirstname.Text) = "" Or Len(Trim(txtFirstname.Text)) = 0 Then
    MsgBox "กรุณาป้อนข้อมูลรายชื่อของลูกค้าให้เรียบร้อยก่อนด้วย.", vbOKOnly + vbExclamation, "รายงานสถานะ"
    txtFirstname.SetFocus
    Exit Sub
ElseIf Trim(txtLastname.Text) = "" Or Len(Trim(txtLastname.Text)) = 0 Then
    MsgBox "กรุณาป้อนข้อมูลนามสกุลของลูกค้าให้เรียบร้อยก่อนด้วย.", vbOKOnly + vbExclamation, "รายงานสถานะ"
    txtLastname.SetFocus
    Exit Sub
End If
Call SaveData
End Sub

Sub SaveData()
Dim CountRec As Long
Set RS = New ADODB.Recordset
    ' หาก blnNewData = จริง คือการเพิ่มข้อมูลใหม่
    If blnNewData = True Then
        Statement = "SELECT * FROM tblCustomer ORDER BY CustomerID "
        RS.CursorLocation = adUseClient
        RS.Open Statement, ConnMyDB, adOpenForwardOnly, adLockReadOnly, adCmdText
        If RS.BOF Or RS.EOF Then
            CountRec = 1
        Else
            ' ขึ้นอยู่กับการออกแบบฐานข้อมูลด้วยน่ะครับ ... กรุณาไปดูในส่วนอื่นๆเพิ่มเติม ที่ผมทำไว้ด้วย
            RS.MoveLast
            CountRec = RS("CustomerID") + 1
        End If
        RS.Close
        
        Set RS = New ADODB.Recordset
        Statement = "SELECT tblCustomer.*, tblTitle.TitleName, tblProvince.ProvinceName " & _
                                " FROM (tblCustomer INNER JOIN tblProvince ON tblCustomer.ProvinceID = tblProvince.ProvinceID) " & _
                                " INNER JOIN tblTitle ON tblCustomer.TitleID = tblTitle.TitleID " & _
                                " ORDER BY [CustomerID] "
        RS.Open Statement, ConnMyDB, adOpenKeyset, adLockOptimistic, adCmdText
        RS.AddNew
        RS("CustomerID") = CountRec
    
    Else  ' การแก้ไขข้อมูล
        Statement = "SELECT tblCustomer.*, tblTitle.TitleName, tblProvince.ProvinceName " & _
                                " FROM (tblCustomer INNER JOIN tblProvince ON tblCustomer.ProvinceID = tblProvince.ProvinceID) " & _
                                " INNER JOIN tblTitle ON tblCustomer.TitleID = tblTitle.TitleID " & _
                                " WHERE [CustomerID] = " & CusID
        RS.Open Statement, ConnMyDB, adOpenKeyset, adLockOptimistic, adCmdText
    
    End If
    ' เทคนิคของการเขียนโปรแกรมอีกแบบหนึ่ง ไม่ว่าจะเป็นการเพิ่ม หรือ แก้ไขข้อมูลก็ตาม
    ' Edit/Save Data
    RS("TitleID") = CheckTitle(Trim(cmbTitle.Text))  ' ส่งค่าที่พิมพ์ใน Combox Box ไปตรวจสอบ
    RS("Firstname") = "" & Trim(txtFirstname.Text)
    RS("Lastname") = "" & Trim(txtLastname.Text)
    RS("Address") = "" & Trim(txtAddress.Text)
    RS("Amphur") = "" & Trim(txtAmphur.Text)
    RS("ProvinceID") = cmbProvince.ListIndex
    RS("PostCode") = "" & Trim(txtPostCode.Text)
    RS("Telephone") = "" & Trim(txtTelephone.Text)
    RS("Facsimile") = "" & Trim(txtFacsimile.Text)
    RS.Update
    ' บอกฟอร์มหลักว่าเกิดการเปลี่ยนแปลงข้อมูล
    FormUpdate = True
    MsgBox "บันทึกข้อมูลเรียบร้อย", vbOKOnly + vbInformation, "รายงานสถานะ"
    RS.Close
    Set RS = Nothing
    '
End Sub
		
' ฟังค์ชั่นที่ใช้ในการตรวจสอบค่าที่อยู่ใน ComboBox (Title)
' ส่งค่ามาเป็น String แต่ตอนส่งค่ากลับจะเป็นค่า TitleID (ตัวเลข) น่ะครับ ... พี่น้อง
Function CheckTitle(TitleName As String) As Byte
Dim CountRec As Byte    ' ไว้นับจำนวนของ TitleID
    ' ตรวจสอบว่ามีการป้อนข้อมูลหรือไม่ หากไม่มีให้กำหนดค่า Default เป็น 0 จากนั้น Return ค่ากลับ
    ' และออกจากฟังค์ชั่นไปเลยครับพี่น้อง ... เพื่อเป็นการไม่เสียเวลา
    If TitleName = "" Or Len(TitleName) = 0 Or TitleName = "-" Then
        CheckTitle = 0
        Exit Function
    End If
    Set DS = New Recordset
    Statement = "SELECT * FROM tblTitle WHERE [tblTitle.TitleName] = " & "'" & TitleName & "'"
    DS.CursorLocation = adUseClient
    DS.Open Statement, ConnMyDB, adOpenForwardOnly, adLockOptimistic, adCmdText
    '
    ' แสดงว่าไม่มีในรายการ ดังนั้นเราต้องเพิ่มรายการเข้าไปใหม่ในตาราง tblTitle
    If DS.RecordCount <= 0 Then
        Set DS = New Recordset
        Statement = "SELECT * FROM tblTitle ORDER BY [TitleID]"
        DS.CursorLocation = adUseClient
        DS.Open Statement, ConnMyDB, adOpenForwardOnly, adLockReadOnly, adCmdText
        ' ก่อนอื่นอ่านค่าจากรายการสุดท้ายซ่ะก่อนครับ
        If DS.BOF Or DS.EOF Then
            CountRec = 1
        Else
            DS.MoveLast
            CountRec = DS("TitleID") + 1  ' ได้เท่าไรให้บวกเพิ่มขึ้นอีก 1 
        End If
        '
        Set DS = New Recordset
        Statement = "SELECT * FROM tblTitle ORDER BY [TitleID]"
        DS.Open Statement, ConnMyDB, adOpenKeyset, adLockOptimistic, adCmdText
        DS.AddNew
        DS("TitleID") = CountRec
        DS("TitleName") = TitleName
        DS.Update
        ' ส่งค่า TitleID กลับไปเพื่อบันทึกข้อมูล
        CheckTitle = CountRec
        
    ' มีข้อมูลเดิมอยู่แล้ว
    Else
        ' ส่งค่า TitleID กลับไปเพื่อบันทึกข้อมูล
        CheckTitle = DS("TitleID")
    End If
    DS.Close
    Set DS = Nothing
End Function