หากทำการ LINK TABLE จาก ODBC มายัง ACCESS แล้วมีการเรียกใช้ LINK TABLE ดังกล่าว ครั้งแรก ACCESS จะทำการถาม LOGIN, PASSWORD ที่จะไป CONNECT กับ DATABASE ที่เราทำ LINK ไว้ นอกจากจะถาม LOGIN PASSWORD เราแล้ว ยังให้เปลี่ยน DSN ของ ODBC ที่ตั้งไว้ได้ด้วย อาการแบบนี้ จะไปสร้าง ความเสี่ยง ให้ USER ไปเลือก DSN ตัวอื่นที่เราไม่ต้องการได้
วิธีที่ดีที่สุด คือการทำหน้าตา LOGIN ของเราขึ้นมา แล้วทำการ ต่อ CONNECTION ไปยัง ODBC รอไว้ก่อน ให้ใช้ CODE sysTestLogin ตามนี้ได้เลยครับ, ส่วน Sub testLogin ผมทำมาทดสอบ การ LOGIN นำไปปะที่ formLogin ได้เลย
ตย Code ที่แสดง เป็นการ Login ไป Oracle นะครับ ถ้าเป็นการ Connect ไปยัง SQL SERVER หรือ ODBC อื่นๆ การทำ ConnStr อาจแตกต่างกันไปครับ
Option Compare Database
Option Explicit
Sub testLogin()
If sysTestLogin("MYDB", "mydblogin", "xg1234") Then
'--- GOTO LOGIN PASS PROCESS
'
'
MsgBox "OK, LOGIN PASS"
Else
'--- GOTO LOGIN ERROR PROCESS
'
'
End If
End Sub
Function sysTestLogin(sysDSNName, sysLogin, sysPassword)
On Error GoTo log_error
Dim dbx As Database
Dim wkODBCDirect As Workspace
Dim x, ConnStr
ConnStr = "ODBC;DSN=" & sysDSNName & ";DBQ=" & sysDSNName & ";"
ConnStr = ConnStr & "UID=" & sysLogin & ";"
ConnStr = ConnStr & "PWD=" & sysPassword & ";"
Set wkODBCDirect = CreateWorkspace("", "", "", dbUseODBC)
Set dbx = wkODBCDirect.OpenDatabase("", dbDriverNoPrompt, True, ConnStr)
Set dbx = DBEngine(0).OpenDatabase("", dbDriverNoPrompt, False, ConnStr)
x = SysCmd(acSysCmdSetStatus, "LOGIN PASS !")
Set dbx = Nothing ' Close database but keep connection.
sysTestLogin = True
Exit Function
log_resume:
sysTestLogin = False
Exit Function
log_error:
MsgBox "ODBC Error: Initial connection error" & vbCrLf & vbCrLf & DBEngine.Errors(0) & vbCrLf & vbCrLf, vbExclamation
Resume log_resume
End Function
วันเสาร์ที่ 4 มิถุนายน พ.ศ. 2554
วันอาทิตย์ที่ 13 กุมภาพันธ์ พ.ศ. 2554
DB-102 DATABASE PROGRAMMING
หนังสือ DATABASE PROGRAMMING เขียนไว้นานแล้วครับ เป็นยุคที่มีการจัดอบรมโปรแกรมเมอร์กัน เยอะๆ บริษัทที่ผมทำงานอยู่ในยุคนั้น ก็จัดทำ COURSE นี้ด้วย ผมเห็นว่าการเขียน APPLICATION ด้วย VB ซึ่งสมัยนั้นก็เป็น VB6 ให้ออกมาเป็น APPLICATION งานฐานข้อมูล นั่น ค่อนข้างใช้เวลา แล้วทำให้ใช้งานจริงๆ ค่อนข้างยุ่งยาก
ในทางกลับกัน การใช้ ACCESS มาทำ เป็น APPLICATION แบบเต็มตัว ไม่ค่อยมีคนทำกัน ด้วยความที่บ้านเรา ส่วนใหญ่มอง MS ACCESS เป็นส่วนหนึ่งของชุด OFFICE หนังสือก็หายาก ท้ายที่สุด ก็ตัดสินใจ เขียนขึ้นมา เพื่อมาใช้ในโครงการอบรมโปรแกรมเมอร์ ที่ทางบริษัทจัดขึ้น
ภายหลัง เมื่อจบโครงการอบรม ผมก็ใช้ เอกสารชุดนี้ อบรม ให้ โปรแกรมเมอร์ ทั้งลูกน้องตัวเอง และ ทีมงานของลูกค้า ที่ต้องดูแล APPLICATION ที่ผมทำด้วย MS ACCESS เพื่อปูพื้นคนที่เป็น PROGRAMMER ให้ เข้ามาใช้ MS ACCESS ในการนำไปใช้เป็น TOOLS ในการพัฒนา โปรแกรมด้านฐานข้อมูล แทนที่จะใช้มันเป็น ฐานข้อมูลเฉยๆ
Donwload กันได้ ตามสะดวกครับ
DB-102 DATABASE PROGRAMMING
ที่เรียกว่า DB-102 เพราะมี DB-101 ด้วย แต่เป็นเนื้อหา MS ACCESS ตอนต้นๆ ที่เกี่ยวกับ การใช้งานACCESS ทั่วๆไป ก่อนจะมา CODING ฉบับ DB-101 ผมไม่ได้เป็นคน จึงไม่ได้มีมา POST กันครับ
ในทางกลับกัน การใช้ ACCESS มาทำ เป็น APPLICATION แบบเต็มตัว ไม่ค่อยมีคนทำกัน ด้วยความที่บ้านเรา ส่วนใหญ่มอง MS ACCESS เป็นส่วนหนึ่งของชุด OFFICE หนังสือก็หายาก ท้ายที่สุด ก็ตัดสินใจ เขียนขึ้นมา เพื่อมาใช้ในโครงการอบรมโปรแกรมเมอร์ ที่ทางบริษัทจัดขึ้น
ภายหลัง เมื่อจบโครงการอบรม ผมก็ใช้ เอกสารชุดนี้ อบรม ให้ โปรแกรมเมอร์ ทั้งลูกน้องตัวเอง และ ทีมงานของลูกค้า ที่ต้องดูแล APPLICATION ที่ผมทำด้วย MS ACCESS เพื่อปูพื้นคนที่เป็น PROGRAMMER ให้ เข้ามาใช้ MS ACCESS ในการนำไปใช้เป็น TOOLS ในการพัฒนา โปรแกรมด้านฐานข้อมูล แทนที่จะใช้มันเป็น ฐานข้อมูลเฉยๆ
Donwload กันได้ ตามสะดวกครับ
DB-102 DATABASE PROGRAMMING
ที่เรียกว่า DB-102 เพราะมี DB-101 ด้วย แต่เป็นเนื้อหา MS ACCESS ตอนต้นๆ ที่เกี่ยวกับ การใช้งานACCESS ทั่วๆไป ก่อนจะมา CODING ฉบับ DB-101 ผมไม่ได้เป็นคน จึงไม่ได้มีมา POST กันครับ
8 : RECORD ใน ACCESS
RECORD ใน ACCESS
วัตถุประสงค์
การเปิด Record ต่างๆ ของ TABLE / QUERY เพื่อจัดการข้อมูลภายในแบบทีละรายการ
เนื้อหา
บทนี้ผมจะพาท่านไปลองสัมผัสกับข้อมูลในแต่ละ Record โดยตรง มีงานด้าน database หลายๆ อย่างที่เราต้องเข้าไป สัมผัสข้อมูลด้วยโปรแกรม ทีละ Record ทีละ Field ด้วยโปรแกรมของเราเอง เช่นการอ่านข้อมูลรายการขาย มาตรวจสอบรหัสสินค้าว่าถูกต้อง ขาดเหลือหรือไม่ รายการไหนไม่สมบูรณ์ ให้พิมพ์ออกมาเป็นต้น การทำงานกับ RecordSet มีวิธีการยุ่งยากทีเดียวครับ ลองมาดูวิธีใช้งานดูครับ
เปิด RecordSet ไปทำไม
ก็เพื่อเข้าไปอ่านข้อมูลใน Table มาทีละรายการ เพื่อทำการตรวจสอบ สมมุติว่าเราอยากรู้ Supplier รายใดบ้างที่ขายสินค้าให้เราต่ำกว่า 2 รายการ ปกติ เราต้องนำ Table Supplier ไป Join กับ Product แล้วหา Count ที่น้อยกว่า 2 ต้องรำหลายกระบวนเพลงเลยละ แต่คราวนี้เราจะใช้ VBA แทนครับ
1 | Sub RecordSetScan() |
2 | Dim rst As Recordset |
3 | Dim x |
4 | Set rst = DBEngine(0)(0).OpenRecordset("Suppliers”) |
5 | |
6 | Do Until rst.EOF |
7 | x = DCount("*", "PRODUCTS", "SUPPLIERID = " & rst("SUPPLIERID")) |
8 | If x < 2 Then MsgBox rst("SUPPLIERID") & ":" & rst("COMPANYNAME") |
9 | rst.MoveNext |
10 | |
11 | Loop |
12 | Set rst = Nothing |
13 | |
14 | End Sub |
การทำงาน
- บรรทัดที่ 2 เราสร้างตัวแปรที่เป็น Recordset
- บรรทัดที่ 4 เป็นการเปิด Recordset ครับ มีหลายวิธีมาก แต่จำ Pattern นี้เลยก็ได้ครับ ให้สนใจตรงที่ “Suppliers” ค่าที่ใส่เป้นการระบุ SQL ที่จะไปหยิบตารางข้อมูลมาเป็น Recordset ให้เรา ตย นี้เป็นการใส่ชื่อ Table ตรงๆ เราจะใช้ ชื่อ Query ที่เราทำไว้ก็ได้ หรือ จะใส่เป็น SQL เลยก็ได้ เช่น “Select * from Suppliers” เป็นต้น อันนี้จะสะดวกในการ สร้าง SQL ได้ดั่งใจ หรือ เราจะ Where อะไรที่ซับซ้อนกว่าเป็น table หรือ query ธรรมดาได้ เช่น
ใช้ SQL ตรงๆ
Set rst = DBEngine(0)(0).OpenRecordset("Select * from Suppliers where Companyname like ‘A*’”)
ผ่านตัวแปรที่เตรียมไว้
Varx = Inputbox(“Enter supplier prefix “)
sqlstr = ("Select * from Suppliers where Companyname like ‘” & varX & “*’”
Set rst = DBEngine(0)(0).OpenRecordset(sqlstr)
- บรรทัดที่ 6 เริ่ม Loop ในการอ่านข้อมูล rst.eof เป็นการตรวจสอบว่า rst ไปถึงรายการสุดท้ายหรือยัง ( end of file จริงๆ น่าจะเป็น end of result มากกว่า ) แน่นอนว่ามาเจอบรรทัดนี้ครั้งแรก ก็น่าจะอยู่ที่ record แรกครับ ทั้งนี้ก็ขึ้นกับการ sort ของ SQL ที่เราเปิดด้วย อย่างกรณีนี้เรา SQL ของเราเป็น Table ตรงๆ ก็จะเรียงตาม Primary Key เป็นต้น ใน Database
- บรรทัดที่ 7-8 เป็นบริเวณที่เราเข้าไปทำธุระกับข้อมูลครับ เวลาที่เราเรียก rst(“ชื่อ filed”) เราจะได้ค่าของ Field นั้นออกมา แต่มาจาก Record ไหนละ ? อันนี้ก็ขึ้นอยู่กับว่าตอนนั้น Recordset มันชี้อยู่ที่ลำดับ Record ไหน
- บรรทัดที่ 9 เป็นการสั่งให้เลื่อนไป record ต่อไป จากนั้นก็เจอ Loop ที่บรรทัดที่ 11 กลับไปที่ บรรทัดที่ 6 ใหม่ ถ้าเจอว่าไม่มี Record แล้ว พอถึงบรรทัดที่ 6 มันก็จะกระเด็นมาที่ บรรทัดที่ 12
แน่นอนครับ ถ้าทำได้เท่าๆ กับการใช้ Query แล้ว จะทำไปทำไม ให้สังเกตุตรง บรรทัดที่ 7-8 ที่เราไปอ่านค่า Supplier มา แล้วไปใช้คำสั่ง dCount เพื่อไปหาว่า Product กี่ราย ที่ Supplier รายนี้ขายให้ บรรทัดที่ 8 ยังมีการตรวจสอบว่าต่ำกว่า 2 ไหม ถ้าต่ำกว่า ก็ msgbox ออกมาเป็นชื่อ Supplier รายนั้น ตรงบริเวณนี้ เราแทรกโปรแกรมได้ เพียบครับ จะมี if จะมี loop ได้อีกเพียบ หรือ จะสร้าง Text ไฟล์ ทำอะไรได้ตามแต่ความต้องการของเราเลยครับ เราสามารถหยิบจับข้อมูลมาตรวจสอบแก้ไขได้อิสระ
วิ่งไปวิ่งมา
RecordSet ที่เปิดแล้ว เราสั่งให้วิ่งไปวิ่งมาได้ 4 แบบคือ
MoveNext | สั่งให้ไป Record ถัดไป |
MovePrevious | สั่งให้ไป Record ก่อนหน้า |
MoveFirst | สั่งให้ไป Record แรก |
MoveLast | สั่งให้ไป Record สุดท้าย |
ตรวจสอบตำแหน่ง
มี function 3 ตัวที่ใช้บ่อยๆ ครับ
EOF | ตรวจว่าอยู่ rec. สุดท้ายหรือยัง ใช้คู่กับ movenext เพื่อดูว่า move ท้ายสุดหรือยัง |
BOF | ตรวจว่าอยู่ rec. แรกหรือยัง ใช้คู่กับ moveprevious เพื่อดูว่า move บนสุดหรือยัง ปกติไม่ค่อยได้ใช้มากครับ |
RECORDCOUNT | ตรวจว่ามี rst นี้มีกี่ record ปกติจะให้ค่าเป็น 0 ถ้าไม่มี record เลย แต่ถ้าอยากทราบจริงๆ ว่ามีกี่ record ขอให้ สั่ง movelast เสียก่อน แล้วค่อยอ่านค่า recordcount ไม่งั้นจะได้ค่าที่ผิด ตย ข้างล่างนี้จะบังคับป record สุดท้ายก่อน แล้วจึงอ่านจำนวน record Sub RecordSetSup() Dim rst As Recordset Set rst = dbEngine(0)(0).OpenRecordset("Suppliers") If rst.RecordCount = 0 Then MsgBox ("No Record Found") Set rst = Nothing Exit Sub End If rst.MoveLast MsgBox ("Total Record is: " & rst.RecordCount) rst.MoveFirst ‘—Do next command – ‘ End Sub |
แก้ไขข้อมูลผ่าน RECORDSET
นอกจากเราจะอ่านข้อมูลมาตรวจสอบได้แล้ส เรายัง Update ข้อมูลกลับไปได้ด้วยเช่นกัน อันนี้ก็จะแตกต่างจากการใช้ Action Query เพราะพวก Action Query จะเหมาะกับการทำเป็นชุด แต่ การใช้ Recordset จะยืดหยุ่นสูงกว่ามาก
การ Add ข้อมูล
การ Add ข้อมูลลงใน Table โดยใช้ Recordset สามารถทำได้ โดยการใช้คำสั่ง ADDNEW แล้วปิดท้าย ด้วยคำสั่ง Update การระบุค่าที่ต้องการ Add ก็เพียงแต่ ใส่ค่าลงใน Field ตามตัวอย่าง
rst.AddNew
rst(“SupplierName”) = “Mr. Amuro”
rst.Update
ทดลองดูการ Add ข้อมูลลงใน Table Products จำนวน 100 Record โดยการเปิด RecordSet สำหรับ การ Add โดยเฉพาะ
Sub AddTimeProduct()
Dim rst As Recordset
Dim i As Integer
Set rst = dbEngine(0)(0).OpenRecordset("Products”)
For i = 0 To 100
rst.AddNew
rst("ProductName") = "Add Number: " & i & " " & Format(Now, "dd/mm/bb hh:nn")
rst.Update
Next i
Set rst = Nothing
End Sub
การลบข้อมูล
การลบข้อมูลใน RecordSet ใช้คำสั่ง Delete ที่ขณะที่ ตำแหน่งของ Record อยู่ที่ Record ที่ต้องการลบ ทดลองดูตัวอย่างที่ใช้ในการลบข้อมูลที่ได้ทำการ Add ไว้ในตัวอย่างการ Add ข้อมูลข้างต้น โปรแกรมตัวนี้จะตรวจสอบที่ชื่อ ProductName หากมี คำว่า “Add Number “ ก็จะทำการลบ Record นั้นเสีย เพราะเป็นรายการที่เราได้ Add ไปเมื่อสักครู่นี้
Sub DeleteProduct()
Dim rst As Recordset
Dim i As Integer
Set rst = dbEngine(0)(0).OpenRecordset("Products", dbOpenDynaset)
Do Until rst.EOF
If rst("ProductName") Like "Add Number:*" Then
rst.Delete
End If
rst.MoveNext
Loop
Set rst = Nothing
End Sub
การแก้ไขข้อมูล
การแก้ไขข้อมูลบน RecordSet ใช้คำสั่ง EDIT แล้วตามด้วยคำสั่ง Update ในหว่าง EDIT และ Update เราจะกำหนดค่าที่ต้องการเปลี่ยนแปลงลงที่ ตัวแปร RecordSet วงเว็บชื่อ Field ที่ต้องการแก้ไข ซึ่งปกติ หากเราสั่งเปลี่ยนแปลงค่าที่ RecordSet โดยที่ไม่อยู่ในระหว่างคำสั่ง EDIT และ UPDATE จะเกิด Error ขึ้น
Sub ProductPriceAdjust()
Dim rst As Recordset
Dim i As Integer
Dim ratio
Set rst = dbEngine(0)(0).OpenRecordset("Products", dbOpenDynaset)
Do Until rst.EOF
Select Case rst("UnitPrice")
Case Is <= 5
ratio = 0.05
Case Is <= 10
ratio = 0.06
Case Is <= 20
ratio = 0.08
Case Is <= 50
ratio = 0.1
Case Is <= 100
ratio = 0.15
Case Is > 100
ratio = 0.2
End Select
rst.Edit
rst("UnitPrice") = rst("UnitPrice") * (1 + ratio)
rst.Update
rst.MoveNext
Loop
Set rst = Nothing
End Sub
ตัวอย่างโปรแกรมข้างต้นเป็นการ Update ราคาใน Table Product ซึ่งมีกลไกการ Update ตามขนาดราคาที่มีอยู่เดิม โดยเก็บค่าที่ต้องการขึ้นราคาไว้ใน Ratio แล้วนำไปเปลี่ยนราคา ระหว่างที่คำสั่ง EDIT และ UPDATE
ตย ข้างต้นจะเห็นชัดว่า เราทำอะไรกับ recordset ได้ซับซ้อนกว่า การใช้ query เราได้มีโอกาศทดสอบค่าในแต่ละ Record ในแต่ละ Field ก่อนทำการ Update ทำให้เราสามารถตัดสินใจเลือกเงื่อนไขที่เหมาะสมในการ Update ข้อมูล ในแต่ละ Record ได้ดีกว่า
การ Copy RecordSet จาก Form
ตามที่เราทราบว่า Form ก็ทำหน้าที่เปิด RecordSet อยู่เช่นกัน เราสามารถ Copy RecordSet จาก Form ได้โดยการใช้คำสั่ง RecordSetClone จาก Object Form ตัวอย่างต่อไปนี้ ใช้การอ้างอิงด้วย Me
Private Sub Form_Load()
Dim rst As Recordset
Set rst = Me.RecordsetClone
rst.MoveLast
MsgBox ("This form have : " & rst.RecordCount & " record.")
Set rst = Nothing
End Sub
เราสามารถอ้างอิง Me.RecordsetClone มาพักไว้ที่ Recordset ของเราเมื่อไรก็ได้ เมื่อเราได้ RecordSet แล้ว เราสามารถทำการบน RecordSet ตัวได้ได้อิสระ เช่นเดียวกับ RecordSet ทั่วไปทุกประการ
การสร้าง WEB PAGE จาก RECORDSET
ตัวอย่างนี้เป็นการแสดงให้เห็นการใช้ RecordSet ในการจัดการที่ซับซ้อน เช่นการ ใช้ RecordSet พิมพ์ Text ไฟล์ ที่มีโครงสร้างแปลก เป็นต้น ในส่วนนี้เราจะทดลองใช้ RecordSet ทำการสร้าง WEB page โดยใช้ Table Customer เป็นแหล่งข้อมูล
Sub WebGen()
Dim filex
Dim rst As Recordset
Set rst = dbEngine(0)(0).OpenRecordset("Customers")
filex = FreeFile
Open "C:\CUSTOMER.HTM" For Output As filex
Print #filex, "<HTML>"
Print #filex, "<BODY BGCOLOR = WHITE>"
Print #filex, "<Font Size = +4>CUSTOMER LIST</font><br>"
Print #filex, "<Font Size = +1>Generate from VBA Since: " & Now() & "</font><br>"
Print #filex, "<TABLE>"
Print #filex, "<TR BGCOLOR=#00007F>"
Print #filex, " <TD><FONT COLOR=#FFFFFF>CUSTOMERID</FONT></TD>"
Print #filex, " <TD><FONT COLOR=#FFFFFF>COMPANYNAME</FONT></TD>"
Print #filex, " <TD><FONT COLOR=#FFFFFF>CONTACT</FONT></TD>"
Print #filex, " <TD><FONT COLOR=#FFFFFF>PHONE</FONT></TD>"
Print #filex, " <TD><FONT COLOR=#FFFFFF>FAX</FONT></TD>"
Print #filex, "</TR>"
Do Until rst.EOF
Print #filex, "<TR BGCOLOR=#F6d6FF>"
Print #filex, " <TD>" & rst("CustomerID") & "</TD>"
Print #filex, " <TD>" & rst("CompanyName") & "</TD>"
Print #filex, " <TD>" & rst("ContactTitle") & " " & rst("ContactName") & "</TD>"
Print #filex, " <TD>" & rst("Phone") & "</TD>"
Print #filex, " <TD>" & rst("Fax") & "</TD>"
Print #filex, "</TR>"
rst.MoveNext
Loop
Print #filex, "</TABLE>"
Print #filex, "</HTML>"
Set rst = Nothing
Close
End Sub
ลองดูโปรแกรม ตย นี้ จะพบว่าไม่มีอะไรที่ซับซ้อน เพียงแต่ใช้การ LOOP ของ RECORDSET ในการพิมพ์ข้อมูลใน TABLE ออกมาเป็นไฟล์ HTML เท่านั้น การพิมพ์ก็ใช้ความสามารถในการจัดการไฟล์ ของ Access จากบทที่แล้ว ความยุ่งยากจะอยู่ที่การจัด TAG HTML ให้ลงตัวมากกว่า ไฟล์ที่ Gen ออกมา จะเป็น HTML ไฟล์ที่เป็นไปตาม Loop ที่เราสั่งพิมพ์ตามลำดับ และปิดท้ายด้วย TAG ตามปกติ หลายท่านที่เขียน ASP เป้น จะร้องอ๋อ ทันทีว่า ความจริง IIS ก็ทำงานแบบนี้นั่นเอง
บทส่งท้าย
บทความที่นำเสนอทั้ง 8 ตอน เป็นการนำเสนอการเขียนโปรแกรมใน Access แต่ผมพยายามคัดเนื้อหาที่สามารถเข้าใจความสามารถของ Access ในการพัฒนาโปรแกรมได้ง่ายออกมาเป็นหลัก และนำเสนอ tip ที่เห็นได้ชัดๆ เนื้อหาหลายๆ ส่วนจะไม่ได้มีโอกาศลงในรายละเอียดมากนัก ผมเองเข้าใจว่า ตำรา Access ที่มีอยู่ตลาดหลายๆ เล่มจะมีขายอยู่มาก เชื่อว่าทั้ง 8 บท คงจะเป็นประโยชน์ในการที่จะศึกษาเนื้อหา Access ในฐานนะ เครื่องมือในการพัฒนาได้ต่อไปนะครับ พบกันใหม่ในโอกาศต่อไปครับ
7: ACCESS กับไฟล์รอบตัว
ACCESS กับไฟล์รอบตัว
วัตถุประสงค์
แนะนำคำสั่งพิเศษใน Access ที่ใช้ในการติดต่อกับไฟล์ ต่างๆ การทำงานร่วมกับ ระบบปฏิบัติการ
เนื้อหา
บทนี้ผมจะพาท่านไปพบกับการใช้งาน ACCESS ในการติดต่อกับไฟล์ต่างๆ ในเครื่อง ต้องเรียนว่าความสามารถตรงนี้ เป็นความสามาารถ VB แท้ของ ACCESS ครับ แต่เราใช้ประโยชน์บ่อย เช่นต้องเขียนโปรแกรมสร้าง Text ไฟล์ เงินเดือน ให้ธนาคาร โปรแกรม Import Text ไฟล์มาเข้า Database หรือ แม้กระทั่ง การดูแล Web Site ที่ต้องการสร้าง Web Page เยอะๆ แบบ อัตโนมัติ
การทำงานกับ File
ขอใช้พื้นที่เล็กๆ ตรงนี้ แนะ คำสั่งสำหรับใช้งานติดต่อกับไฟล์ในระบบกันก่อนนะครับ
คำสั่งเกี่ยวกับ File
§ Dir
เป็นคำสั่งสำหรับค้นหา File หรือ List ไฟล์ เหมือนกับ Dir บน Dos มีรูปแบบคำสั่งคือ
=Dir[(pathname[, attributes])]
คำสั่งนี้มี tip นิดหน่อย คือตอนเราสั่งครั้งแรก จะต้องระบุ File ที่ต้องการค้นหา โดยระบุเป็น String patแบบเดียวกับที่ใช้บน Dos เช่น “C:\*,MDB” เป็นต้น เมื่อทำสั่งครั้งแรกแล้ว คำสั่ง Dir ครั้งต่อๆไป ไม่ต้องมีการใส่ค่า pathname อีก Dir จะใช้ Pathname เดิม แล้วค้นหารายการต่อไป ส่วน attributes เป็นค่า Paramter ที่ใช้ระบุสิ่งที่ต้องการจะหา ดูตามตารางได้เลยครับ
ค่าคงที่ของ Attribute | ค่าจริง | คำอธิบาย |
vbNormal | 0 | ไม่ระบุการค้นหาพิเศษ จะ Scan เฉพาะไฟล์ปกติ |
VbHidden | 2 | ระบุให้รวม ไฟล์ที่เป็นสถานะ Hidden ด้วย |
VbSystem | 4 | ระบุให้รวม System ไฟล์ เพื่อการค้นหาด้วย |
VbVolume | 8 | สำหรับต้องการอ่านชื่อ Volume label ของ Disk |
VbDirectory | 16 | สำหรับค้นหาเฉพาะ Directory |
ค่า Paramter ที่กำหนด สามารถกำหนดพร้อมกัน หลายๆค่าได้ เนื่องจากเป็นเลขฐาน 2 สมมุติว่าต้องการค้นหาไฟล์ ทั้งที่เป็น Hidden และะ System File จะใช vbNormal + vbHidden + vbSystem
ตัวอย่างการอ่านชื่อไฟล์ใน C:\
Sub GetCFile()
Dim tmpStr, i
i = 0
tmpStr = Dir("C:\*.*")
Do Until tmpStr = ""
i = i + 1
Debug.Print tmpStr
tmpStr = Dir
Loop
MsgBox ("Total: " & i & " files")
End Sub
ตัวอย่างข้างต้นจะหาชื่อไฟล์ทั้งหมด แล้วพิมพ์ออกที่ Debug Windows ทำเสร็จแล้วลงกด ctrl+G ดูนะครับ หากต้องการให้มีการ Scan ทั้ง Hidden และ System ไฟล์ จะใช้
tmpStr = Dir("C:\*.*",vbNormal + vbHidden + vbSystem)
ตัวอย่างการอ่านชื่อ Volume จะต้องระบุชื่อ Dir ตามตัวอย่าง
MsgBox (Dir("C:", vbVolume))
§ FileDatetime
ใช้สำหรับตรวจสอบวันที่ของ File Return ค่าเป็นวันที่
=FileDateTime(PathName)
ระบุชื่อ File ลงที่ pathName ตัวอย่างการอื่น วันที่ของ C:\COMMAND.COM
Sub GetFileDatetime
Dim tmpDate
TmpDate =FileDateTime(“C:\Command.Com”)
Msgbox(TmpDate)
End Sub
§ FileLen
ใช้สำหรับตรวจสอบขนาดของ File ค่าที่ Return เป็น Long Integer หน่วนเป็น Byte
=FileLen(PathName)
ระบุชื่อ File ลงที่ pathName ตัวอย่างการอื่น วันที่ของ C:\COMMAND.COM
Dim tmpSize
TmpSize =FileLen(“C:\Command.Com”)
Msgbox(TmpSize)
§ FileCopy
เป็นคำสั่งสำหรับ Copy File เหมือนคำสั่ง Copy บน Dos ไม่สามารถใช้ WildCard ได้นะครับ มี 2 Input คือ File ต้นทาง และ File ปลายทาง
Filecopy SrcPathName , DestPathName
ตัวอย่างการ Copy ไฟล์จาก C:\ ไปไว้ที่ tmpBackup
Sub CopyAuto()
Dim tmpStr
On Error Resume Next
MkDir "C:\tmpBackup"
On Error GoTo 0
tmpStr = Dir("C:\*.*")
Do Until tmpStr = ""
FileCopy "C:\" & tmpStr, "C:\tmpBackup\" & tmpStr
tmpStr = Dir
Loop
End Sub
§ Kill
เป็นคำสั่งสำหรับลบ File สามารถระบุเป็น wild card ได้ ควรระมัดระวังในการใช้งาน เพราะหากสั่งไม่ดี อาจลบทั้ง Directory ได้
Kill PathName ( Wild Card Allow )
ตัวอย่างการลบ File ที่ได้ทำไว้ในตัวอย่างไฟล์ Copy
Sub KillAuto()
Dim tmpStr
tmpStr = Dir("C:\tmpBackup\*.*")
Do Until tmpStr = ""
Kill "C:\tmpBackup\" & tmpStr
tmpStr = Dir
Loop
End Sub
การเรียกโปรแกรมอื่นๆ
บ่อยครั้งที่ เราต้องบังคับโปรแกรมของเรให้ออกไปเรียกโปรแกรมอื่นๆ ขึ้นมาทำงานต่อเนื่องจากโปรแกรมที่เราทำงานอยู่ เช่น ทำการ Copy ข้อมูลแล้ว ก็จะต้องทำการ Zip ไฟล์ และ Copy ไปลงที่ Drive A เป็นต้น ตรงนี้เราอาจต้องเรียก Bat ไฟล์ที่ทำไว้
§ Shell
ใช้สำหรับเรียกโปรแกรมอื่นให้มาทำงาน มีรูปแบบคำสั่งคือ
Shell(pathname[,windowstyle])
PathName เป็นชื่อโปรแกรมที่ต้องการเรียก ส่วน WindowStyle เป็นการระบุสถานะ Windows ของ Application ที่ถูกเรียก
Constant | Value | Description |
VbHide | 0 | เรียก Application แต่ให้อยู่ใน Hide Mode ไม่ถูก Focus |
VbNormalFocus | 1 | ทำงานโดยถูก Focus จากระบบ และอยู่ใน Mode Windows ปกติ |
VbMinimizedFocus | 2 | อยู่ในสถานะ Minimize ( Icon ) แต่ได้รับ Focus |
VbMaximizedFocus | 3 | อยู่ในสถานะ Maximize และได้รับ Focus |
VbNormalNoFocus | 4 | เปิด Windows ขึ้นมาทำงาน โดยใช้สถานะ Windows ตามปกติ แต่ไม่ต้อง Focus |
VbMinimizedNoFocus | 6 | อยู่ในสถานะ Minimize ( Icon ) และไม่ได้รับ Focus |
การเรียกด้วยคำสั่ง Shell ติดกัน Access จะประมวณผลต่อเนื่อง ไม่เหมือนกับ BAT ไฟล์บน Dos ที่ประมวลผลที่ละคำสั่ง หากเรากำลังใช้ Shell ไปเรียก Application ที่ทำงานต่อเนื่องกัน อาจเกิดปัญหาได้ เพราะลำดับที่ทำก่อหน้า ตัวอย่างเช่น การทำ Zip ไฟล์ต่อไปนี้
Sub TestBatX()
Dim x
x = Shell("pkunzip a:test.zip c:\tmp", VbNormalFocus)
x = Shell("command.com /crename C:\tmp\test.mdb test2.mdb", VbNormalFocus)
End Sub
ชุดโปรแกรมนี้ ไม่สามารถทำการ Rename ไฟล์ได้ เนื่องจาก เมื่อ Access เรียก pkunzip แล้ว จะไป บรรทัดต่อไปทันที คือการ Rename ซึ่ง โปรแกรม Unzip ยังอาจทำงานไม่เสร็จ
วิธีแก้ปัญหากรณีดังกล่าว ควรทำ Bat ไฟล์ที่เก็บคำสั่งทั้ง 2 ไว้ แล้วเรียก Bat ไฟล์นี้ เพียงครั้งเดียว
Sample.BAT
-----------------
pkunzip a:test.zip c:\tmp
rename C:\tmp\test.mdb test2.mdb
-----------------
Sub TestBatX()
Dim x
x = Shell("sample.bat", VbNormalFocus)
End Sub
§ AppActivate
ใช้สำหรับเรียกโปรแกรมที่ Run แล้ว ซึ่งจะสังเกตุจาก TaskBar ให้ขึ้นมาเป็น Application ที่รับ Focus แทน เราต้องมีการเรียก Applicationดังกล่าว ด้วย Shell ก่อนเสมอ เพราะถ้าเราเรียก AppActivate โดยไม่มี Application มาก่อน อาจเกิด Error ได้
AppActivat title[,wait])
Title เป็นชื่อโปรแกรมที่ต้องการเรียก เป็นชื่อที่ปรากฎบน TaskBar ส่วน wait เป็นการระบุให้ Application ที่เรียกได้รับ Focus ทันทีWindowStyle เป็นการระบุสถานะการอ เป็น True หรือ False เป็นการบอกให้ Application ที่ถูกเรียกได้รับ Focus ทันที ( False เป้นค่า Default หากไม่ระบุ ) หรือ รอให้ Windows ของผู้เรียก ได้รับ Focus ก่อน แล้วจึง ให้ Windows ของ Application ได้รับ Focus (True )
Sub TestAppActivate()
Dim x
On Error Resume Next
AppActivate "Calculator"
If Err Then
x = Shell("Calc.exe")
AppActivate "Calculator"
End If
End Sub
ตัวอย่างข้างต้น จะทำการทดสอบการ Activate โดยไม่ระบุการ Shell ก่อน เผื่อว่า Calculator ได้รับการ Run แล้ว หาก พบว่า Error จะทำการเรียก Shell ก่อน แล้วเรียก AppActivate อีกครั้ง
การอ่านเขียน File
โดยปกติ Utilities ที่มา Access ก็เพียงพอในการ Convert Text ไฟล์ได้ แต่ในสถานะการณ์จริง เราพบว่าของที่มากับ Access จะใช้ดิบๆ ตรงๆ ไม่ค่อยได้ จำเป็นมากมาก ที่เราต้องอ่านเขียน ไฟล์เองเป็น การอ่านเขียนก็จะเริ่มจากการเปิดไฟล์ ซึ่งต้องเริ่มจากการ ขอเปิดไฟล์ผ่าน Function Freefile ของ Access เพื่อขอเลขที่ไฟล์ที่ทำการเปิด หลังจากนั้นเวลาที่เราทำอะไรกับไฟล์ ก็จะอ้างเลขทีนี้ เวลาเปิดไฟล์ขึ้นมา ไม่ว่า จะอ่านหรือ เขียน อย่าลืมปิดทุกครั้งนะครับ คำสั่งในการเปิดคือ
Open [filename] For [mode] As [fileno]
[mode] มี 3 แบบคือ
- Input: เปิดเพื่ออ่าน,
- Output: สร้างไฟล์ใหม่ ถ้ามีแล้วให้ทับไฟล์เดิม
- Append: เปิดมาเพื่อเพิ่มรายการ จากเดิมทีมีอยู่แล้ว
Mode: input
ตัวอย่างข้างล่างเป็นการเปิด Text ไฟล์ AUTOEXEC.BAT มาอ่านค่าในไฟล์นะครับ สำหรับท่านที่มช้ XP คงไม่มี autoexec.bat แล้ว ลองเปลี่ยนเป็น c:\boot.ini ก็ได้นะครับ ส่วนผลก็แสดงที่ debug windows
Sub ReadAutoExec()
Dim Filex, tmpStr
Filex = FreeFile
Open "C:\AUTOEXEC.BAT" For Input As Filex
Do Until EOF(Filex)
Line Input #Filex, tmpStr
Debug.Print (tmpStr)
‘--- another process
‘
‘
Loop
Close Filex
End Sub
- ขั้นตอนตามปกติในการเปิดไฟล์คือ
. อ่านค่า FreeFile มาเก็บไว้ในตัวแปร เพื่อให้เราทราบว่า ตอนนี้เราได้ลำดับที่ File ที่เท่าไร
. ใช้คำสั่ง Open ในการเปิด ระบุชื่อ File ตามด้วย Mode ที่การเปิดในที่นี้ คือการ Input และระบุลำดับที่ File
. ทำการ Do loop โดยใช้ ฟังก็ชั่น EOF ซึ่งจะต้องระบุเลขที่ลำดับไฟล์ที่ขอจากระบบ ในที่ก็คือค่าที่เก็บไว้ใน Filex
. ใช้คำสั่ง Line Input ในการอ่านไฟล์เข้ามาพักไว้ในตัวแปร ที่ละบรรทัด
. นำตัวแปร ซึ่งขณะที่เก็บข้อมูลในแต่ละบรรทัดที่อ่านได้ไว้ไปทำการต่อ
. ปิดไฟล์ เมื่อทำงานเรียบร้อย
Mode: Output
สำหรับขั้นตอนการสร้างไฟล์ใหม่ ก็ใช้วิธีการเดียวกัน เพียงแต่เปลี่ยน Mode การ Open จาก Input เป็น Output และ ใช้คำสั่ง Print แทนคำสั่ง Write ทดลองดูตัวอย่างต่อไปนี้ เป็นการ อ่าน File Autoexec.bat หรือ Boot.ini มาสร้างเป็น WebPage
Sub GenAutoExecHtm()
Dim Filex, FileHtm, tmpStr, I
Filex = FreeFile
Open "C:\AUTOEXEC.BAT" For Input As Filex
FileHtm = FreeFile
Open "C:\AUTOEXEC.HTM" For Output As FileHtm
Print #FileHtm, "<HTML>"
Print #FileHtm, "<BODY BGCOLOR = WHITE>"
Print #FileHtm, "<Font Size = +3>Your Autoexec.bat is</font><br>"
Print #FileHtm, "<TABLE>"
i = 1
Do Until EOF(Filex)
Line Input #Filex, tmpStr
Print #FileHtm, "<TR><TD>" & i & "): </TD><TD> " & tmpStr & "</TD></TR>"
i = i + 1
Loop
Print #FileHtm, "</TABLE>"
Print #FileHtm, "</BODY>"
Print #FileHtm, "</HTML>"
Close Filex
Close FileHtm
End Sub
Mode: Append
Append ต่างกับ Output ตรงที่ Append จะไม่ลบไฟล์เดิม เมื่อสั่ง Print จะทำการ Write ข้อมูลต่อจากไฟล์เดิม แต่คำสั่งต่างๆ เหมือนกันครับ
สร้าง Database เก็บรายชื่อไฟล์
เราจะเอาคำสั่งต่างๆที่แนะนำไป มาสร้างโปรแกรมที่ค้นหารายชื่อไฟล์ใน Directory ที่ต้องการพร้อมกับ ขนาดไฟล์ กันดูนะครับ ก่อนอื่น ขอให้สร้าง Table ชื่อ FILELIST มี 2 FIELD ครับ คือ FILENAME เป็น TEXT(255), FileSize เป็น Double ใช้ ฟิลด์ FILENAME เป็น Primary Key ก็ได้นะครับ
.
Sub genFilelist()
Dim SDir
Dim x
SDir = InputBox("Enter Folder Name")
If SDir = "" Then
MsgBox "Nothing to search "
Exit Sub
End If
x = Dir(SDir & "\*.*", vbDirectory + vbHidden + vbSystem)
DBEngine(0)(0).Execute "delete from filelist"
Do Until x = ""
DBEngine(0)(0).Execute "insert into FileList(filename, filesize) " & _
" values('" & x & "'," & FileLen(SDir & "\" & x) & ")"
x = Dir
Loop
End Sub
โปรแกรมนี้จะถาม Directory ที่ต้องการหาขนาดไฟล์ จากนั้นก็ใช้คำสั่ง Dir แต่มีการต่อ *.* เข้าไปเพื่อให้หาไฟล์ทุกๆ ไฟล์ ทำการลบข้อมูลเดิมทิ้งก่อน รายการไฟล์จะได้จากคำสั่ง Dir ไฟล์ที่หาเจอ ก็นำไปเพิ่มใน Table FILELIST เราใช้ Filelen ในการอ่านขนาด
ลองทำต่ออีกนิดนะครับ แทนที่จะเพิ่มข้อมูลอย่างเดียว ลองนำไปสน้างเป็น HTML แบบตัวอย่างในการ Gen ไฟล์ด้วยก็ได้นะครับ
สมัครสมาชิก:
บทความ (Atom)