ผู้เขียน หัวข้อ: [VB.Net] แจกโค้ด Advanced CRUD กับการเก็บข้อมูลผู้ป่วย (Patient Info)  (อ่าน 806 ครั้ง)

ออฟไลน์ ทองก้อน ทับทิมกรอบ

  • Administrator
  • *****
  • กระทู้: 245
  • เพศ: ชาย
  • Webmaster G2GNet
CRUD is ...
Create Insert a new data row into the database
Read get information than database (Or it's Retrieve)
Update changes the value in the database
Delete remove this data from the database

ทีแรกตั้งใจว่าจะเขียนโค้ดออกมาในลักษณะ Simple CRUD หรือแบบง่ายๆเพื่อให้เห็นถึงหลักการวิธีคิดนั่นแหละครับ แต่ไปๆมาๆเห็นแล้วมันหงุดหงิดใจ ตามแนวคิดของคนสายทำม่ะ คือ "ความรู้ปราศจากความหมาย หากไม่สามารถนำไปใช้งานได้จริง" ก็เลยเปลี่ยนใจเขียนเป็นโค้ดตัวอย่างจริงๆในลักษณะ Advanced ไปเลยดีกว่า แต่ปรับลดความยากลงมา ด้วยการใช้ตารางข้อมูลแบบเดี่ยวๆ โดยไม่มีการ Join หรือสร้างความสัมพันธ์กับตารางอื่น ซึ่งจะเป็นแนวทางในการพัฒนาสำหรับผู้เริ่มต้นต่อไป ...


หน้าตาโปรแกรม ซึ่งรวมการค้นหา-เพิ่ม-แก้ไข-ลบ เอาไว้ที่ฟอร์มเดียวกันหมด ซึ่งการออกแบบในลักษณะนี้ ค่อนข้างง่ายก็จริง แต่ควบคุมลำดับขั้นตอนการทำงาน (Flow Control) ของผู้ใช้งานได้ยาก เพราะต้องคอยเช็คการเปิดปิด (Enabled) ปุ่มควบคุมต่างๆ

หลักการทั่วไปในการเขียนโปรแกรมกับระบบฐานข้อมูล
1. ทำการค้นคืนข้อมูล (Retrieve) เพื่อค้นหาเฉพาะสิ่งที่ต้องการเท่านั้น (ซึ่งไม่ใช่การมาเลือกรายการแบบเดินหน้า ถอยหลังไปทีละเรคคอร์ดน่ะครับ) หรือแสดงรายการทั้งหมด
2. ตรวจสอบว่ามีข้อมูลหรือไม่
2.1 หากไม่มีก็ทำการเพิ่ม (Add)
2.2 หากมีข้อมูล ก็มี 2 ทางเลือก คือ
2.2.1 ทำการแก้ไข (Edit)
2.2.2 ทำการลบ (Delete)


ตารางข้อมูล: ขอย้ำอีกทีว่า Primary Key (PK) คนละอย่างกับ Indentifier (ID)

เมื่อ ...
HNPK = Primary Key (โปรแกรมเมอร์ต้องใช้ในการอ้างอิง)
HN (Hospital Number) = Identifier (ผู้ใช้งานต้องใช้ในการอ้างอิง)

หากเรากำหนด PK = ID (คือใช้ HN ตัวเดียวนั่นแหละครับ)


- จะเกิดปัญหาขึ้นในวันข้างหน้าอย่างแน่นอน เพราะอะไร? ก็เพราะว่า สมมุติว่าตอนนี้เรากำหนด HN ให้เป็น Primary Key เวลาเอาไปเชื่อมความสัมพันธ์กับตารางการตรวจ (Diagnostic) มันก็จะยึดค่า HN นี้เอาไว้ แต่ถ้าหากวันหนึ่งเราอาจจะต้องเปลี่ยน HN (จากค่าเดิมที่ตั้งตามใจฉัน เช่น HN-59XXXXX) มาเป็นรหัสบัตรประชาชน 13 หลักแทนล่ะ เราก็ต้องตามไปแก้ไขหรือปรับปรุงค่า HN ในตารางการตรวจ (หรือตารางอื่นๆที่เกี่ยวข้อง) ตามกันไปให้หมดซิข่ะรับ

- ดังนั้นเราจึง ต้องแยก PK ออกจาก ID และใช้ PK ยึดเอาไว้เสมอ ไม่ว่าค่า ID (ในที่นี้คือ HN) จะเปลี่ยนจากตาราง Patient ไปกี่ครั้งก็ตามที แต่ตารางอื่นๆที่เกี่ยวข้อง เราจึงไม่จำเป็นต้องไปเปลี่ยนแปลงหรือแก้ไขแต่อย่างใดเลย

จงจำเอาไว้ว่า ...
Primary Key (PK) จะมีค่าซ้ำกันไม่ได้ และไม่สามารถเปลี่ยนแปลงค่าได้ (ควรใช้ข้อมูลแบบตัวเลขจำนวนเต็ม เพราะคำนวณหาได้ง่าย แต่ไม่แนะนำให้ใช้ AutoNumber)
Identifier (ID) จะมีค่าซ้ำกันไม่ได้ แต่สามารถเปลี่ยนแปลงค่าได้ (ข้อมูลแบบลูกผสมตัวเลข ตัวอักษรก็ได้)

รายละเอียดเพิ่มเติม พื้นฐานการเขียนโปรแกรมติดต่อฐานข้อมูลแบบ One-To-One (เก็บข้อมูลลูกค้า)

โค้ดในส่วนของฟอร์มหลัก (frmMainCRUD.vb)

โค๊ด: [Select]
' / --------------------------------------------------------------------------------
' / Developer : Mr.Surapon Yodsanga (Thongkorn Tubtimkrob)
' / eMail : thongkorn@hotmail.com
' / URL: http://www.g2gnet.com (Khon Kaen - Thailand)
' / Facebook: https://www.facebook.com/g2gnet (For Thailand)
' / Facebook: https://www.facebook.com/commonindy (For International)
' / Purpose: Advanced CRUD - Create Read Update Delete
' / Microsoft Visual Basic .NET (2010) + MS Access 2007
' / --------------------------------------------------------------------------------
Imports System.Data.OleDb

Public Class frmMainCRUD
    Dim PK As Integer
    Dim NewData As Boolean = False

    Private Sub frmSimpleCRUD_FormClosed(sender As Object, e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
        Me.Dispose()
        Application.Exit()
    End Sub

    ' / --------------------------------------------------------------------------------
    Private Sub InitializeGrid()
        With dgvData
            .Columns(0).HeaderText = "HNPK"
            .Columns(0).Visible = False
            '//
            .Columns(1).HeaderText = "HN"
            .Columns(2).HeaderText = "ชื่อ - นามสกุล"
            .Columns(3).HeaderText = "ที่อยู่"
            '//
            .Columns(4).HeaderText = "อำเภอ"
            .Columns(4).Visible = False
            '//
            .Columns(5).HeaderText = "จังหวัด"
            .Columns(5).Visible = False
            '//
            .Columns(6).HeaderText = "รหัสไปรษณีย์"
            .Columns(6).Visible = False
            '//
            .Columns(7).HeaderText = "เบอร์โทรศัพท์"
            '//
            .Columns(8).HeaderText = "วันเดือนปีเกิด"
            .Columns(8).Visible = False
            .Columns(9).HeaderText = "เพศ"
            .Columns(9).Visible = False
            '//
            .Columns(10).HeaderText = "หมู่โลหิต"
            .Columns(10).Visible = True
            .Columns(10).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
            .Columns(10).HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter

            '// แสดงสีสลับแถวคู่-คี่
            .AlternatingRowsDefaultCellStyle.BackColor = Color.AliceBlue
            With .ColumnHeadersDefaultCellStyle
                .BackColor = Color.Navy
                .ForeColor = Color.Black
                .Font = New Font("Tahoma", 9, FontStyle.Bold)
            End With
        End With
    End Sub

    Private Sub frmSimpleCRUD_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        Conn = ConnectDataBase()
        lblRecordCount.Text = ""
        NewMode()
        RetrieveData()
    End Sub

    ' / --------------------------------------------------------------------------------
    ' / รวบการค้นหา และการแสดงผลทั้งหมด เข้ามาไว้ที่เดียวกัน
    ' / หาก blnSearch = True แสดงว่า เกิดการค้นหาข้อมูล
    ' / หากไม่มีการส่งค่ามา ก็กำหนด blnSearch ไว้เป็น Option ค่าเป็น False เพื่อแสดงผลทั้งหมด
    Private Sub RetrieveData(Optional ByVal blnSearch As Boolean = False)
        '// blnSearch = True ค้นหาข้อมูล
        If blnSearch Then
            strSQL = "SELECT Patient.HNPK, Patient.HN, Patient.PatientName, Patient.Address, " & _
                " Patient.Amphur, Patient.ProvinceName, Patient.PostCode, Patient.Telephone, Patient.BirthDate, Patient.Sex, Patient.Blood " & _
                " FROM(Patient) " & _
                " WHERE " & _
                " [HN] " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
                " [PatientName] " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
                " [Address] " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
                " [Amphur] " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
                " [ProvinceName] " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
                " [PostCode] " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
                " [Telephone] " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
                " [Sex] " & " Like '%" & txtSearch.Text & "%'" & " OR " & _
                " [Blood] " & " Like '%" & txtSearch.Text & "%'" & _
                " ORDER BY Patient.HN "
        Else
            strSQL = "SELECT Patient.HNPK, Patient.HN, Patient.PatientName, Patient.Address, " & _
                " Patient.Amphur, Patient.ProvinceName, Patient.PostCode, Patient.Telephone, Patient.BirthDate, Patient.Sex, Patient.Blood " & _
                " FROM(Patient) ORDER BY Patient.HN "
        End If
        DA = New OleDb.OleDbDataAdapter(strSQL, Conn)
        DS = New DataSet
        DS.Clear()
        DA.Fill(DS, "Patient")
        dgvData.DataSource = DS.Tables("Patient")
        lblRecordCount.Text = "[จำนวน : " & dgvData.RowCount & " รายการ]"
        '//
        DA.Dispose()
        DS.Dispose()
        Conn.Close()
        '//
        InitializeGrid()
        txtSearch.Clear()
    End Sub

    ' / --------------------------------------------------------------------------------
    ' / ดับเบิ้ลคลิ๊กเพื่อแก้ไขรายการ
    Private Sub dgvData_DoubleClick(sender As Object, e As System.EventArgs) Handles dgvData.DoubleClick
        '// หากมีการเพิ่ม/แก้ไขข้อมูลค้างไว้อยู่ ควรแจ้งเตือนเอาไว้ก่อน
        If btnDelete.Text = "ยกเลิก" Then
            Dim Result As Byte = MessageBox.Show("คุณกำลังทำรายการค้างเอาไว้อยู่ กรุณาเลือก" & vbCrLf & _
                                    "Yes หากต้องการยกเลิกรายการปัจจุบัน หรือ " & vbCrLf & _
                                    "No หากต้องการทำรายการเดิม.", "ยืนยัน", _
                                    MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2)
            '// ยังไม่ทำรายการใหม่
            If Result = DialogResult.No Then Exit Sub
        End If
        '//
        Dim iRow As Integer
        '// อ่านค่าแถวที่ถูกโฟกัส
        iRow = dgvData.CurrentRow.Index
        '//
        PK = dgvData.Item(0, iRow).Value  '// เก็บค่า Primary Key เอาไว้
        txtHN.Text = "" & dgvData.Item(1, iRow).Value
        '// เก็บค่า HN เดิมเอาไว้ เพื่อทำการเปรียบเทียบในภายหลัง
        txtHN.Tag = txtHN.Text
        '// การใช้ Double quote "" เพื่อดักค่าว่าง (แนวคิดดั้งเดิมมาตั้งแต่ VB6)
        txtPatientName.Text = "" & dgvData.Item(2, iRow).Value
        txtAddress.Text = "" & dgvData.Item(3, iRow).Value
        txtAmphur.Text = "" & dgvData.Item(4, iRow).Value
        txtProvinceName.Text = "" & dgvData.Item(5, iRow).Value
        txtPostCode.Text = "" & dgvData.Item(6, iRow).Value
        txtTelephone.Text = "" & dgvData.Item(7, iRow).Value
        '//
        dtpBirthDate.Value = dgvData.Item(8, iRow).Value
        lblAge.Text = CalcDate(dtpBirthDate.Value, Now)
        '//
        If dgvData.Item(9, iRow).Value = "ชาย" Then
            rbtSexM.Checked = True
        Else
            rbtSexF.Checked = True
        End If
        cmbBlood.Text = dgvData.Item(10, iRow).Value
        '// พร้อมอยู่ในโหมดการแก้ไข
        NewData = False
        EditMode()
    End Sub

    ' / --------------------------------------------------------------------------------
    ' / สถานะการทำงานอยู่ในโหมดการเพิ่มข้อมูล
    ' / --------------------------------------------------------------------------------
    Private Sub NewMode()
        '// เคลียร์ค่าใน TextBox ทั้งหมด
        For Each c In GroupBox1.Controls
            If TypeOf c Is TextBox Then
                DirectCast(c, TextBox).Clear()
                DirectCast(c, TextBox).Enabled = False
            End If
        Next
        dtpBirthDate.Value = Now()
        rbtSexM.Checked = True
        '//
        cmbBlood.Items.Clear()
        cmbBlood.Items.Add("(N/A)")
        cmbBlood.Items.Add("A")
        cmbBlood.Items.Add("B")
        cmbBlood.Items.Add("AB")
        cmbBlood.Items.Add("O")
        cmbBlood.SelectedIndex = 0
        '//
        btnAdd.Enabled = True
        btnSave.Enabled = False
        btnDelete.Enabled = True
        btnDelete.Text = "ลบข้อมูล"
        btnRefresh.Enabled = True
    End Sub

    ' / --------------------------------------------------------------------------------
    ' / สถานะการทำงานอยู่ในโหมดการแก้ไข
    Private Sub EditMode()
        '// เคลียร์ค่าใน TextBox
        For Each c In GroupBox1.Controls
            If TypeOf c Is TextBox Then
                DirectCast(c, TextBox).Enabled = True
            End If
        Next
        btnAdd.Enabled = False
        btnSave.Enabled = True
        btnDelete.Enabled = True
        btnDelete.Text = "ยกเลิก"
        btnRefresh.Enabled = False
    End Sub

    ' / --------------------------------------------------------------------------------
    Private Sub btnSave_Click(sender As System.Object, e As System.EventArgs) Handles btnSave.Click
        '// Validate Data
        If txtHN.Text = "" Or IsNothing(txtHN.Text) Then
            MessageBox.Show("กรุณาป้อนค่า HN ให้เรียบร้อยด้วย.", "รายงานความผิดพลาด", _
                            MessageBoxButtons.OK, MessageBoxIcon.Warning)
            txtHN.Focus()
            Exit Sub
        End If
        If txtPatientName.Text = "" Or IsNothing(txtPatientName.Text) Then
            MessageBox.Show("กรุณาป้อนชื่อ-สกุลผู้ป่วย ให้เรียบร้อยด้วย.", "รายงานความผิดพลาด", _
                            MessageBoxButtons.OK, MessageBoxIcon.Warning)
            txtPatientName.Focus()
            Exit Sub
        End If
        '//
        Dim Sex As String
        If rbtSexM.Checked Then
            Sex = "ชาย"
        Else
            Sex = "หญิง"
        End If
        '// NewData = True คือการเพิ่มข้อมูลใหม่ (ค่านี้กำหนดตอนที่กดปุ่ม btnAdd_Click)
        If NewData Then
            '// ตรวจสอบค่า HN ที่ป้อนเข้ามา ไปมีค่าซ้ำกับของเดิมที่มีอยู่หรือไม่
            strSQL = _
                " SELECT Count(Patient.HN) AS CountHN FROM Patient " & _
                " WHERE HN = " & "'" & txtHN.Text & "'"
            If DuplicateID(strSQL) Then
                MessageBox.Show("HN มีค่าซ้ำ กรุณาแก้ไขใหม่ให้เรียบร้อยด้วย.", "รายงานความผิดพลาด", _
                                MessageBoxButtons.OK, MessageBoxIcon.Warning)
                txtHN.Focus()
                Exit Sub
            End If
            '//
            strSQL = "INSERT INTO Patient(" & _
                " HNPK, HN, PatientName, Address, Amphur, ProvinceName, PostCode, Telephone, " & _
                " BirthDate, Sex, Blood, DateAdded, DateModified) " & _
                " VALUES(" & _
                "'" & SetupNewPK() & "'," & _
                "'" & txtHN.Text & "'," & _
                "'" & txtPatientName.Text & "'," & _
                "'" & txtAddress.Text & "'," & _
                "'" & txtAmphur.Text & "'," & _
                "'" & txtProvinceName.Text & "'," & _
                "'" & txtPostCode.Text & "'," & _
                "'" & txtTelephone.Text & "'," & _
                "'" & dtpBirthDate.Value & "'," & _
                "'" & Sex & "'," & _
                "'" & cmbBlood.Text & "'," & _
                "'" & Now & "'," & _
                "'" & Now & "'" & _
                ")"
            '// EDIT MODE
        Else
            '// หากค่าใหม่ (Text) กับค่าเดิม (Tag) มีค่าไม่เท่ากันแสดงว่ามีการเปลี่ยนแปลงค่า HN
            '// จะต้องทำการตรวจสอบว่าค่าที่เปลี่ยนไปนั้น ไปซ้ำกับของเดิมที่มีอยู่แล้วหรือไม่
            If txtHN.Text <> txtHN.Tag Then
                strSQL = _
                    " SELECT Count(Patient.HN) AS CountHN FROM Patient " & _
                    " WHERE HN = " & "'" & txtHN.Text & "'"
                If DuplicateID(strSQL) Then
                    MessageBox.Show("HN มีค่าซ้ำ กรุณาแก้ไขใหม่ให้เรียบร้อยด้วย.", "รายงานความผิดพลาด", _
                                    MessageBoxButtons.OK, MessageBoxIcon.Warning)
                    txtHN.Focus()
                    Exit Sub
                End If
            End If
            '// START UPDATE
            strSQL = "UPDATE Patient SET " & _
                " HN='" & txtHN.Text & "', " & _
                " PatientName='" & txtPatientName.Text & "', " & _
                " Address='" & txtAddress.Text & "', " & _
                " Amphur='" & txtAmphur.Text & "', " & _
                " ProvinceName='" & txtProvinceName.Text & "', " & _
                " PostCode='" & txtPostCode.Text & "', " & _
                " Telephone='" & txtTelephone.Text & "', " & _
                " BirthDate='" & dtpBirthDate.Value & "', " & _
                " Sex='" & Sex & "', " & _
                " Blood='" & cmbBlood.Text & "', " & _
                " DateModified='" & Now & "'" & _
                " WHERE HNPK=" & PK & ""    ' ค่า PK จะได้มาจากการดับเบิ้ลคลิ๊กเลือกรายการแก้ไขเอาไว้แล้วล่วงหน้า
        End If
        '// การ Insert/Update กระทำเหมือนกัน
        DoSQL(strSQL)
        RetrieveData()  '// Refresh
        '//
        NewMode()       '// ตั้งค่าโหมด
    End Sub

    ' / --------------------------------------------------------------------------------
    ' / ฟังค์ชั่นในการหาค่า Primary Key ตัวใหม่ไม่ให้ซ้ำกัน
    Function SetupNewPK() As Long
        strSQL = _
            " SELECT MAX(Patient.HNPK) AS MaxPK FROM Patient "
        If Conn.State = ConnectionState.Closed Then Conn.Open()
        Cmd = New OleDb.OleDbCommand(strSQL, Conn)
        '/ ตรวจสอบว่ามีข้อมูลอยู่หรือไม่ และคืนค่ากลับ
        If IsDBNull(Cmd.ExecuteScalar) Then
            SetupNewPK = 1
        Else
            SetupNewPK = Cmd.ExecuteScalar + 1
        End If
    End Function

    ' / --------------------------------------------------------------------------------
    Public Function DuplicateID(ByVal Sql As String) As Boolean
        If Conn.State = ConnectionState.Closed Then Conn.Open()
        Cmd = New OleDb.OleDbCommand(Sql, Conn)
        ' Return count records
        DuplicateID = Cmd.ExecuteScalar
    End Function

    ' / --------------------------------------------------------------------------------
    ' / ฟังค์ชั่นในการสร้างรหัสลูกค้า หรือ ID แบบอัตโนมัติ ตามรูปแบบที่เราต้องการ
    Function SetupAutoID() As String
        strSQL = _
            " SELECT MAX(Patient.HNPK) AS MaxPK FROM Patient "
        If Conn.State = ConnectionState.Closed Then Conn.Open()
        Cmd = New OleDb.OleDbCommand(strSQL, Conn)
        Dim MaxPK As Long
        '/ หาค่าสูงสุดของ Primary Key
        If IsDBNull(Cmd.ExecuteScalar) Then
            '// ไม่มีข้อมูลก็กำหนดค่า 1 ให้
            MaxPK = 1
        Else
            '// หากมีข้อมูลก็เพิ่ม (Increment) ไปอีก 1
            MaxPK = Cmd.ExecuteScalar + 1
        End If
        ' ตัวอย่างของการสร้างรูปแบบ ID อัตโนมัติ HN-59XXXXX
        ' เช่น ได้ MaxPK = 13 เอามาเรียงต่อกันกับ 0 จำนวน 5 ตัว ก็จะได้ "00000" & "13" = "0000013"
        ' ให้นับกลับมาจากทางขวาเข้ามาทางซ้าย ก็จะได้ "00013" (Microsoft.VisualBasic.Right("00000" & MaxPK, 5))
        SetupAutoID = "HN-" & Microsoft.VisualBasic.Right(Year(Now), 2) & Microsoft.VisualBasic.Right("00000" & MaxPK, 5)
    End Function

    ' / --------------------------------------------------------------------------------
    Private Sub DoSQL(ByVal Sql As String)
        Cmd = New OleDb.OleDbCommand
        If Conn.State = ConnectionState.Closed Then Conn.Open()
        Try
            Cmd.Connection = Conn
            Cmd.CommandType = CommandType.Text
            Cmd.CommandText = Sql
            Cmd.ExecuteNonQuery()
            MessageBox.Show("ปรับปรุงข้อมูลเรียบร้อย.", "รายงานสถานะ", MessageBoxButtons.OK, MessageBoxIcon.Information)
            Cmd.Dispose()
        Catch ex As Exception
            MsgBox("Error: " & ex.Message)
        End Try
    End Sub

    Private Sub btnAdd_Click(sender As System.Object, e As System.EventArgs) Handles btnAdd.Click
        NewData = True  '// IMPORTANT เมื่อต้องระบุว่ามีการเพิ่มข้อมูลใหม่
        EditMode()
        '// สร้าง HN แบบอัตโนมัติ
        txtHN.Text = SetupAutoID()
        txtHN.Focus()
    End Sub

    Private Sub btnDelete_Click(sender As System.Object, e As System.EventArgs) Handles btnDelete.Click
        '// กรณีอยู่ในโหมดแก้ไขข้อมูลอยู่
        If btnDelete.Text = "ยกเลิก" Then
            btnAdd.Enabled = True
            btnSave.Enabled = True
            btnDelete.Enabled = True
            btnDelete.Text = "ลบข้อมูล"
            btnRefresh.Enabled = True
            '//
            NewMode()
        Else
            If dgvData.RowCount = 0 Then Exit Sub
            '// รับค่า Primary Key เอาไว้อ้างอิงเพื่อลบข้อมูล
            Dim iRow As Long = dgvData.Item(0, dgvData.CurrentRow.Index).Value
            '// รับค่า HN ไว้แสดงผลยืนยันการลบข้อมูล
            Dim HN As String = dgvData.Item(1, dgvData.CurrentRow.Index).Value
            Dim Result As Byte = MessageBox.Show("คุณแน่ใจว่าต้องการลบข้อมูล " & HN & " นี้ ?", "ยืนยันการลบข้อมูล", _
                                                 MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2)
            If Result = DialogResult.Yes Then
                '// iRow คือค่า HNPK หรือ Primary Key ที่ถูกซ่อนใหนหลัก 0
                strSQL = "DELETE FROM Patient WHERE HNPK = " & iRow
                DoSQL(strSQL)
                '//
                NewMode()
                RetrieveData()
            End If
        End If
    End Sub

    Private Sub btnRefresh_Click(sender As System.Object, e As System.EventArgs) Handles btnRefresh.Click
        '// แสดงผลใหม่ทั้งหมด (ไม่ต้องกำหนด False เพราะถือเป็น Option ในตัวอยู่แล้ว)
        RetrieveData()
    End Sub

    Private Sub txtSearch_KeyPress(sender As Object, e As System.Windows.Forms.KeyPressEventArgs) Handles txtSearch.KeyPress
        ' ดักจับตัวอักขระอันไม่พึงปรารถนาสำหรับฐานข้อมูล เช่น ', * หรือ %
        txtSearch.Text = Replace(Trim(txtSearch.Text), "'", "")
        txtSearch.Text = Replace(Trim(txtSearch.Text), "%", "")
        txtSearch.Text = Replace(Trim(txtSearch.Text), "*", "")
        If Trim(txtSearch.Text) = "" Or Len(Trim(txtSearch.Text)) = 0 Then Exit Sub
        ' RetrieveData(True) หมายความว่า เป็นการค้นหาข้อมูล ดังนั้นจึงต้องใช้
        If e.KeyChar = Chr(13) Then
            '// ปิดเสียงเตือน
            e.Handled = True
            Call RetrieveData(True)
        End If
    End Sub

    Private Sub dtpBirthDate_ValueChanged(sender As System.Object, e As System.EventArgs) Handles dtpBirthDate.ValueChanged
        '// คำนวณหาอายุ
        lblAge.Text = CalcDate(dtpBirthDate.Value, Now())
    End Sub

    Private Sub txtPostCode_KeyPress(sender As Object, e As System.Windows.Forms.KeyPressEventArgs) Handles txtPostCode.KeyPress
        '// ดักค่าการกดคีย์ ให้รับค่า 0 - 9 เท่านั้น
        e.Handled = CheckDigitOnly(Asc(e.KeyChar))
    End Sub

End Class

โค้ดในการเชื่อมต่อฐานข้อมูล MS Access (modDataBase.vb)

โค๊ด: [Select]
' / --------------------------------------------------------------------------------
' / Developer : Mr.Surapon Yodsanga (Thongkorn Tubtimkrob)
' / eMail : thongkorn@hotmail.com
' / URL: http://www.g2gnet.com (Khon Kaen - Thailand)
' / Facebook: https://www.facebook.com/g2gnet (For Thailand)
' / Facebook: https://www.facebook.com/commonindy (For International)
' / Microsoft Visual Basic .NET (2010)
' / --------------------------------------------------------------------------------
Imports System.Data.OleDb

Module modDataBase
    Public Conn As OleDbConnection
    Public Cmd As OleDbCommand
    Public DS As DataSet
    Public DR As OleDbDataReader
    Public DA As OleDbDataAdapter
    Public strSQL As String

    Public Function ConnectDataBase() As System.Data.OleDb.OleDbConnection
        Dim strPath As String = MyPath(Application.StartupPath)
        'MsgBox(strPath)

        ' ให้ต่อท้ายด้วยโฟลเดอร์ตำแหน่งของข้อมูลที่ต้องการ คือ  \Data\ไฟล์ข้อมูล MS Access
        Dim strConn As String = _
            "Provider = Microsoft.ACE.OLEDB.12.0;"
        strConn += _
            "Data Source = " & strPath & "Data\Patient.accdb"

        Dim ConnDB As OleDb.OleDbConnection = New OleDb.OleDbConnection(strConn)
        ' Create Connection
        ConnDB.ConnectionString = strConn
        ' Return
        Return ConnDB
    End Function

    ' / --------------------------------------------------------------------------------
    ' / Get my project path
    ' / AppPath = C:\My Project\bin\debug
    ' / Replace "\bin\debug" with "\"
    ' / Return : C:\My Project\
    Function MyPath(AppPath As String) As String
        '/ MessageBox.Show(AppPath);
        AppPath = AppPath.ToLower()
        '/ Return Value
        MyPath = AppPath.Replace("\bin\debug", "\")
        '// กรณีที่หาโฟลเดอร์ไม่เจอ จะทำให้ขาดเครื่องหมาย \ ต่อท้าย
        If Right(MyPath, 1) <> "\" Then MyPath = MyPath & "\"
    End Function
End Module

โค้ดสำหรับรวบรวมฟังค์ชั่นต่างๆ (modFunction.vb)

โค๊ด: [Select]
' / --------------------------------------------------------------------------------
' / Developer : Mr.Surapon Yodsanga (Thongkorn Tubtimkrob)
' / eMail : thongkorn@hotmail.com
' / URL: http://www.g2gnet.com (Khon Kaen - Thailand)
' / Facebook: https://www.facebook.com/g2gnet (For Thailand)
' / Facebook: https://www.facebook.com/commonindy (For International)
' / Microsoft Visual Basic .NET (2010)
' / --------------------------------------------------------------------------------
Module modFunction
    ' / --------------------------------------------------------------------------------
    ' / ฟังค์ชั่นในการป้อนเฉพาะค่าตัวเลขได้เท่านั้น
    Function CheckDigitOnly(ByVal index As Integer) As Boolean
        Select Case index
            Case 48 To 57 ' เลข 0 - 9
                CheckDigitOnly = False
            Case 8, 13 ' Backspace = 8, Enter = 13
                CheckDigitOnly = False
            Case Else
                CheckDigitOnly = True
        End Select
    End Function

    ' / --------------------------------------------------------------------------------
    ' / ฟังค์ชั่นในการคำนวณหาความแตกต่างระหว่างวันเดือนปี (คำนวณหาอายุ)
    ' / คัดลอกโค้ดทั้งหมดมาจาก VB6
    Public Function CalcDate(sDate As Date, eDate As Date) As String
        Dim vDays As Integer
        Dim vMonths As Integer
        Dim vYears As Integer
        ' Parameters:
        '    sDate - ค่าวันเดือนปีเกิด (หรือวันเดือนปีที่ต้องการคำนวณหา)
        '    eDate - คำนวณเทียบกับวันเดือนปีปัจจุบัน (Now())
        ' Results:
        '    vYears - เก็บค่าความแตกต่างของจำนวนปี
        '    vMonths - เก็บค่าความแตกต่างของจำนวนเดือน
        '    vDays - เก็บค่าความแตกต่างของจำนวนวัน

        ' หาความแตกต่างของจำนวนเดือน
        vMonths = DateDiff("m", sDate, eDate)
        vDays = DateDiff("d", DateAdd("m", vMonths, sDate), eDate)
        If vDays < 0 Then
            vMonths = vMonths - 1
            vDays = DateDiff("d", DateAdd("m", vMonths, sDate), eDate)
        End If
        vYears = vMonths \ 12 ' หารตัดเศษก็จะได้จำนวนปี
        vMonths = vMonths Mod 12 ' การหารเอาเศษ โดยจะมีค่าระหว่าง 0, 1, 2, ... 11 ไม่มีทางเท่ากับ หรือ มากกว่า 12
        CalcDate = "อายุ: " & vYears & " ปี " & vMonths & " เดือน " & vDays & " วัน."
    End Function

End Module

Conclusion: เอาไว้แค่นี้พอก่อนครับ แล้วค่อยมาว่ากันต่อในภาคต่อไป ที่ผมไม่ได้ใส่ข้อมูลต่างๆให้เต็มในประวัติผู้ป่วย ก็เพราะยังไม่อยากให้โค้ดมันรกเกินไป และต้องการให้เหล่ามือใหม่ทั้งหลายได้ศึกษาถึงกระบวนการขั้นตอน วิธีคิดเฉพาะในส่วนที่สำคัญอันเป็นหัวใจหลักของการเขียนโปรแกรม ตามสเต็ป CRUD ให้ลึกซึ้งเพียงพอเสียก่อน แล้วก้าวต่อไปพร้อมกัน Keep Walking

ดาวน์โหลดโค้ดต้นฉบับ VB.Net (2010) + MS Access 2007 ได้ที่นี่

บันทึกการเข้า
สิ่งที่ดีกว่าการให้ คือการให้แบบไม่มีที่สิ้นสุด

ออฟไลน์ โจ้

  • Newbie
  • *
  • กระทู้: 21
Re: [VB.Net] แจกโค้ด Advanced CRUD กับการเก็บข้อมูลผู้ป่วย (Patient Info)
« ตอบกลับ #1 เมื่อ: พฤศจิกายน 04, 2016, 06:11:39 am »
ขอบคุณครับ  :D

บันทึกการเข้า

ออฟไลน์ Mr.Den

  • Jr. Member
  • **
  • กระทู้: 73
  • เพศ: ชาย
Re: [VB.Net] แจกโค้ด Advanced CRUD กับการเก็บข้อมูลผู้ป่วย (Patient Info)
« ตอบกลับ #2 เมื่อ: พฤศจิกายน 11, 2016, 02:58:53 pm »
ขอบคุณมากครับอาจารย์  :-*

บันทึกการเข้า

ออฟไลน์ kangaroos

  • Newbie
  • *
  • กระทู้: 1
Re: [VB.Net] แจกโค้ด Advanced CRUD กับการเก็บข้อมูลผู้ป่วย (Patient Info)
« ตอบกลับ #3 เมื่อ: มกราคม 09, 2017, 06:55:35 pm »
ขอบคุณครับ

บันทึกการเข้า