thongkorn โพสต์ 2017-10-27 14:47:48

[VB.NET] การโหลดและบันทึกข้อมูลแบบไม่ซ้ำกันระหว่าง ComboBox และระบบฐานข้อมูล MS Access

http://www.g2gnet.com/webboard/images/vbnet/FillSaveComboBox.png
จากโปรเจค แจกฟรีโค้ดโปรแกรมการเก็บบันทึกข้อมูลบุคคล โดยใช้ VB.NET + MS Access 2007+ เรามาดูในส่วนย่อยของการใช้ ComboBox ก็เพื่อเชื่อมความสัมพันธ์กันแบบ One to One ซึ่งโค้ดในบทความนี้จะเป็นต้นฉบับ ก่อนที่จะทำให้มันกลายไปเป็นโปรแกรมย่อย หรือฟังค์ชั่นเพื่อในงานจริง เพราะถ้าหากเราใช้ ComboBox เพียงตัวเดียวก็ไม่มีปัญหา แต่ทีนี้งานมันมีมากกว่า 1 ตัวนี่ซิ ... โดยตัวอย่างนี้จะใช้ตาราง tblPosition หรือแสดงตำแหน่งพนักงาน คำว่า One To One หมายความว่าพนักงาน 1 คน จะมีตำแหน่งได้เพียง 1 ตำแหน่งเท่านั้น (ในทางปฏิบัติจริงอาจจะมีมากกว่า 1 ตำแหน่งได้ แต่ตอนนี้เอาแบบพื้นฐานเบื้องต้นก่อนข่ะรับ) ...

ขออารัมภบทเล็กน้อย ในการออกแบบตารางข้อมูลตาม ทฤษฎีบทของทองก้อน (Thongkorn's Theorem) หากฟิลด์ข้อมูลใดมีค่าที่ซ้ำๆกันในตารางนั้น ให้แยกฟิลด์นั้นออกไปอยู่อีก 1 ตาราง จากนั้นจับมันกลับเข้ามาเชื่อมความสัมพันธ์กันใหม่อีกครั้ง จะปรากฏดังรูป
http://www.g2gnet.com/webboard/images/vbnet/FillSaveComboBoxDB.png
ที่เรียกว่า ความสัมพันธ์แบบ 1 ต่อ 1 ก็เพราะค่า PositionFK ในตารางหลัก tblContact จะมีความสัมพันธ์กับ PositionPK ในตารางย่อย tblPosition เพียงค่า 1 ค่า เช่น PositionFK และ PositionPK = 14 มันมีค่า PositionName = IT Specialist และค่าตำแหน่งนี้ก็จะมีอยู่ด้วยกัน 2 คน แต่ค่า "IT Specialist" มันจะเก็บค่าเอาไว้เพียง 1 ค่าเท่านั้นในตาราง tblPosition ... การแยกย่อยตารางออกไป ก็เพื่อลดความซ้ำซ้อนของข้อมูล และทำให้ลดขนาดของไฟล์ฐานข้อมูล (DataBase) ลงไปด้วยนั่นเอง ประเด็นที่สำคัญคือ มันเกิดความยืดหยุ่น อำนวยความสะดวกให้กับผู้ใช้งาน แต่ทั้งนี้ทั้งนั้นมันก็ต้องมาพร้อมกับการเขียนโปรแกรมที่ยากขึ้นไปอีกนั่นเอง ...
มาดูโค้ดในส่วนของการโหลดข้อมูลเข้าสู่ ComboBox
    ' / --------------------------------------------------------------------------------
    ' / Load Position data into ComboBox
    Private Sub PopulateComboBox()
      strSQL = "SELECT * FROM tblPosition ORDER BY PositionName "
      '// Initialize ComboBox
      With cmbPositionName
            .DropDownStyle = ComboBoxStyle.DropDown
            .AutoCompleteMode = AutoCompleteMode.Suggest
            .AutoCompleteSource = AutoCompleteSource.ListItems
      End With
      '//
      Try
            If Conn.State = ConnectionState.Closed Then Conn.Open()
            Cmd = New OleDb.OleDbCommand(strSQL, Conn)
            Dim DR As OleDb.OleDbDataReader = Cmd.ExecuteReader
            Dim DT As DataTable = New DataTable
            DT.Load(DR)
            '/ Primary Key = ValueMember
            cmbPositionName.ValueMember = "PositionPK"
            '/ Display with field PositionName
            cmbPositionName.DisplayMember = "PositionName"
            '// Bind data source to control.
            cmbPositionName.DataSource = DT
            DR.Close()

      Catch ex As Exception
            MessageBox.Show(ex.Message)
      End Try
    End Sub
เมื่อเราทำการป้อนค่าเข้าไปยัง ComboBox จากนั้นทำการบันทึก (Save) จะต้องไป ตรวจสอบก่อนว่าค่าที่ป้อนเข้าไปใหม่มันมีอยู่แล้วหรือไม่
    ' / --------------------------------------------------------------------------------
    ' / Check duplicate data, If exist data then return <> 0
    Function CheckDuplicateName() As Integer
      ' Blank, and used TRIM for cut the head and tail spaces.
      If Trim(cmbPositionName.Text) = "" Then Return 1
      strSQL = _
            " SELECT Count(tblPosition.PositionName) AS CountName FROM tblPosition " & _
            " WHERE PositionName = " & "'" & Trim(cmbPositionName.Text) & "'"
      If Conn.State = ConnectionState.Closed Then Conn.Open()
      Cmd = New OleDb.OleDbCommand(strSQL, Conn)
      ' Return count records
      CheckDuplicateName = CInt(Cmd.ExecuteScalar)
    End Functionหากมีค่าซ้ำมันจะรีเทิร์น หรือส่งค่ากลับมากกว่า 1 ก็ให้ข้ามไป หากมีค่าเป็น 0 แสดงว่าค่าที่ป้อนเข้าไปใหม่ยังไม่มี ก็ให้ทำการบันทึกเข้าสู่ตาราง

แต่ก่อนที่จะบันทึกข้อมูล จะต้องทำการหาค่า Primary Key ตัวใหม่ ซ่ะก่อน
    ' / --------------------------------------------------------------------------------
    ' / Populate Primary Key for new Position Name and Return Primary Key.
    Function SetupNewPK() As Long
      strSQL = " SELECT MAX(tblPosition.PositionPK) AS MaxPK FROM tblPosition "
      If Conn.State = ConnectionState.Closed Then Conn.Open()
      Cmd = New OleDb.OleDbCommand(strSQL, Conn)
      '/ Check exist data and return value
      If IsDBNull(Cmd.ExecuteScalar) Then
            SetupNewPK = 1
      Else
            SetupNewPK = CLng(Cmd.ExecuteScalar) + 1
      End If
    End Function
ทำการบันทึกข้อมูลค่าตำแหน่ง (Position) ใหม่
    ' / --------------------------------------------------------------------------------
    ' / Save data from ComboBox into DataBase
    Private Sub SaveData()
      Try
            ' / Create New Primary Key for PositionName
            Dim PK As Integer = SetupNewPK()
            '/ ------------------------------------------------------------------
            If Conn.State = ConnectionState.Closed Then Conn.Open()
            '// Set your query to a variable(strSQL)
            strSQL = "INSERT INTO tblPosition (PositionPK, PositionName) Values (" & PK & ", '" & Trim(cmbPositionName.Text) & "')"
            Dim DA As OleDb.OleDbDataAdapter = New OleDb.OleDbDataAdapter(strSQL, Conn)
            '// Fill and add or refreshes rows in the dataset
            Dim DS As New DataSet
            DA.Fill(DS)
            '// Refresh data in ComboBox
            Dim strPos As String = Trim(cmbPositionName.Text)
            '// Load Data into ComboBox
            Call PopulateComboBox()
            ' Check value and show
            cmbPositionName.Text = strPos
            cmbPositionName.Focus()
      Catch ex As Exception
            MsgBox(ex.Message)
      End Try
    End SubConclusion: นี่คือกระบวนการคิดแบบเป็นขั้นเป็นตอน โดยทำการแยกย่อยงานต่างๆออกมาให้ได้ก่อน จากนั้นทำการเขียนโค้ดและทดสอบว่ามันได้ผลอย่างที่ต้องการหรือไม่ แล้วค่อยตัดต่อไปใช้กับงานจริงต่อไป มันก็จะลดปัญหาเรื่องของข้อผิดพลาดที่เราเรียกกันว่า "Bug" ได้ครับทั่นผู้ชม ... สวัสดี
ดาวน์โหลดโค้ดต้นฉบับ VB.NET (2010) ได้ที่นี่

066-pc โพสต์ 2018-7-3 10:37:56

Code อาจารย์เป็น สากล เลยครับ

thongkorn โพสต์ 2018-7-3 13:35:03

ผมไปแจกโค้ดตามเว็บนอกด้วยครับ ก็เลยมีโอกาสได้รู้จัก และแลกเปลี่ยนความรู้ แนวคิดกับบรรดาโปรแกรมเมอร์ต่างชาติเขาไปพร้อมๆกันครับ

jaricha5 โพสต์ 2020-4-20 16:33:31

ขอบคุณครับ

g2gsoftuser โพสต์ 2022-10-25 14:26:53

ขอบคุณครับ
หน้า: [1]
ดูในรูปแบบกติ: [VB.NET] การโหลดและบันทึกข้อมูลแบบไม่ซ้ำกันระหว่าง ComboBox และระบบฐานข้อมูล MS Access