วันอาทิตย์ที่ 13 กุมภาพันธ์ พ.ศ. 2554

5 : บันทึกข้อมูลแบบคุมได้ด้วย EVENT

บันทึกข้อมูลแบบคุมได้ด้วย EVENT

วัตถุประสงค์

ทำหน้าจอบันทึกข้อมูล ที่มีเงื่อนไขซับซ้อน โดยใช้ EVENT ใน VBA ควบคุมการใส่ข้อมูล

เนื้อหา

                ในการพัฒนาโปรแกรมสมัยนี้มีรูปแบบแตกต่างไปจากสมัยที่เป็น DOS มาก เนื่องจาก User Interface ปัจจุบันเป็นกราฟฟิก และ ตอบโต้กับผู้ใช้ผ่าน Mouse   แนวทางการเขียนโปรแกรมจึงถูกออกแบบมาให้สอดคล้องกันสภาพแวดล้อมเหล่านี้  เรียกว่า Event Driven Programming  
ขณะที่เราออกแบบหน้าจอโปรแกรมต่างๆ ก็จะมีตัว Interface หลายๆ แบบ ไม่ว่าจะ text box , combo box , checkbox,… interface เหล่านี้มี event เกาะอยู่ ซึ่งรวมไปถึงตัว Form เอง ก็มี Event ด้วยเช่นกัน  Event พวกทำหน้าที่คอยตอบสนองตามการปฏิสัมพันธ์กับผู้ใช้  การที่เราบอกว่า Interface นี้มี Event อะไร ก็หมายถึง Interface นี้มีการตอบสนองอะไรได้บ้าง  เช่น ปุ่ม Command มี Event Click  พอเราไป Click ก็เกิด Event พวกนี้ พอเมื่อเกิด Event แล้วมันก็จะไปเรียกโปรแกรมที่เราเขียนฝากไว้ใน Event มาทำงาน   การเขียนโปรแกรมแนวนี้จึงเป็นการเขียนโปรแกรมไปแทรกใน Event ต่างๆ ที่เกิดขึ้นในโปรแกรมของเรานั่นเอง    หากจะว่าไปแล้ว Event  พวกนี่ก็เป็นเหมือน Sub Routine ว่างๆ ที่รอให้เราไปเขียนโปรแกรมแทรกลงไปนั่นเอง  เพียงแต่ Sub พวกนี้จะลุกขึ้นมาทำงานตามเหตุการณ์ต่างๆ  ตามลักษณะของตัว Interface ที่เป็น
                และสำหรับ Access แล้ว ก็มี Event หลายๆ ตัวที่ เหมาะสำหรับทำงานกับ Database มากๆ หรือพูดง่ายๆ ว่ามี Sub Routine ที่พร้อมจะลุกมาทำงานตามคำสั่งที่เรากำหนด  มาลองไปดูพร้อมๆ กันนะครับ ในตอนนี้ขอลงรายละเอียด EVENT ของ FORM เองเป็นหลักก่อนนะครับ
FORM EVENT
Event บน Form เป็น Event ที่สำคัญสำหรับการเขียนโปรแกรมบน Access เพราะมี Event ที่เกี่ยวข้องการการ Update ข้อมูลเข้ามาเกี่ยวข้องหลายๆ ตัว  เราจะกล่าวถึง Event ที่สำคัญตามลำดับ  สำหรับการทดลองเขียนโปรแกรมตาม ขอให้สร้าง Form เปล่า มา 1 Form แล้วลองใส่ Code ตาม Event เหล่านี้
การทดลอง EVENT ต่างๆ ของ FORM

สำหรับการใส่ code เพื่อทดลองทำได้ 2 วิธีหลักคือ การไปหน้า VBA เลือก Object ( ณ ตอนนี้คือ Form ) ที่จะเขียนแล้วเลือก Event  หรือ เข้ามาจากหน้า Properties ของ Object แล้วไปที่ Event ก็ได้
EVENT เมื่อเปิด Form
ทุกครั้งเมื่อเราเรียก Form ขึ้นมาด้วยคำสั่ง Open หรือไปเปิด Form ขึ้นมา จะเกิด Event ตามลำดับ บน Form คือ
 Open -> Load -> Resize -> Activate -> GotFocus -> Current
 
-   OPEN EVENT
เกิดเมื่อมีการ Open Form จุดเด่นคือเราสามารถบังคับให้ยกเลิกการ Open Form ได้โดยการ Set ค่าลงในตัวแปร Cancel ที่ผูกมากับ Event นี้ ปกติค่าตัวแปร Cancel จะเป็น False ถ้าเราไม่ใส่ Code อะไรไว้ Form ก็จะเปิดตามปกติ   แต่ถ้าเราสั่งให้ Cancel = True  Form นี้จะถูกยกเลิกการ Open, Event ตามหลังจากนี้ ก็จะไม่เกิดขึ้น นั่นหมายถึง Form ก็จะถูกปิด   เรามักใช้ Event ตัวนี้ ตรวจสอบสิทธิในการ Open Form เช่นตัวอย่างต่อไปนี้
  Private Sub Form_Open(Cancel As Integer)
          If InputBox("Enter Magiccode") <> "6358" Then
             MsgBox ("Sorry! Magiccode was wrong")
             Cancel = True
          End If
  End Sub

ตัวอย่างนี้ ถ้าใส่รหัสผ่าน ไม่ถูกต้อง ก็จะไม่สามารถเข้าสู่ระบบได้ Form ตัวนี้ก็จะปิดตัวเองทันที
-   LOAD EVENT
เกิดเมื่อเริ่มทำการ Open เหมาะสำหรับการ แทรก Code ที่ใช้สำหรับตรวจสอบค่าต่างๆ ของระบบ เช่น User คนนี้ทำอะไรได้บ้างบนระบบ  แล้วทำการจัด Form ให้ตรงกับ User  นั้นๆ หรือ การแสดงวันเวลาที่ เปิด Form เป็นต้น  Event นี้จะเกิดขึ้นครั้งเดียวในการ Open Form จนกว่าจะมีการปิด แล้วเปิดใหม่
-   RESIZE EVENT
เกิดเมื่อมีการปรับเปลี่ยนขนาดของ Form  ไม่ได้เกิดเฉพาะในขณะ Open Form เท่านั้น  เมื่อ Form Open แล้ว แล้วมีการปรับขนาด Form ภายหลัง ก็จะเกิด Event นี้เช่นกัน
-   ACTIVATE EVENT
เกิดเมื่อมีเรียก Form ขึ้นมาใช้งานทุกครั้งจะเกิด Event นี้ ถ้า Form ถูกซ่อนอยู่โดยยังไม่ถูกปิด  และถูกเรียกกลับมาอีกครั้ง จะเกิด Event นี้เช่นกัน  เวลาที่เรา Switch ระหว่าง Form ใดใด Form หนึ่งจะเกิด Event นี้ เมื่อ Form นั้นถูกเรียกขึ้นมา  Event นี้จึงเหมาะกับการใส่โปรแกรมให้ Refresh ค่าบางอย่าง เมื่อมีการเรียก Form นี้กลับมา
-   GOTFOCUS EVENT
เกิดเมื่อมี User เรียก Form นี้ขึ้นมา ซึ่งหมายถึงการ Focus ของ User จะกลับมาที่ Form นี้  แต่ Event นี้จะเกิด ก็ต่อเมื่อ บน Form นั้นไม่ มี Control อื่นๆเลย การ Focus ของระบบ จึงต้องไปตกกับ Form ทั้ง Form   แต่ถ้ามี Control อยู่บน Form แล้ว  การ GotFocus จะไปเกิดที่ Event ของ Control แทน  ดังนั้นการฝัง Code ที่ให้ทำงานกับ Form สำหรับกรณีที่มีการเรียก Form ทุกครั้ง ควรใส่ไว้ใน ACTIVATE EVENT จะดีกว่า
-   CURRENT EVENT ( Database Event )
EVENT นี้ จะเกี่ยวข้องกับฐานข้อมูล กล่าวคือ เมื่อ Form ได้ทำการ Open สมบูรณ์แล้ว Form จะไปเรียกฐานข้อมูลออกมาแสดงบนจอ   เมื่อ Form แสดงข้อมูลลงบนจอจาก Record ใดใดก็ตาม จะเกิด Event นี้  ถ้า User ย้ายข้อมูลไปทีละ Record ทุกครั้งที่ย้ายไป จะเกิด Event นี้   เราใช้ Event นี้บ่อยมาก ในการตรวจสอบข้อมูลในแต่ละ Record  หรือการไป หยิบค่าบางอย่างที่เกี่ยวกับ Record นั้นๆ มาประมวลผล
ทดลองดูตัวอย่างการ ตรวจสอบ เบอร์ FAX ของ Supplier เมื่อไรก็ตามที่ User เลื่อน Record และพบ Supplier ที่ไม่มีเบอร์ FAX จะมี Msgbox เตือน  ทดลอง แทรก Code ชุดนี้ลงใน Current Event ของ Form ที่ตั้งค่า  RecordSource  Properties เป็น Supplier
 
      Private Sub Form_Current()
             If IsNull(Me.Fax) Then
                MsgBox ("Please ask FAX number for " & Me.CompanyName)
             End If
      End Sub                   
EVENT เมื่อปิด FORM
Event นี้จะเกิดขึ้นขณะปิด Form จะสวนทางกับการ Open Form ถ้าขณะที่ปิด Form ข้อมูลยังไม่ถูก Save, ACCESS  จะพยามยาม Save ข้อมูลก่อน ซึ่งอาจมี Event ของการ Update ข้อมูลก่อนหน้า ชุด Event นี้  สำหรับชุด ที่เกิดขึ้น ขณะ ปิด Form ตามปกติคือ
15. Unload -> Deactivate -> Close
-   Unload Event
เป็นการ Unload Object ออกจากระบบ  มีค่าที่สามารถบังคับให้การ Unload นี้lสามารถดำเนินต่อไปได้หรือไม่ ผ่านการ Set ค่า Cancel   คล้ายกับการ Open ถ้า Cancel = True จะไม่สามารถปิด Form ได้   เรามักใช้ Event นี้ควบคุม User ให้บันทึก หรือทำการข้อมูลให้เสร็จสิ้นก่อนออกจาหน้าจอ
-   Deactivate Event
เป็น Event ที่ตรงกันข้ามกับ Activate Event  Event นี้ มิได้เกิดขึ้นเฉพาะเมื่อเราปิด Form เท่านั้น  ขณะที่ เรา Switch Form ไปมา ก็จะเกิด Event นี้เช่นกัน โดยเกิดในขณะที่เราออกจาก Form ใด Form หนึ่ง
-   Close Event
เกิดขึ้นเมื่อ Form ถูกปิดแล้วจริง ๆ  เราใช้ทำการใดใด ที่คล้ายกับการสรุป เช่น บันทึกวันเวลาที่ User  หยุดใช้ งาน Form ตัวนี้เป็นต้น
EVENT เมื่อมีการแก้ไขข้อมูล ( UPDATE )
Event ชุดนี้ จะเกิดขึ้นเมื่อมีการแก้ไขข้อมูล และข้อมูลนั้นกำลังจะเข้าไป Write เข้าไปใน ฐานข้อมูลที่เราผูกไว้ใน Record Source Event กลุ่มนี้เป็น Event เฉพาะกับงาน Database โดยเแพาะ ลำดับการเกิด Event อง Form คือ
 BeforeUpdate -> AfterUpdate
-   BeforeUpdate Event ( Database Event )
เกิดขึ้นก่อนข้อมูลกำลังจะถูก Update เราสามารถตรวจสอบเงื่อนไขบางอย่าง ก่อนที่จะปล่อยให้เกิดการ Update จริงในข้อมูลได้   โดยการใส่ Code เข้าไปควบคุม  และในขณะเดียวกัน เราสามารถยกเลิกการ Update ของ User ได้โดยการใช้คำสั่ง Cancel = True  ทดลองดูตัวอย่างการบังคับให้ User สามารถ Update ข้อมูลได้ เฉพาะช่วงเวลา 08:00 – 17:00
 Private Sub Form_BeforeUpdate(Cancel As Integer)
             If Time < TimeValue("08:00") Or Time > TimeValue("17:00") Then
                MsgBox ("Please update data in office hour")
                Cancel = True
             End If
 End Sub
-   AfterUpdate Event( Database Event )
Event นี้เกิดขึ้น เมื่อมีการ Update ข้อมูลแล้ว  เรามักใช้ Event นี้ ในการคำนวณค่าสรุป หรือ เก็บ Log การบันทึกข้อมูลของ User เป็นต้น
 Private Sub Form_AfterUpdate()
         MsgBox ("You Just Update A Data Record !")
 End Sub
EVENT เมื่อมีการลบข้อมูล ( DELETE )
เป็นชุด EVENT ที่เกิดขณะทำการ Delete ข้อมูล ซึ่งเราจะพบบ่อยๆ ว่า Access จะมีข้อความเตือนเราก่อนการลบ Record ทุกครั้ง  EVENT พวกนี้จะแทรกอยู่ในขณะการลบและเป็นไปตามลำดับ Event ดังที่แสดง
 Delete-> BeforeDelConfirm -> AfterDelConfirm
-   Delete Event ( Database Event )
เกิดขึ้นทันที ที่ User พยายามจะลบข้อมูล  Event นี้เกิดก่อนที่จะมีการถาม Confirm จาก User  เราสามารถ Cancel การลบ ได้ตั้งแต่จุดนี้ โดยให้ค่า  Cancel = True
-   BeforeDelConfirm Event ( Database Event )
Event นี้เกิดขึ้น ก่อนที่จะมี ข้อความที่ Access ถามเพื่อการ Confirm การลบ   เราสามารถกำหนดให้ Confirm การลบเองได้เลย โดยการผ่านค่าสู่ตัวแปร Response ใน Sub นี้  และ Sub นี้มีตัวแปร Cancel ให้ยกเลิกการลบได้ด้วยเช่นกัน  การผ่านค่า Response มี 2 ค่าคิอ

Constant
คำอธิบาย
AcDataErrContinue
ไม่ต้องแสดงข้อความเตือนของ Access ให้ Confirm การลบเลย
AcDataErrDisplay
แสดงข้อความเตือนการลบ ซึ่งเป็นค่า Default ของ Access หากไม่มีการแก้ไขอะไร ก็จะเป็นเงื่อนนี้

ตัวอย่างเช่น เราไม่ต้องการให้ Access เตือนการลบข้อมูลหากมีการลบข้อมูลในช่วงเวลา 08:00 – 17:00    เราจะระบุ Code ตามตัวอย่าง
 Private Sub Form_BeforeDelConfirm(Cancel As Integer, Response As Integer)
             If Time > TimeValue("08:00") And Time < TimeValue("17:00") Then
                Response = acDataErrContinue
             End If
 End Sub
-   AfterDelConfirm Event ( Database Event )
เกิดขึ้นหลังจากผ่านขั้นตอนทั้ง 2 แล้ว  ใช้สำหรับทำการสรุปข้อมูล เช่นการตัด Stock หรือ เก็บ Log ผู้ที่ลบข้อมูลเป็นต้น  เราสามารถตรวจสอบได้ว่า ผลการลบที่ผ่านมาเป็นอย่างไร โดยดูที่ตัวแปร Status ซึ่งจะมีค่าดังต่อไปนี้

Constant
คำอธิบาย
AcDeleteOK
การลบข้อมูลสำเร็จ
AcDeleteCancel
การลบข้อมูลถูกยกเลิก
AcDeleteUserCancel
การลบข้อมูลถูกยกเลิกโดย User

ตัวอย่างด้านล่างเป็นการทดสอบการ Delete ข้อมูล และแสดงข้อความตอบโต้กับผู้ใช้
 Private Sub Form_AfterDelConfirm(Status As Integer)
     Select Case Status
         Case acDeleteOK  'Indicates the deletion was successful.
          MsgBox ("Record Deleted")
     Case acDeleteCancel  'Indicates the deletion was canceled in Visual Basic.
          MsgBox ("Record Deletion Canceled")
     Case acDeleteUserCancel 'Indicates the deletion was canceled by the user.
          MsgBox ("Record Deletion Canceled by User")
     End Select
 End Sub
EVENT เมื่อมีการเพิ่มข้อมูล
ขณะที่เราทำการเพิ่มข้อมูลลงใน ACCESS จะเกิดชุด Event นี้ขึ้น ซึ่งมี Event ที่ซ้ำกับการ Update ข้อมูล 2 Event คือ BeforeUpdate และ AfterUpdate มีลำดับขั้นคือ
 BeforeInsert -> BeforeUpdate -> AfterUpdate-> AfterInsert
สำหรับกรณีที่มี Event เดียว แต่เกิดจาก 2 ทั้งแก้ไข ( update )  และ เพิ่ม ( insert )  เราจะใช้ค่า Newrecord เป็นตัวตรวจสอบว่า ขณะนั้น เป็น Event ที่เกิดจากการแก้ไขข้อมูลเก่า หรือ เกิดจากการเพิ่มข้อมูลใหม่
 Private Sub Form_BeforeUpdate(Cancel As Integer)
         If Me.NewRecord Then
            MsgBox ("-- Inserted")
         Else
            MsgBox ("-- Updated")
         End If
 End Sub
-   BeforeInsert Event ( Database Event )
Event นี้เกิดขึ้นขณะที่ User เริ่มบันทึก Stroke แรก ลงในการ Add ข้อมูล เราจะใช้สำหรับการอ่านค่าพิเศษ ที่ต้อง Write ไปในฐานข้อมูลทุกครั้งที่มีการ Add ข้อมูล คล้ายกับการทำ Default   แต่มีเงื่อนไขที่ซับซ้อนกว่า การใช้ Default ปกติ  Event นี้สามารถยกเลิกการ Add ข้อมูลได้ด้วย  โดยการใช้ Cancel = True เช่นกัน
-   AfterInsert Event ( Database Event )
เกิดเมื่อขั้นตอนการ Insert เสร็จสิ้นแล้ว เรามักใช้ในการทำ Summary หรือ สร้าง Log File เก็บประวัติการเพิ่มข้อมูล เป็นต้น
EVENT เมื่อมี Error
-   Error Event
เมื่อเกิด Error บน Form จะเกิด Event ตัวนี้ ให้เราสามารถ Trap การ Error ได้ และทำการตอบโต้ Error กับ Access ได้เองผ่านตัวแปร Response  โดยค่า Error จะส่งเป็น รหัสผ่านตัวแปรชื่อ DataErr

Constant
คำอธิบาย
AcDataErrContinue
ข้ามข้อความ Error ของ Access แล้วทำงานต่อไป  แต่ Error ยังคงค่าอยู่ เพียงแต่ปิดข้อความ Error ของ Access เท่านั้น เราใช้สำหรับการจัดการข้อความ Error ด้วยโปรแกรมของเราเอง
AcDataErrDisplay
ค่า Default ของ Access คือ แสดงข้อความ Error ของ Access

 Private Sub Form_Error(DataErr As Integer, Response As Integer)
        Const conDuplicateKey = 3022
        Dim strMsg As String
        If DataErr = conDuplicateKey Then
               Response = acDataErrContinue
               strMsg = "รหัสรายชื่อพนักงานจะต้องไม่ซ้ำกับรหัสเดิม"
               MsgBox strMsg
        End If
 End Sub
ตัวอย่างข้างต้นเป็นการตรวจสอบ Error โดยบรรจุลงใน Form ที่ทำการบันทึกรหัสพนักงาน หากมีการใส่รหัสซ้ำก็จะแสดง Error เป็นข้อความภาษาไทยที่สัมพันธ์กับ Table ทดลองใช้ตัวอย่าง Code ชุดนี้กับหน้า Form บันทึกข้อมูลของ Table อื่นๆได้เช่นกัน
ก่อนจาก
                บทนี้เราได้ทดลอง Event หลายๆ ตัวของ Form ไปแล้วนะครับ  จะเห็นได้ว่า Event พวกนี้เรานำไปประยุกต์การทำหน้าจอบันทึกข้อมูลได้มากมาย  ก่อนจากไปผมฝาก Event Timer ให้ลองเล่นดูอีก 1 Event ครับ ลอลทำดูนะครับ
-   Timer Event
มี Event ที่พิเศษ สำหรับ Form คือ Timer Event ซึ่งจะทำงานร่วมกับ TimerInterval Properties เป็น Event ที่จะเกิดขึ้นเองโดยไม่มีการไปทำอะไรจาก User  โดยจะเกิดในทุกระยะเวลาที่กำหนดไว้ในTimerInterval มีหน่วยเป็น 1/1000 ของวินาที  เราใช้ประโยชน์จาก Event นี้ในการทำงานพิเศษบางอย่างเช่น Screen Saver เมื่อไม่มีการทำการใดใดบน Form  ให้ปิด Form หรือ ให้อ่านค่าจากฐานข้อมูลตลอดเวลา  เช่น สร้าง Form ที่คอย Monitor ยอดขายสินค้าเป็นต้น ทดลองทำตามตัวอย่าง
-   Monitor จำนวน Customer
1.        สร้าง Form ใหม่ขึ้นหนึ่ง Form
2.        สร้าง Control ชื่อ Text0
3.        กำหนด TimerInterval ใน Properties ของ Form เป็น 2000 ( 2 วินาที )
4.        สร้าง Code ลงใน Form_Timer
5.      
6.  Private Sub Form_Timer()
7.          Me.Text0 = DCount("CustomerID", "Customers")
8.          
9.  End Sub
10.     
11.     ทดลอง Run Form
12.     ทดลอง Add ข้อมูลลงในฐานข้อมูล Customers

ตัวอย่างนี้ แสดงให้เห็นว่า ในการทำงานแบบ Multiuser เราสามารถกำหนดให้ Form เข้าไปอ่านค่าใน ฐานข้อมูลขึ้นมาแสดงได้ตลอดเวลา เราสามารถใช้วิธีการดังกล่าวในการ Monitor ราคาหุ้นสูงสุด ต่ำสุด  จำนวนที่นั่งที่เหลือในหนังแต่ละรอบ 
จากตัวอย่างข้างต้น การ Set ค่า Timer ยิ่งน้อย จะทำให้ Access ต้องวิ่งเข้าไปอ่านข้อมูลบ่อยขึ้น ซึ่งทำให้กิน Load ของระบบงาน เพราะในขณะนั้น User คนอื่นอาจกำลัง ทำการเขียนอ่าน Table ที่เราเข้าไปอ่านอยู่เช่นกัน  ควรระมัดระวังในการใช้ กลุ่มคำสั่งที่ต้องอ่านเขียนข้อมูล ใน Timer เป็นอย่างดี

ไม่มีความคิดเห็น:

แสดงความคิดเห็น