ชุมชนคนรักภาษาเบสิค - Visual Basic Community

 ลืมรหัสผ่าน
 ลงทะเบียน
ค้นหา
ดู: 5383|ตอบกลับ: 1

[VB.NET] แจกโค้ดฟรีการเก็บข้อมูลลูกค้า กับความสัมพันธ์ของตารางข้อมูลแบบ One To One

[คัดลอกลิงก์]

308

กระทู้

498

โพสต์

5973

เครดิต

ผู้ดูแลระบบ

ทองก้อน ทับทิมกรอบ

Rank: 9Rank: 9Rank: 9

เครดิต
5973



ต้องบอกกล่าวก่อนว่าแอดมินไม่เคยนำวิธีการคิดแบบ Normalization มาใช้ในการอธิบาย แต่จะใช้ความสัมพันธ์ของตารางข้อมูลมาประกอบการพิจารณาการออกแบบเท่านั้น โดยแอดมินจะใช้แค่ 2 แบบ คือ One To One และ One To Many ...

ความสัมพันธ์ของตารางข้อมูลแบบ One To One ... เกิดจากการที่มีข้อมูลซ้ำๆขึ้นมาในตารางข้อมูล ตอนขณะที่ยังเป็นข้อมูลดิบอยู่ ดังนั้นเราต้องแยกฟิลด์ข้อมูลที่ซ้ำๆกันออกไปอยู่อีกตาราง เช่น บุคคล (หรือลูกค้า) อาศัยอยู่ในจังหวัดขอนแก่นได้หลายคน (แล้วจังหวัดอื่นๆอีกล่ะ) นักศึกษาเรียนสาขาดนตรีอยู่หลายคน (แล้วสาขาอื่นๆอีกล่ะ) ทั้งนี้ทั้งนั้นเมื่อมองย้อนกลับมาจะสังเกตได้ว่า บุคคล 1 คน จะอยู่ในจังหวัดใดจังหวัดหนึ่งตามบัตรประชาชนเท่านั้น (หรืออยู่อาศัยสักที่ใดที่หนึ่ง) และ นักศึกษา 1 คน สามารถเข้าศึกษาในสาขาใดสาขาหนึ่งเท่านั้น (เฉพาะสถานศึกษานั้นๆ) ความสัมพันธ์แบบนี้เราถึงได้เรียกว่า หนึ่งต่อหนึ่ง หรือ One To One ... (อ่านรายละเอียดเพิ่มเติม VB6+Access โปรแกรมระบบฐานข้อมูลครุภัณฑ์ ภาคตารางข้อมูล)

กระบวนการคิดในการออกแบบความสัมพันธ์ตารางข้อมูลแบบ One To One ...



- จะมี หลัก (Column) เราเรียกว่า ฟิลด์ข้อมูล (Field) ซึ่งแต่ละฟิลด์ที่ได้มานั้น ก็มาจากความต้องการในการจัดเก็บข้อมูลในแต่ละโปรเจค โดยนำเอา Field มาเป็นตัวหลักในการออกแบบตารางข้อมูล ทั้งการกำหนดชื่อฟิลด์ และชนิดของข้อมูล
- จะมี แถว (Row) เรียกว่า รายการ (Record) ซึ่งรวบรวมข้อมูลต่างมาจากฟิลด์ข้อมูล


- จากนั้นให้ป้อนข้อมูลดิบ (Raw Data) โดยให้มองว่านี่คือ ตารางหลัก (Master Table) จากนั้นมาพิจารณาว่า ฟิลด์ใดมีข้อมูลซ้ำๆกัน ให้จับฟิลด์นั้นแยกออกไปอยู่อีกตาราง เรียกว่า ตารางย่อย (Detail Table) แล้วเชื่อมความสัมพันธ์มันกลับเข้ามายังตารางหลัก ด้วยการใช้ตัวเลขจำนวนเต็ม


- ในตารางหลักจะมีกุญแจรอง Foreign Key หรือ FK เพื่อใช้ในการเชื่อมความสัมพันธ์ฟิลด์ข้อมูลเข้าไปหาตารางย่อยอื่นๆได้ ค่านี้ต้องเป็นตัวเลขเท่านั้น (หรือใครอยากจะใช้แบบอื่นก็ทำได้) ... นี่คือความสัมพันธ์แบบ One To One



- ในตารางหลัก (Master Table) จะมี Primary Key หรือ PK หรือ กุญแจหลัก เพื่อใช้ในการอ้างถึงข้อมูลที่ต้องการ โดยค่านี้ควรจะเป็นตัวเลขแบบจำนวนเต็ม (Number) เพื่อให้ง่าย สะดวก รวดเร็ว แม่นยำ ต่อการสร้าง ค่านี้จะต้องไม่เกิดค่าที่ซ้ำกัน และไม่สามารถเปลี่ยนค่าได้

- ในตารางหลัก (Master Table) จะมี ID หรือ IDentifier เพื่อระบุรหัสประจำตัวของคน หรือสิ่งของ เช่น รหัสลูกค้า (อาจจะยึดตามบัตรประชาชน หรือเลขที่ผู้เสียภาษี) รหัสนักศึกษา หรือรหัสสินค้า เป็นต้น ซึ่งค่า ID จะไม่สามารถมีค่าที่ซ้ำกันได้ แต่สามารถเปลี่ยนแปลงค่าได้ (อาจจะมาจากการคีย์ข้อมูลผิด หรือต้องการเปลี่ยนแปลงในภายหลัง) ซึ่งค่าที่เปลี่ยนไปนั้นต้องไม่ไปซ้ำกับค่าอื่นๆที่มีอยู่แล้ว ยกเว้นค่าเดิมของตัวมันเอง


- ในตารางย่อย (Detail Table) จะต้องมี Primary Key เพื่อเชื่อมความสัมพันธ์กลับไปยังตารางหลัก แต่ไม่จำเป็นต้องมี IDentifier เช่น รหัสจังหวัด รหัสหน่วยนับ หรือรหัสประเภทสินค้า


การทำ Query MS Access ...


การกำหนด Maximum Length หรือความยาวสูงสุดในการป้อนค่าลง TextBox Control ตามจำนวนจากการออกแบบตารางข้อมูล ...

มาดูโค้ดในส่วนสำคัญของรายการลูกค้า (frmCustomerMain.vb) ... ส่วนของการแสดงผล และทำการค้นหา
  1.     Private Sub SearchData(Optional ByVal blnSearch As Boolean = False)
  2.         ' ดักค่าว่างกรณีที่ต้องการให้ค้นหา (blnSearch = True)
  3.         If blnSearch And Trim(txtSearch.Text) = "" Then Exit Sub

  4.         '/ เคลียร์ค่าใน DataSet ... นั่นก็คือ ลบรายการออกจาก DataGridView
  5.         DAS1.Clear()

  6.         strSQL = _
  7.             " SELECT tblCustomer.CustomerPK, tblCustomer.CustomerID, tblCustomer.CustomerName, " & _
  8.             " tblCustomer.PostCode, tblCustomer.Telephone, " & _
  9.             " tblCustomer.eMail, tblCustomer.LineID, tblCustomer.Facebook, tblProvince.ProvinceName " & _
  10.             " FROM tblCustomer INNER JOIN tblProvince ON tblCustomer.ProvinceFK = tblProvince.ProvincePK "

  11.         '/ การทำ Query เพื่อเลือกเฉพาะ Field ที่ต้องการค้นหามาเท่านั้น และแสดงผลฟิลด์หลัก
  12.         '/ เนื่องจากมันเป็นการ Bound Data Control ดังนั้นเราจึงต้องซ่อนหลักบางตัวเอาไว้ แต่การค้นหาก็ยังทำได้เหมือนเดิม
  13.         If blnSearch Then
  14.             strSQL = strSQL & _
  15.                 " WHERE " & _
  16.                 " [CustomerID] " & " Like '%" & Trim(txtSearch.Text) & "%'" & " OR " & _
  17.                 " [CustomerName] " & " Like '%" & Trim(txtSearch.Text) & "%'" & " OR " & _
  18.                 " [ProvinceName] " & " Like '%" & Trim(txtSearch.Text) & "%'" & " OR " & _
  19.                 " [PostCode] " & " Like '%" & Trim(txtSearch.Text) & "%'" & " OR " & _
  20.                 " [Telephone] " & " Like '%" & Trim(txtSearch.Text) & "%'" & " OR " & _
  21.                 " [eMail] " & " Like '%" & Trim(txtSearch.Text) & "%'" & " OR " & _
  22.                 " [LineID] " & " Like '%" & Trim(txtSearch.Text) & "%'" & " OR " & _
  23.                 " [Facebook] " & " Like '%" & Trim(txtSearch.Text) & "%'" & _
  24.                 " ORDER BY CustomerPK "
  25.         Else
  26.             strSQL = strSQL & " ORDER BY CustomerPK "
  27.         End If

  28.         '/ ยัดใส่ตารางที่มาจากการทำ Query ให้กับ DataAdapter
  29.         DAP1 = New OleDb.OleDbDataAdapter(strSQL, Conn)
  30.         DAP1.Fill(DAS1, "Customer")
  31.         ' / --------------------------------------------------------------------------------
  32.         ' / B O U N D --- D A T A --- C O N T R O L
  33.         ' / เหมาะสำหรับการค้นหาข้อมูล เพื่อนำมาแสดงผล
  34.         ' / Bind Data into DataGridView
  35.         dgvData.DataSource = DAS1.Tables("Customer")
  36.         ' / --------------------------------------------------------------------------------

  37.         ' ตั้งค่าคุณสมบัติ DataGridView (จริงๆแยกออกไปเป็นโปรแกรมย่อยน่าจะดีกว่าครับ)
  38.         With dgvData
  39.             .RowHeadersVisible = False
  40.             .AllowUserToAddRows = False
  41.             .AllowUserToDeleteRows = False
  42.             .AllowUserToResizeRows = False
  43.             .MultiSelect = False
  44.             .SelectionMode = DataGridViewSelectionMode.FullRowSelect
  45.             .ReadOnly = True
  46.             '// Data rows
  47.             .Font = New Font("Tahoma", 10)
  48.             .RowTemplate.MinimumHeight = 27
  49.             .RowTemplate.Height = 27
  50.             '// Column Header
  51.             .ColumnHeadersHeight = 30
  52.             .ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing
  53.             '// Autosize Column
  54.             .AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
  55.             '// Even-Odd Color
  56.             .AlternatingRowsDefaultCellStyle.BackColor = Color.Honeydew
  57.             ' ปรับรูปแบบ Header
  58.             With .ColumnHeadersDefaultCellStyle
  59.                 .BackColor = Color.Navy
  60.                 .ForeColor = Color.White
  61.                 .Font = New Font(dgvData.Font, FontStyle.Bold)
  62.             End With
  63.             ' หลัก 0 ซึ่งผมจะนำไปซ่อนเอาไว้ไม่ให้ผู้ใช้เห็น และปกติจะเป็นค่า Primary Key
  64.             .Columns("CustomerPK").Visible = False
  65.             .Columns("CustomerID").HeaderText = "รหัสลูกค้า"
  66.             .Columns("CustomerName").HeaderText = "ชื่อลูกค้า"
  67.             .Columns("Telephone").HeaderText = "เบอร์โทรศัพท์"
  68.             .Columns("ProvinceName").HeaderText = "จังหวัด"
  69.             '/ พวกที่ซ่อนหลักไว้ แต่ยังนำมาเป็นคีย์เวิร์ดเพื่อค้นหาได้
  70.             .Columns("PostCode").Visible = False
  71.             .Columns("eMail").Visible = False
  72.             .Columns("LineID").Visible = False
  73.             .Columns("Facebook").Visible = False
  74.         End With
  75.         lblRecordCount.Text = "[จำนวน : " & dgvData.RowCount & " รายการ.]"
  76.         txtSearch.Text = ""
  77.         dgvData.Focus()
  78.     End Sub

  79.     Private Sub txtSearch_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles txtSearch.KeyPress
  80.         If Trim(txtSearch.Text) = "" Or Len(Trim(txtSearch.Text)) = 0 Then Exit Sub
  81.         If e.KeyChar = Chr(13) Then '// Press Enter
  82.             '// No beep.
  83.             e.Handled = True
  84.             '/ ดักจับตัวอักขระอันไม่พึงปรารถนาสำหรับฐานข้อมูล เช่น ', * หรือ %
  85.             txtSearch.Text = Trim(txtSearch.Text).Replace("*", "").Replace("'", "").Replace("%", "")
  86.             '/ SearchData(True) หมายความว่า เป็นการค้นหาข้อมูล ดังนั้นจึงต้องใช้ True
  87.             Call SearchData(True)
  88.         End If
  89.     End Sub
คัดลอกไปที่คลิปบอร์ด


มาดูโค้ดในส่วนสำคัญของรายละเอียดลูกค้า (frmCustomerDetail.vb) ... ส่วนของการแสดงผลข้อมูล
  1.     ' / --------------------------------------------------------------------------------
  2.     Private Sub frmCustomerDetail_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
  3.         Me.CenterToScreen()
  4.         Me.KeyPreview = True    '/ สามารถใช้ KeyDown การกดปุ่มฟังค์ชั่นต่างๆบนฟอร์มได้ เช่น F8, F10
  5.         ' / เคลียร์หน้าจอในการแสดงผล
  6.         Call SetupScreen()

  7.         ' / รับค่า Public มาใส่ในตัวแปรแบบ Local แทน (เผื่อมีการเรียกใช้งานของฟอร์มอื่น)
  8.         NewData = blnNewData
  9.         ' / โหลดรายชื่อจังหวัดเข้ามา (หรือตารางย่อยอื่นๆ)
  10.         Call LoadProvince()
  11.         ' /
  12.         ' / การเพิ่มข้อมูล NewData = True
  13.         If NewData Then
  14.             '/ ------------------------------------------------------------------
  15.             '/ กำหนด Tag เป็นค่าว่าง เพื่อนำไปเปรียบเทียบกับ Text ตอนก่อนบันทึกข้อมูล
  16.             txtCustomerID.Tag = ""
  17.             chkAutoID.Enabled = True
  18.             chkAutoID.Checked = True
  19.             '/ ------------------------------------------------------------------
  20.             '/ NewData = False คือการแก้ไขข้อมูล
  21.         Else
  22.             '/ ------------------------------------------------------------------
  23.             ' / อ่านค่า Primary Key จากการเลือกในตารางกริด โดยอ้างถึงจากฟอร์มที่เรียกมันมา คือ frmCustomerMain
  24.             ' / โดยเราเอาข้อมูลหลักแรก (Index = 0) จาก DataGridView ที่เราซ่อนหลัก PK เอาไว้มาใช้งาน
  25.             PK = frmCustomerMain.dgvData.Item(0, frmCustomerMain.dgvData.CurrentRow.Index).Value
  26.             ' / นำข้อมูลมาแสดงผล
  27.             Call RecordToScreen()
  28.             chkAutoID.Enabled = False
  29.             chkAutoID.Checked = False
  30.             '/ ------------------------------------------------------------------
  31.         End If
  32.     End Sub
คัดลอกไปที่คลิปบอร์ด
  1.     ' / --------------------------------------------------------------------------------
  2.     ' / โปรแกรมย่อยในการนำข้อมูลจาก DataBase มาแสดงผล
  3.     ' / --------------------------------------------------------------------------------
  4.     Sub RecordToScreen()
  5.         strSQL = _
  6.             " SELECT tblCustomer.*, tblProvince.ProvinceName " & _
  7.             " FROM tblCustomer INNER JOIN tblProvince ON tblCustomer.ProvinceFK = tblProvince.ProvincePK " & _
  8.             " WHERE CustomerPK = " & PK & _
  9.             " ORDER BY CustomerPK "
  10.         Try
  11.             If Conn.State = ConnectionState.Closed Then Conn.Open()
  12.             DAP1 = New OleDb.OleDbDataAdapter(strSQL, Conn)
  13.             Dim DT As New DataTable
  14.             DAP1.Fill(DT)
  15.             txtCustomerID.Text = DT(0).Item("CustomerID").ToString()
  16.             '/ ------------------------------------------------------------------
  17.             '/ VERY IMPORTANT - ใจกลางความรู้สึกดีดี 5555+
  18.             '/ นำค่าเดิมจาก CustomerID.Text ไปเก็บไว้ที่ CustomerID.Tag
  19.             '/ โดยเราจะทำการเปรียบเทียบ 2 ค่าในเหตุการณ์ btnSave_Click
  20.             txtCustomerID.Tag = txtCustomerID.Text
  21.             '/ ------------------------------------------------------------------
  22.             With DT(0)
  23.                 txtCustomerName.Text = .Item("CustomerName").ToString()
  24.                 txtAddress.Text = .Item("Address").ToString
  25.                 txtAmphur.Text = .Item("Amphur").ToString
  26.                 txtPostCode.Text = .Item("PostCode").ToString
  27.                 txtTelephone.Text = .Item("Telephone").ToString
  28.                 txtFacsimile.Text = .Item("Facsimile").ToString
  29.                 txtContactPerson.Text = .Item("ContactPerson").ToString
  30.                 txtEmail.Text = .Item("Email").ToString
  31.                 txtLineID.Text = .Item("LineID").ToString
  32.                 txtFacebook.Text = .Item("Facebook").ToString
  33.                 '/ คือเอาค่าชื่อจังหวัดในตารางข้อมูล มาเปรียบเทียบกับค่าที่มีอยู่ใน ComboBox (ส่วนของ DisplayMember)
  34.                 cmbProvince.Text = .Item("ProvinceName").ToString
  35.             End With
  36.             DAP1.Dispose()
  37.             txtCustomerID.Focus()
  38.         Catch ex As Exception
  39.             MsgBox(ex.ToString())
  40.         End Try
  41.     End Sub
คัดลอกไปที่คลิปบอร์ด


มาดูโค้ดในส่วนสำคัญของรายละเอียดลูกค้า (frmCustomerDetail.vb) ... ส่วนของการบันทึกข้อมูล
  1.     ' / --------------------------------------------------------------------------------
  2.     ' / โปรแกรมย่อยในการบันทึกข้อมูล
  3.     ' / --------------------------------------------------------------------------------
  4.     Sub SaveData()
  5.         Try

  6.             '/ ------------------------------------------------------------------
  7.             '/ กรณีเพิ่มข้อมูลใหม่ NewData = True ต้องทำการ INSERT เข้าไปใหม่ก่อน
  8.             If NewData Then
  9.                 '/ ------------------------------------------------------------------
  10.                 '/ ต้องหาค่า Primary Key ใหม่อีกรอบ (เพื่อความมั่นใจ)
  11.                 '/ และตอนนี้ไม่ว่าจะเป็นการเพิ่มหรือแก้ไข ค่า PK จะเหมือนกันแล้ว
  12.                 strSQL = " SELECT MAX(tblCustomer.CustomerPK) AS MaxPK FROM tblCustomer "
  13.                 PK = SetupNewData(strSQL)
  14.                 '/ ------------------------------------------------------------------
  15.                 Using Cmd As New OleDb.OleDbCommand
  16.                     With Cmd
  17.                         .Connection = Conn
  18.                         .CommandType = CommandType.Text
  19.                         '/ ------------------------------------------------------------------
  20.                         '/ เลือกเฉพาะฟิลด์ที่สำคัญในการ INSERT มาก่อน ที่เหลือค่อย UPDATE ตามหลัง
  21.                         '/ เพื่อลดพารามิเตอร์ในการใช้งานทั้งการเพิ่ม และแก้ไขข้อมูลให้ใช้งานร่วมกันได้
  22.                         Cmd.CommandText = _
  23.                             " INSERT INTO tblCustomer (CustomerID, DateAdded, CustomerPK) VALUES (@CID, @DateAdded, @CPK)"
  24.                         With .Parameters
  25.                             .Add("@CID", OleDbType.VarChar).Value = txtCustomerID.Text
  26.                             .Add("@DateAdded", OleDbType.Date).Value = Now()
  27.                             '/ ------------------------------------------------------------------
  28.                             .Add("@CPK", OleDbType.Integer).Value = PK
  29.                             '/ ------------------------------------------------------------------
  30.                         End With
  31.                         '/ Insert new record.
  32.                         .ExecuteNonQuery()
  33.                         .Parameters.Clear()
  34.                         '/ ------------------------------------------------------------------
  35.                     End With
  36.                 End Using
  37.             End If

  38.             '/ ------------------------------------------------------------------
  39.             '/ เริ่มต้นทำการ UPDATE โดยใช้ได้ทั้งการเพิ่มและแก้ไขข้อมูล
  40.             '/ เหตุที่ผมเลือก Command Method มาใช้งาน
  41.             '/ เพราะตอนใช้งานจริงๆต้องมีการตรวจสอบข้อมูลก่อนการบันทึกเสมอ
  42.             '/ ซึ่งจะทำให้ง่ายในการดักค่าการตรวจสอบต่างๆครับผม
  43.             '/ ------------------------------------------------------------------
  44.             Using Cmd As New OleDb.OleDbCommand()
  45.                 With Cmd
  46.                     .Connection = Conn
  47.                     .CommandType = CommandType.Text
  48.                     .CommandText = _
  49.                         " UPDATE tblCustomer SET " & _
  50.                         " CustomerID=?, CustomerName=?, Address=?, Amphur=?, ProvinceFK=?, " & _
  51.                         " PostCode=?, Telephone=?, Facsimile=?, ContactPerson=?, EMail=?, LineID=?, Facebook=?, " & _
  52.                         " DateModified=? " & _
  53.                         " WHERE CustomerPK=? "
  54.                     With .Parameters
  55.                         .AddWithValue("@CID", txtCustomerID.Text.Trim)
  56.                         .AddWithValue("@CName", txtCustomerName.Text.Trim)
  57.                         .AddWithValue("@Address", txtAddress.Text.Trim)
  58.                         .AddWithValue("@Amphur", txtAmphur.Text.Trim)
  59.                         '/ ------------------------------------------------------------------
  60.                         ' / กรณีของ ComboBox ให้เอาค่า MemberValue มาใช้งาน (อันนี้ใน VB6 จะไม่มี)
  61.                         .AddWithValue("@ProvinceFK", cmbProvince.SelectedValue)
  62.                         '/ ------------------------------------------------------------------
  63.                         .AddWithValue("@PostCode", txtPostCode.Text.Trim)
  64.                         .AddWithValue("@Telephone", txtTelephone.Text.Trim)
  65.                         .AddWithValue("@Facsimile", txtFacsimile.Text.Trim)
  66.                         .AddWithValue("@ContactPerson", txtContactPerson.Text.Trim)
  67.                         .AddWithValue("@EMail", txtEmail.Text.Trim)
  68.                         .AddWithValue("@LineID", txtLineID.Text.Trim)
  69.                         .AddWithValue("@Facebook", txtFacebook.Text.Trim)
  70.                         .AddWithValue("@DateModified", FormatDateTime(Now(), DateFormat.GeneralDate))
  71.                         '/ ------------------------------------------------------------------
  72.                         .AddWithValue("@CPK", PK)
  73.                         '/ ------------------------------------------------------------------
  74.                     End With
  75.                     '/ UPDATE
  76.                     .ExecuteNonQuery()
  77.                     .Parameters.Clear()
  78.                 End With
  79.             End Using
  80.             MessageBox.Show("บันทึกข้อมูลเรียบร้อย.", "รายงานสถานะ", MessageBoxButtons.OK, MessageBoxIcon.Information)
  81.             '/ ------------------------------------------------------------------
  82.             ' ไม่ใช่ข้อมูลใหม่อีกต่อไป
  83.             NewData = False
  84.             '/ ส่งค่ากลับไปว่ามีการเปลี่ยนแปลงข้อมูล เพื่อสั่งให้รีเฟรชการแสดงผลใหม่ (จริงๆไม่จำเป็น)
  85.             FormUpDate = True
  86.             '/ ------------------------------------------------------------------
  87.             '/ หากไม่ปิดหน้าจอนี้ต้องกำหนดค่า CustomerID.Tag ใหม่
  88.             txtCustomerID.Tag = txtCustomerID.Text
  89.             '/ ปิดหน้าจอนี้
  90.             Me.Close()
  91.             '/ ------------------------------------------------------------------
  92.         Catch ex As Exception
  93.             MessageBox.Show(ex.Message)
  94.         End Try
  95.     End Sub
คัดลอกไปที่คลิปบอร์ด

ดาวน์โหลดโค้ดต้นฉบับแบบเต็ม VB.NET (2010) ได้ที่นี่ ...

ขออภัย! โพสต์นี้มีไฟล์แนบหรือรูปภาพที่ไม่ได้รับอนุญาตให้คุณเข้าถึง

คุณจำเป็นต้อง ลงชื่อเข้าใช้ เพื่อดาวน์โหลดหรือดูไฟล์แนบนี้ คุณยังไม่มีบัญชีใช่ไหม? ลงทะเบียน

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

0

กระทู้

1

โพสต์

50

เครดิต

Member

Rank: 2

เครดิต
50
โพสต์ 2021-5-13 12:10:27 | ดูโพสต์ทั้งหมด

มีประโบชน์มากเลยครับ
ขออภัย! คุณไม่ได้รับสิทธิ์ในการดำเนินการในส่วนนี้ กรุณาเลือกอย่างใดอย่างหนึ่ง ลงชื่อเข้าใช้ | ลงทะเบียน

รายละเอียดเครดิต

ข้อความล้วน|อุปกรณ์พกพา|ประวัติการแบน|G2GNet.com  

GMT+7, 2024-3-29 14:19 , Processed in 0.211508 second(s), 4 queries , File On.

Powered by Discuz! X3.4, Rev.62

Copyright © 2001-2020 Tencent Cloud.

ตอบกระทู้ ขึ้นไปด้านบน ไปที่หน้ารายการกระทู้