บันทึกข้อมูลแบบคุมได้ด้วย 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 เป็นอย่างดี
ไม่มีความคิดเห็น:
แสดงความคิดเห็น