หากมีคำถาม ขอให้ไปโพสต์ลง เว็บบอร์ดจีทูจีเน็ตดอตคอม ตัวใหม่แทนน่ะครับ

หรือติดต่อเข้ามาทาง Inbox ที่ เฟซบุ๊ค ผมครับ

หน้าหลัก
ข่าวสาร - บทความ ทั้งหมด
VB 6/VB.Net
ASP/ASP.Net
จับฉ่ายคอมพิวเตอร์
เรียนรู้ผ่าน Flash Movie
บทความที่มีผู้ตอบล่าสุด  
 RSS Feeds
 ดาวน์โหลดโปรแกรม RSS Reader ได้ที่นี่ ...   Download โปรแกรม RSS Reader

Forum - www.g2gnet.com
Webmaster - www.g2gnet.com
Visitors - Session views
 5 1 2 8 5 1 2

7 ธันวาคม พ.ศ.2549
303 Users On-Line.
Visitors - Page views
 8 4 2 4 5 6 3
1 กุมภาพันธ์ พ.ศ.2551

Google   
เว็บ g2gnet.com
ขนาดตัวอักษร:  

การอ่านข้อมูลแบบ Text File เข้าสู่ MS Access ด้วย MS Visual Basic 6.0 ภาค 2

Category »  VB 6/VB.Net
โดย : Webmaster เมื่อ 5/4/2551 2:35:00
(อ่าน : 20211) 
สำหรับตอนที่ผ่านมา ประมาณว่าก็คงจะเป็นพื้นฐาน (แบบบ้านๆ) ให้พี่น้อง ได้มองเห็นการเชื่อมต่อกับ Text File ในลักษณะเสมือนกับว่ามันเป็นฐานข้อมูลตัวหนึ่ง อัศจรรย์ใจกันบ้างมั้ยล่ะครับพี่น้อง ... มาตอนนี้ก็ตามที่จั่วหัวเอาไว้แหละครับ ว่าผมแอบซุกซ่อนเทคนิคบางอย่างเอาไว้ รวมไปถึงเรื่องของวันที่เจ้าปัญหาที่มักจะเกิดกับ MS Access มาแทบจะรุ่นสู่รุ่นกันเลยทีเดียว ...
    เรื่องราวของตอนนี้จะเป็นการเพิ่มเติมบางอย่าง เพื่อให้โปรแกรมมันมีความยืดหยุ่นมากกว่าภาคที่แล้ว ...

  • ใช้ CommonDialog เพื่อเลือกเปิด Text File ตามที่ต้องการ แน่นอนว่าจะต้องทำการอ่านค่า
    1. ตำแหน่งที่เก็บไฟล์ หรือ Path เพื่อใช้ในการสร้าง Connection เช่น C:\TestVB\Sample\
      ดังนั้นต้องส่งค่ากับ strPath = "C:\TestVB\Sample\" ให้ได้
      
          Conn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
                 "Data Source=" & strPath & ";" & _
                 "Extended Properties=""text;HDR=NO;FMT=Delimited;"";"
      
    2. ชื่อไฟล์ ซึ่งจะเปรียบเสมือนเป็นตารางข้อมูล หรือ Table นั่้่นเอง เช่น Jan-2008.txt ดังนั้นต้องส่งค่ากับ strFile = "Jan-2008.txt" ให้ได้
      
          RS.Open "SELECT * FROM [" & strFile & "]", Conn, adOpenStatic, _
                              adLockReadOnly, adCmdText
      
  • การตรวจสอบข้อมูลด้วยว่ามันมีข้อมูลเดิมอยู่แล้วไม่ ด้วยการตรวจสอบรหัสพนักงาน วันที่ และ เวลา หากมีข้อมูลอยู่แล้วก็ให้ข้ามไปอ่านข้อมูลเข้ามาจาก Text File ใหม่ หากไม่มีข้อมูลก็ทำการบันทึกเข้าสู่ MS Access ... แน่นอนครับส่วนมากก็จะพบปัญหาของเรื่องการค้นหาด้วยวันที่ใน SQL Statement ... งั้นมาลองดูกัน

    การทำ Query เพื่อเปรียบเทียบค่าวันที่ใน MS Access 2000/2003


    ดูผลมันแล้ว ... ไม่น่าจะเป็นไปได้เลย แต่มันก็เป็นไปแล้ว ... 55555+
ดาวน์โหลด Source Code สำหรับ MS Visual Basic 6.0 - Service Pack 6
 ดาวน์โหลด Visual Basic 6.0 SP5: Run-Time Redistribution Pack
 ดาวน์โหลด Microsoft Data Access Object (MDAC) และ Jet 4.0 Update
 ดาวน์โหลด Microsoft Visual Basic Service Pack 6

' โปรแกรมย่อยเพื่อทำการเลือกไฟล์ที่ต้องการ
Private Sub cmdBrowse_Click()
On Error Resume Next ' ไม่สน Error ใดๆทั้งสิ้น
    With dlgOpenFile
        .DialogTitle = " เลือกเท็กซ์ไฟล์ - Text File Format " ' แสดง Title Bar
        .Filter = "Text File (*.txt) | *.txt" ' เลือก (Filter) เฉพาะไฟล์ txt
        .CancelError = True ' ยกเลิกทุกๆความผิดพลาด ไม่สนว่างั้นเหอะ ... พี่น้อง
        .ShowOpen ' เปิด Dialog ขึ้นมาเพื่อเลือกไฟล์
        .DefaultExt = "*.txt" ' ตั้งค่าเป็นมาตรฐานให้เลือกเฉพาะไฟล์ txt
    End With
    
    ' เลือกไฟล์ได้แล้วก็ให้นำไปใส่ไว้ใน TextBox แบบ Full Path เลย
    txtFilePath.Text = dlgOpenFile.FileName

End Sub

Private Sub cmdSaveData2MDB_Click()
' ตรวจสอบว่ามีชื่อไฟล์อยู่หรือไม่ ... ไม่มีก็เด้งออกจากโปรแกรมย่อยไปเลย ...
If txtFilePath.Text = "" Or Len(txtFilePath.Text) = 0 Then Exit Sub

Dim CountRec As Long
Dim StrData As String
Dim iRow, i As Long
Dim iArr As Variant
Dim StrTemp As String

' สมมุติว่าเราเก็บข้อมูลไว้ที่ C:\TestVB\Sample\Jan-2008.txt
' ดังนั้นต้องแยกออก 2 ส่วน คือ
' 1. หาตำแหน่ง Path เช่น C:\TestVB\Sample เพื่อนำไปใช้ในการกำหนด Data Source
Dim strPath As String

' 2. หาชื่อตาราง เช่น Jan-2008.txt (มอง TextFile เป็นตาราง)
Dim strFile As String
    
    Set Conn = New ADODB.Connection
    Set RS = New ADODB.Recordset
    
    ' ===================================================================================
    ' เริ่มการหา Path ให้กับ Data Source
    ' ตัวอย่าง C:\TestVB\Sample\Jan-2008.txt (มีความยาวทั้งสิ้น 29 ตัวอักขระ) หลักการก็คือ ...
    ' ให้นับจากทางขวามือเข้ามาจนเจอเครื่องหมาย \ (ตำแหน่งที่ 17) ก็ให้หยุดทันที
    ' ทำการเก็บค่า strPath = Left$(Path เต็มๆ, ความยาวที่เหลือของ i นั่นคือ i = 17)
    
    ' แบบที่ 1 - For ... Next
    ' นั่นคือ For i = 29 To 1 ลดค่าลงทีละ 1 ... จาก 29, 28, 27, ... 1
    For i = Len(txtFilePath) To 1 Step -1
        If Mid$(txtFilePath, i, 1) = "\" Then
            ' นับไปจากทางซ้ายมือตาม i = 17 ก็จะได้ C:\TestVB\Sample\
            strPath = Left$(txtFilePath, i)
            ' เด้งออกจาก For Loop ไปเลย ... หมดหน้าที่แล้ว ... 55555+
            Exit For
        End If
    Next
    
    ' แบบที่ 2 While - Wend
    'i = Len(txtFilePath.Text)
    'While Mid$(txtFilePath, i, 1) <> "\"
        ' ลดค่า i ... เพื่อที่จะนำค่า i ไปใช้งาน
    '    i = i - 1
    'Wend
    ' นับจากอักขระตัวแรกทางซ้ายไปจนเท่ากับความยาวของ i
    strPath = Mid$(txtFilePath, 1, i)
    
    ' รูปแบบการเชื่อมต่อแหล่งข้อมูล (Data Source) ของ Text File
    Conn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
           "Data Source=" & strPath & ";" & _
           "Extended Properties=""text;HDR=NO;FMT=Delimited;"";"
    ' ===================================================================================
    
    ' ===================================================================================
    ' เริ่มการหาชื่อไฟล์ หรือ มอง Text File ให้เป็นตารางข้อมูลครับ
    ' ตัวอย่าง C:\TestVB\Sample\Jan-2008.txt (มีความยาวทั้งสิ้น 29 ตัวอักขระ) หลักการก็คือ ...
    ' ให้นับจากทางขวามือเข้ามาจนเจอเครื่องหมาย \ (ตำแหน่งที่ 17) ก็ให้หยุดทันที
    ' แต่ในช่วงที่วนลูปอยู่นั้นต้องเก็บตัวอักษรที่อยู่ทางขวามือมาเรื่อยๆ จนกว่าจะเจอเครื่องหมาย \ น่ะครับผม
    'For i = Len(txtFilePath) To 1 Step -1
    '    If Mid$(txtFilePath, i, 1) <> "\" Then
    '        strFile = Mid$(txtFilePath, i, 1) & strFile
    '    Else
    '        Exit For
    '    End If
    'Next
    i = Len(txtFilePath.Text)
    While Mid$(txtFilePath, i, 1) <> "\"
        strFile = Mid$(txtFilePath, i, 1) & strFile
        i = i - 1
    Wend
    ' อัลกอริทึ่มตัวอย่างง่ายๆ ที่ผมกล่าวถึงนี้ ...
    ' ไม่ว่าคุณจะนำไปใช้กับภาษาใดๆก็ตามที ... แนวคิดมันแทบไม่เปลี่ยนไปเลยครับ ... พี่น้อง
    ' สิ่งเล็กๆน้อยๆแบบนี้ อย่ามองข้ามมันไปน่ะครับ ... พยายามหาโจทย์อื่นๆ แล้วหมั่นฝึกฝนดู

    ' ที่ว่ามาทั้งหมดทางด้านบน ... มีคำเฉลยอยู่ทางด้านล่างเด้อพี่น้อง
    
    RS.Open "SELECT * FROM [" & strFile & "]", Conn, adOpenStatic, _
                        adLockReadOnly, adCmdText
    CountRec = RS.RecordCount
    ' ใช้งานมันเป็นที่เรียบร้อยแล้ว ก็ปิดการเชื่อมต่อมันซ่ะ
    RS.Close:    Set RS = Nothing
    Conn.Close: Set Conn = Nothing
    ' ================= จบกระบวนการนับจำนวนข้อมูลที่ใช้ในการกำหนดแถวให้กับ MS FlexGrid =================
    
    ' ตั้งค่าให้กับ MS Flex Grid
    With fgData
        .Clear
        ' จำนวน 4 หลัก
        .Cols = 4
        ' กำหนดจำนวนแถว (Rows) ตามจำนวนรายการข้อมูลที่มีอยู่ทั้งหมด
        ' ให้เพิ่มจำนวนแถวขึ้นอีก 1 เนื่องจากมี Column Header อยู่อีก 1 แถวแล้ว
        .Rows = CountRec + 1
        
        .ColWidth(0) = 1200
        
        ' กำหนดค่าให้กับแถวแรก หรือ Column Header
        .TextMatrix(0, 0) = "ลำดับที่"
        .TextMatrix(0, 1) = "รหัสพนักงาน"
        .TextMatrix(0, 2) = "วันที่เข้า/ออก"
        .TextMatrix(0, 3) = "เวลาเข้า/ออก"
    End With
    
    ' เปิดข้อมูล Text File เพื่อทำการอ่านข้อมูลเข้าทีละบรรทัด
    Open txtFilePath For Input As #1
    
    ' เริ่มเปิดการเชื่อมต่อไฟล์ฐานข้อมูลใหม่ ... ก็ดึงตัวแปร Object เดิมแหละมาใช้งาน
    Set Conn = New ADODB.Connection
    Conn.ConnectionString = _
        "Provider=Microsoft.Jet.OLEDB.4.0;" & _
        "Data Source=" & App.Path & "\Attendance.mdb;" & _
        "Persist Security Info=False"
    Conn.Open
    
    iRow = 1    ' ให้เริ่มต้นแสดงผลข้อมูลจากแถวที่ 1 (แถวแรกน่ะคือ แถว 0 น่ะครับ ... พี่น้อง)

    ' ต้องเริ่มการวนรอบตามจำนวนของข้อมูล
    Do While iRow <= CountRec
        ' ต้องตรวจสอบก่อนว่า Text File นั้นมันหมดข้อมูลแล้วหรือยัง
        ' มิฉะนั้นจะเกิด Error หากไม่ดักไว้รอไว้ก่อนครับ
        If EOF(1) = True Then
            MsgBox "สิ้นสุดการอ่านข้อมูลจาก Text File.", vbOKOnly + vbExclamation, "รายงานสถานะ"
            Conn.Close: Set Conn = Nothing
            Close #1
            Exit Sub
        End If
        ' อ่านข้อมูลจาก Text File เข้ามาทีละบรรทัด
        Line Input #1, StrData
        StrTemp = Trim(StrData)
        ' แยกชุดตัวอักษรออกจากกันด้วยคำสั่ง Split
        ' โดยใช้เครื่องหมายช่องว่าง (Space) ในการจับแยกชุดตัวอักษร
        iArr = Split(StrTemp, " ")
        
        ' เริ่มต้นการบันทึกข้อมูล
        ' ต้องทำการตรวจสอบข้อมูลก่อน ... โปรดสังเกตรูปแบบวันที่ในการเปรียบเทียบค่า
        ' จาก MS Access แสดงว่าข้อมูลที่เก็บจริงๆ (ไม่ใช่การแสดงผลน่ะครับ) ...
        ' คือ mm/dd/yyyy ... หลายต่อหลายคนคงติดเรื่อง SQL ของวันที่ใน Access
        ' นี่แหละครับ คือ ขุมความลับที่สำคัญอีกตัวหนึ่ง ... เอาไปลองเล่นและพิจารณาดูเองเถิดครับ
        Set RS = New ADODB.Recordset
        Statement = "SELECT * FROM tblAttendance WHERE EmployeeID = " & "'" & iArr(0) & "'" & _
                                " AND JobDate = " & _
                                "#" & Left$(Format(iArr(1), "mm/dd/yyyy"), 2) & _
                                "/" & Mid$(Format(iArr(1), "mm/dd/yyyy"), 4, 2) & _
                                "/" & Right$(Format(iArr(1), "mm/dd/yyyy"), 4) - 543 & _
                                "#" & _
                                " AND JobTime = " & "#" & FormatDateTime(iArr(2), vbShortTime) & "#" & _
                                " ORDER BY EmployeeID "
        RS.CursorLocation = adUseClient
        RS.Open Statement, Conn, adOpenKeyset, adLockOptimistic, adCmdText
        ' หาก RS.RecordCount > 0 แสดงว่ามีข้อมูลเดิมอยู่ครับ
        If RS.RecordCount = 0 Then
            ' เสมือนปิดการเชื่อมต่อของเดิม แล้วเปิดการเชื่อมต่อใหม่
            ' อยากทำแบบนี้มีอะไรหรือเปล่าล่ะเนี่ย ... 55555+
            Set RS = New ADODB.Recordset
            Statement = "SELECT * FROM tblAttendance ORDER BY PK "
            RS.Open Statement, Conn, adOpenKeyset, adLockOptimistic, adCmdText
            RS.AddNew
            ' ต้องตรวจสอบหาค่า Primary Key ก่อน โดยเรียกผ่านฟังค์ชั่น CheckPK
            ' จากนั้นต้องส่งค่าแบบ Long Integer กลับมาเป็นค่า Primary Key ด้วย
            RS("PK") = CheckPK("tblAttendance", "PK")
            RS("EmployeeID") = "" & iArr(0)
            RS("JobDate") = "" & FormatDateTime(iArr(1), vbShortDate)
            RS("JobTime") = "" & FormatDateTime(iArr(2), vbShortTime)
            RS.Update
            
            ' แสดงใน MS FlexGrid
            fgData.TextMatrix(iRow, 0) = iRow
            fgData.TextMatrix(iRow, 1) = iArr(0)
            fgData.TextMatrix(iRow, 2) = iArr(1)
            fgData.TextMatrix(iRow, 3) = iArr(2)
            
            ' เพิ่มแถวใน MS FlexGrid ใหม่
            iRow = iRow + 1
            
        End If
        ' ปิดเลย
        RS.Close:   Set RS = Nothing
    Loop
    MsgBox "สิ้นสุดการอ่านข้อมูลจาก Text File.", vbOKOnly + vbInformation, "รายงานสถานะ"
    ' ใช้งานมันเป็นที่เรียบร้อยแล้ว ก็ปิดการเชื่อมต่อมันซ่ะ
    Conn.Close: Set Conn = Nothing
    ' ปิด Text File
    Close #1
    
End Sub
Conclusion:
การหาตำแหน่งของไฟล์ (Path) เพื่อใช้ในการสร้าง Connection แล้ว รวมไปถึงการหาชื่อไฟล์เพื่อกำหนดเป็นตาราง แท้ที่จริงแล้ว มันยังมีวิธีการง่ายๆ ดังนี้ คือ

Private Sub cmdBrowse_Click()
On Error Resume Next ' ไม่สน Error ใดๆทั้งสิ้น
    With dlgOpenFile
        .DialogTitle = " เลือกเท็กซ์ไฟล์ - Text File Format " ' แสดง Title Bar
        .Filter = "Text File (*.txt) | *.txt" ' เลือก (Filter) เฉพาะไฟล์ txt
        .CancelError = True ' ยกเลิกทุกๆความผิดพลาด ไม่สนว่างั้นเหอะ ... พี่น้อง
        .ShowOpen ' เปิด Dialog ขึ้นมาเพื่อเลือกไฟล์
        .DefaultExt = "*.txt" ' ตั้งค่าเป็นมาตรฐานให้เลือกเฉพาะไฟล์ txt
    End With
    
    ' เลือกไฟล์ได้แล้วก็ให้นำไปใส่ไว้ใน TextBox แบบ Full Path เลย
    txtFilePath.Text = dlgOpenFile.FileName
    ' เอาแต่เฉพาะชื่อไฟล์และนามสกุล มาใส่ไว้ในคุณสมบัติที่สำคัญของ TextBox อีกตัว คือ ...
    ' Tag ครับพี่น้อง ... งงล่ะซิ ... 55555+ ... เป็นเทคนิคของการประหยัดตัวแปรของผมแหละ
    txtFilePath.Tag = dlgOpenFile.FileTitle

End Sub

Private Sub cmdSaveData2MDB_Click()

    ' ...
    ' ...
    ' จากที่ว่ามาทั้งหมดของการหา Path และ ชื่อไฟล์ สามารถทำง่ายๆได้ประมาณนี้เอง ... 55555
    strPath = Left(txtFilePath.Text, Len(txtFilePath.Text) - Len(txtFilePath.Tag))
    strFile = txtFilePath.Tag
    ' ...
    ' ...

End Sub
ที่ผมให้โค้ดตามแบบแรกนั้น ก็เพื่อต้องการให้พี่น้องได้ลองคิด ลองฝึกดู ซึ่งมันเป็นอัลกอริทึม หรือแนวคิดตามแบบฉบับพื้นฐานทั่วไป การที่จะเป็นโปรแกรมเมอร์ที่ดีได้นั้น "เราต้องฝึกคิดที่จะเขียนโปรแกรม ไม่ใช่ฝึกฝนไปเพื่อแค่ใช้โปรแกรม" ... มิเช่นนั้นจะกลายสภาพเป็น GURU แต่ GUTUM ไม่ได้ ... 55555+
จี ทู จี เน็ต ดอต คอม - g2gNet Dot Com
เลขทะเบียนพาณิชย์อิเล็กทรอนิกส์ 0407314800231
CopyLeft © 2004 - 2099 g2gNet.Com All rights reserved.
Email: [email protected] หรือ โทร. 08-6862-6560