โปรแกรมการตรวจสอบหมายเลขบัตรประชาชน
อันดับแรกต้องขอออกตัวก่อนน่ะครับว่า การคำนวณหาความถูกต้องของเลขบัตรประชาชน ผมได้ Source Code เป็นโปรแกรมที่เขียนขึ้นจาก FoxPro ซึ่งน้องๆนักศึกษากลุ่มหนึ่งที่กำลังทำโปรเจคจบ ป.ตรี ได้ Load มาให้ผม โดยเธอทั้งหลายนั้นต้องการให้ผมแก้ไข Code เพื่อแปลงเป็น Visual Basic 6 กะ VB Dot Net ซึ่งผมเองก็ยังไม่ได้ตรวจสอบความถูกต้องหรอกครับว่า Algorithm นี้มันถูกต้องหรือไม่ หากท่านที่เข้ามาอ่านแล้วพบว่ามันไม่ตรงกะความเป็นจริง ก็ขอความกรุณาช่วยแจ้งบอกผมมาด้วยก็แล้วกันน่ะครับ

Private Sub cmdCheck_Click()
Dim Sum, Count As Integer ' ไม่มีการป้อนข้อมูลเข้า ก็ให้ออกจากโปรแกรมย่อยไปเหอะ If Trim(txtIDcard.Text) = "" Or Len(Trim((txtIDcard.Text)) = 0 Then Exit Sub
' คำสั่ง Trim คือการตัดช่องว่าง (Space) ทั้งด้านหน้า และ ด้านหลังของข้อมูลที่ป้อนเข้าไป พยายามใช้งานมันหน่อยน่ะครับ อย่างน้อยก็ป้องกันปัญหาจากผู้ใช้งาน - Human Error ได้ดีทีเดียวเชียวแหละ ' ความยาวต้องเท่ากับ 13 หลัก If Len(Trim(txtIDcard.Text)) < 13 Then MsgBox "กรุณากรอกหมายเลขบัตรประชาชนให้ครบทั้ง 13 หลักด้วย.", vbOKOnly + vbExclamation, "รายงานความผิดพลาด" Exit Sub End If
|
' หมายเหตุ: ไม่ต้องไปกังวลใจหรือซีเรียสมากนัก เพราะมีตำราภาคภาษาไทยหลายเล่ม มักบอกว่าคำสั่ง Exit Sub ไม่ควรใช้ ซึ่งสิ่งสำคัญของภาษา Visual Basic มันคือเรื่องของกระบวนการ Event/Driven กล่าวง่ายๆคือมันเกิดเหตุการณ์อะไรขึ้นมา เช่น กดคีย์ Enter การกดเมาส์ แล้วเราจะบังคับให้มันไปทำอะไรล่ะ ????? ' ปกติเราจะนำคำสั่ง Exit Sub มาใช้งานเพื่อ Trap Error ในขณะที่โปรแกรมกำลังทำงาน (Run Time) ดังนี้ครับ Sub ProgramTest() On Error GoTo ErrHandler ' หากเกิด Error ก็ให้กระโดดไปที่ Label --> ErrHandler กฏข้อห้ามของภาษา Basic (หรือภาษาอื่นๆ ยกเว้นภาษา Assembly) ก็คือ ห้ามใช้คำสั่ง GoTo เพราะคุณจะเขียนโปรแกรมในแบบที่เรียกได้ว่า "ไม่มีโครงสร้าง (Non-Structure)" แต่ใน VB จะยกเว้นในกรณีนี้ครับผม ' Do Something ' Do ........
' ปกติเราจะวางไว้ตำแหน่งล่างสุดของโปรแกรมย่อย ExitProc: Exit Sub
ErrHandler: MsgBox Err.Number & vbLf & Err.Description, vbOKOnly + vbCritical, "Error Status" Resume ExitProc ' ให้กระโดดไปที่ Label --> ExitProc เพื่อต้องการจบโปรแกรมย่อย End Sub ' Mission Impossible - เป็นไปไม่ได้ที่จะไม่ใช้ Exit Sub เลยครับพี่น้อง....
หลักการคิด (ที่ผมถอดมาจาก FoxPro น่ะครับ ผิดถูกอย่างไรก็ช่วยแจ้งมาด้วย จักขอบพระคุณเป็นอย่างยิ่งครับท่าน) ' หาผลรวมตั้งแต่หลักที่ 1 ไปจนถึงหลักที่ 12 (นับจากซ้ายไปขวา) ' โดยให้หลักที่ 1 คูณด้วยน้ำหนักประจำหลัก = 13 ' โดยให้หลักที่ 2 คูณด้วยน้ำหนักประจำหลัก = 12 ' โดยให้หลักที่ 3 คูณด้วยน้ำหนักประจำหลัก = 11 ' โดยให้หลักที่ .. คูณด้วยน้ำหนักประจำหลัก = .. ' โดยให้หลักที่ 12 คูณด้วยน้ำหนักประจำหลัก = 2 ' จากนั้นนำผลการคูณของแต่ละหลักมารวมกันเข้าไป
' หลักแต่ละหลัก คือ Val(Mid$(txtIDcard.Text, Count, 1)) ' น้ำหนักของแต่ละหลัก คือ (14 - Count) เมื่อ Count เริ่มต้นจาก 1 ไปสิ้นสุดที่ 12 ดังนั้นค่านี้ (14 - Count) จึงเริ่มต้นค่าจาก 13, 12, 11, ..., สิ้นสุดที่ 2 ครับผม
Sum = 0 ' Clear ค่าผลรวมก่อน (เพื่อความแน่ใจ) For Count = 1 To 12 Sum = Sum + Val(Mid$(txtIDcard.Text, Count, 1)) * (14 - Count) Next ' ลักษณะของการนำตัวแปร Sum มาเวียนใช้งาน สำหรับมือใหม่หัดขับในการพัฒนาโปรแกรม พยายามศึกษาการทำงานมันให้ดีน่ะครับ เพราะคุณต้องนำมันมาใช้งานตลอดทั้งชีวิตของการเขียนโปรแกรมของคุณแน่ๆ
' นำผลรวมที่ได้มา Mod (การหารเอาเศษ) ด้วย 11 นั่นคือค่าที่เราจะได้ก็คือ 0, 1, 2, .. , 10 (Sum Mod 11) ' เพิ่มเติม: เรา Mod ด้วยอะไร ก็จะได้ค่าสูงสุด (ที่เป็นไปได้) ของตัว Mod ลบด้วย 1 เสมอ (ในที่นี้คือ 11 - 1 = 10) ' เพิ่มเติม: เรามักจะนำตัวเลขจำนวนเต็มมา Mod ด้วย 2 เพื่อตรวจสอบว่าเลขจำนวนเต็มนั้นมันเป็นเลขคู่ หรือ เลขคี่ หาก Mod แล้วได้ 0 นั่นคือ เป็นเลขคู่ หาก Mod แล้วผลลัพธ์เป็น 1 แสดงว่าเป็นเลขคี่
' เอ้ามาว่ากันต่อไป ... ' จากนั้นให้ลบออกด้วย 11 ก็จะทำให้ได้ค่าตั้งแต่ 1, 2, 3, ... , 11 (11 - (Sum Mod 11)) ' แล้วให้เลือกตัวขวามือสุดมาหนึ่งตัว ด้วยคำสั่ง Right$ --> Right$(Str(11 - (Sum Mod 11)), 1) ' สุดท้ายก็ให้นำมาเปรียบเทียบกับหลักที่ 13 ของหมายเลขบัตรประชาชน ว่ามันตรงกันหรือไม่ ? ' หากตรงกันก็แสดงว่า เป็นบัตรแท้, หากไม่ตรงกัน ก็คือ บัตรเก๊ เท่านี้เองครับพี่น้อง If Right$(txtIDcard.Text, 1) = Right$(Str(11 - (Sum Mod 11)), 1) Then MsgBox "หมายเลขบัตรประชาชน " & txtIDcard.Text & " ถูกต้อง.", vbOKOnly + vbInformation, "รายงานการตรวจสอบ" Else MsgBox "หมายเลขบัตรประชาชน " & txtIDcard.Text & " ไม่ถูกต้อง.", vbOKOnly + vbInformation, "รายงานการตรวจสอบ" End If End Sub
Private Sub cmdExit_Click() End End Sub
Private Sub Form_Load() txtIDcard.Text = "" End Sub
Private Sub txtIDcard_KeyPress(KeyAscii As Integer) KeyAscii = CheckDigit(KeyAscii) ' ต้องการรับค่าเฉพาะตัวเลขเข้าไปใน TextBox End Sub
' ฟังค์ชั่นตรวจสอบการรับค่าเฉพาะตัวเลข Function CheckDigit(Index As Integer) As Integer Select Case Index Case 48 To 57: ' เลข 0 - 9 Case vbKeyReturn: ' Enter Case vbKeyBack: ' Backspace Case vbKeyDelete: ' Delete Case Else Index = 0 ' ส่งค่ากลับเป็น 0 แปลว่าไม่มีการกดคีย์ใดๆเกิดขึ้นน่ะครับ End Select
CheckDigit = Index' เป็นการส่งกลับค่าของการกดคีย์ เว้ากันซื่อๆคือ เลือกเฉพาะคีย์ที่เราต้องการน้านแหละพี่น้อง End Function |
VB Dot Net (Version 2003) Code Example
Public Class frmIDcard Inherits System.Windows.Forms.Form
Private Sub frmIDcard_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load txtIDcard.Text = "" lblIDcard.Text = "หมายเลขบัตรประชาชน" End Sub
Private Sub btnExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExit.Click End End Sub
' Sub Program ตัวนี้ผมคิดว่าหลายท่านคงจะน่าสนใจอยู่ไม่น้อยน่ะครับ Private Sub txtIDcard_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles txtIDcard.KeyPress ' เราไม่สามารถนำ KeyAscii ใน VB 6 มาใช้งานใน Dot Net ได้ ดังนั้นจึงต้องอาศัย e.KeyChar (มันจะระบุคีย์นั้นๆ ออกมาเลย) เข้ามาช่วย แล้วแปลงให้เป็นรหัส ASCII Code ด้วยคำสั่ง Asc Dim KeyAscii As Short = Asc(e.KeyChar) ' ทดสอบคีย์ที่กด โดยอาศัย Handle แปลเป็นภาษามนุษย์ง่ายๆ (เพราะผมไม่ใช่นักวิชาการ) คือ หากกดคีย์ที่ต้องการ เช่น เลข 0 เราจะไม่ล็อคการกดคีย์นี้ ดังนั้น e.Handled จึงต้องกำหนดให้เป็น False ก็คงเท่านี้เองแหละครับ Select Case KeyAscii Case 47 To 58 ' เลข 0 - 9 e.Handled = False Case 8, 13, 46 ' Backspace=8, Enter=13, Delete=46 e.Handled = False Case Else e.Handled = True End Select End Sub ' ลองไปดัดแปลงเป็น Function เพื่อใช้งานดูแล้วกันน่ะครับ พี่น้อง ...
' Algorithm และ รูปแบบคำสั่งเหมือนกันกะ VB 6 นั่นแหละครับ Private Sub btnCheck_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCheck.Click Dim Sum, Count As Integer ' ' ไม่มีการป้อนข้อมูล ก็ให้ออกจากโปรแกรมย่อยไปเหอะ If txtIDcard.Text = "" Or Len(txtIDcard.Text) = 0 Then Exit Sub ' ความยาวต้องเท่ากับ 13 หลัก If Len(txtIDcard.Text) < 13 Then ' โห ... เล่นเลียนแบบ Code ของ VB 6 มันซะเลย MsgBox("กรุณากรอกหมายเลขบัตรประชาชนให้ครบทั้ง 13 หลักด้วย.", vbOKOnly + vbExclamation, "รายงานความผิดพลาด") Exit Sub End If ' ' หาผลรวมตั้งแต่หลักที่ 1 ไปจนถึงหลักที่ 12 Sum = 0 For Count = 1 To 12 Sum = Sum + Val(Mid(txtIDcard.Text, Count, 1)) * (14 - Count) Next
' เปรียบเทียบค่าที่ได้กับหลักที่ 13 If Microsoft.VisualBasic.Right(txtIDcard.Text, 1) = Microsoft.VisualBasic.Right(Str(11 - (Sum Mod 11)), 1) Then MessageBox.Show("หมายเลขบัตรประชาชน " & txtIDcard.Text & " ถูกต้อง.", "รายงานการตรวจสอบ", MessageBoxButtons.OK, MessageBoxIcon.Information) Else MessageBox.Show("หมายเลขบัตรประชาชน " & txtIDcard.Text & " ไม่ถูกต้อง.", "รายงานการตรวจสอบ", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) End If End Sub End Class
|
|