Title Forum
IndexIndex  CalendarCalendar  GalleryGallery  Trợ giúpTrợ giúp  Tìm kiếmTìm kiếm  Đăng kýĐăng ký  Đăng NhậpĐăng Nhập  
News & Announcements
  • Gallery & Others
  • Top posters
 N.H.M (706)
 nhuantrung0210 (323)
 TjaGoChangLj (227)
 GVRFnu-Bjn (190)
 lisaidong (122)
 phongngan1997 (94)
 puppy:x* (85)
 anhcudo01 (69)
 taoghetmay (68)
 anhlathe47 (45)
Similar topics

Share | 
 

 Chương Mười Lăm - Lập trình với kỹ thuật DAO †(Học visual basic Nâng Cao)†

Xem chủ đề cũ hơn Xem chủ đề mới hơn Go down 
Tác giảThông điệp
TjaGoChangLj
Administrator
Administrator


Thanked : 14


Bài gửiTiêu đề: Chương Mười Lăm - Lập trình với kỹ thuật DAO †(Học visual basic Nâng Cao)†   16/6/2011, 1:59 pm

Khóa Hàm Thụ Visual Basic 6.0


Chương Mười Lăm - Lập trình với kỹ thuật DAO




Reference DAO


Trong bài nầy ta sẽ học những cách lập trình căn bản với MS Access database qua kỹ thuật DAO mà không
cần dùng đến Control Data như trong bài trước. Ta sẽ cần đến vài Objects trong thư viện DAO, do đó nếu bạn mở một
dự án VB6 mới thì hãy dùng Menu Command Project | References... để chọn Microsoft DAO 3.51 Object Library
bằng cách click cái checkbox bên trái như
trong hình dưới đây. (Một cách để nhớ tên của Object nầy là nhớ câu "thằng cha cua ĐÀO 35 con dê").
<blockquote></blockquote>
Sau đó trong code của Form chính ta sẽ declare variable myDatabase cho một instance của DAO database
variable myRS cho một DAO recordset.
Ở đây ta nói rõ Database và Recordset là thuộc loại DAO để phân biệt với Database và Recordset thuộc loại ADO (ActiveX Data
Object)
sau nầy. Để ý là Intellisense giúp ta trong lúc viết code:
<blockquote></blockquote>
Bây giờ bạn hãy đặt lên Form chính, tên frmDAO, 4 labels với captions: Title, Year Published, ISBNPublisher ID. Kế đó cho thêm
4 textboxes tương ứng và đặt tên chúng là txtTitle, txtYearPublished, txtISBNtxtPublisherID.

Điều ta muốn làm là khi Form mới được loaded, nó sẽ lấy về từ database một Recordset chứa tất cả records trong table Titles
theo thứ tự về mẫu tự (alphabetical order) của field Title và hiển thị record đầu tiên.

Dùng keyword SET


Chuyện trước hết là mở một Database Object dựa vào tên đầy đủ (full path name) của Access database:
<blockquote>
' Open main database
Set myDB = OpenDatabase(AppFolder & "BIBLIO.MDB")
</blockquote>
Để ý chữ Set trong câu code trên. Đó là vì myDB là một Pointer đến một Object. Mặc dầu từ rày về sau ta sẽ dùng myDB
như một Database theo cách giống như bất cứ variable
thuộc data type nào khác, nhưng khi chỉ định lần đầu là nó từ đâu đến thì ta dùng chữ Set, để
nói rằng thật ra myDB không phải là Object Database, nhưng là Pointer đến Object Database. Điểm nầy càng nói đến càng khó hiểu.

Đại khái là VB6 runtime dynamically allocates (dành ra cho khi cần) một
phần trong bộ nhớ (memory) để chứa Object Database khi ta nhận được nó
từ
execution của Method OpenDatabase. Dầu vị trí chỗ chứa Object Database trong bộ nhớ không nhất định, nhưng vì ta nắm cái cán chỉ đến vị trí ấy
nên ta vẫn có thể làm việc với nó một cách bình thường. Cái cán ấy là value (trị số) của variable myDB. Vì value
nầy không phải là Object, nhưng nó chứa memory address chỉ đến (point to hay refer to) Object Database, nên ta gọi nó là Pointer.


Lập trình dùng Pointer
nói chung rất linh động là hiệu năng trong các ngôn ngữ như C, Pascal,
C++ ,v.v.. Tuy nhiên, lập trình viên phải nhớ trả lại Operating System
phần memory
mình dùng khi không còn cần nó nữa để Operating System lại allocate cho
Object khác. Nếu công việc quản lý dùng lại memory không ổn thỏa thì có
những mảnh
memory nằm lang bang mà Operating Sytem không biết. Lần lần Operating
System sẽ không còn memory dư nữa. Ta gọi
hiện tượng ấy là memory leakage (rỉ). Các ngôn ngữ sau nầy như
Java, C# đều không dùng Pointer nữa. Visual Basic không muốn lập trình
viên
dùng Pointer. Chỉ trong vài trường hợp đặc biệt VB6 mới lộ ra cho ta
thấy thật ra ở trong hậu trường VB6 Runtime dùng Pointer, như trong
trường hợp nầy.

Tương tự như vậy, vì Recordset là một Pointer đến một Object, ta cũng dùng Set khi chỉ định một DAO Recordset lấy về từ Method OpenRecordset của database myDB.
<blockquote>
'Open recordset
Set myRS = myDB.OpenRecordset("Select * from Titles ORDER BY Title")
</blockquote>
Cái parameter loại String ta dùng cho method OpenRecordset là một Lệnh (Statement) SQL. Nó chỉ định cho database lấy tất cả mọi
fields (columns) (Select *) của mỗi record từ Table Titles (from Titles) làm một Recordset và sort các records trong Recordset ấy theo alphabetical order của field
Title (ORDER BY Title).

Nhớ là Recordset nầy cũng giống như property Recordset của một Control Data mà ta dùng trong bài trước. Bây giờ có
Recordset rồi, ta có thể hiển thị chi tiết của record đầu tiên nếu Recordset ấy có ít nhất một record. Ta kiểm
tra điều ấy dựa vào property RecordCount của Recordset như trong code dưới đây:
<blockquote>
Private Sub Form_Load()
' Fetch Folder where this program EXE resides
AppFolder = App.Path
' make sure it ends with a back slash
If Right(AppFolder, 1) <> "" Then AppFolder = AppFolder & ""
' Open main database
Set myDB = OpenDatabase(AppFolder & "BIBLIO.MDB")
'Open recordset
Set myRS = myDB.OpenRecordset("Select * from Titles ORDER BY Title")
' if Recordset is not empty then display the first record
If myRS.RecordCount > 0 Then
myRS.MoveFirst ' move to first record
Displayrecord ' display details of current record
End If
End Sub
</blockquote>
Sau khi dùng method MoveFirst của Recordset để position current record ở Record đầu tiên, ta hiển thị trị số các
fields của record bằng cách assign chúng vào các textboxes của Form như sau:
<blockquote>
Private Sub Displayrecord()
' Assign record fields to the appropriate textboxes
With myRS
' Assign field Title to textbox txtTitle
txtTitle.Text = .Fields("Title")
txtYearPublished.Text = .Fields("[Year Published]")
txtISBN.Text = .Fields("ISBN")
txtPublisherID.Text = .Fields("PubID")
End With
End Sub
</blockquote>
Để ý vì field Year Publshed gồm có hai chữ nên ta phải đặt tên của field ấy giữa hai dấu ngoặc vuông ([]). Để
tránh bị phiền phức như trong trường hợp nầy, khi bạn đặt tên database field trong lúc thiết kế một table
hãy dán dính các chữ lại với nhau, đừng để rời ra. Thí dụ như dùng YearPublished thay vì Year Published.

Các nút di chuyển


Muốn có các nút Navigators tương đương với của một Control Data, bạn hãy đặt lên Form 4 buttons mang tên CmdFirst, CmdPrevious,
CmNext
CmdLast với captions: <<, <, >, >>.

Code cho các nút nầy cũng đơn giản, nhưng ta phải coi chừng khi user
muốn di chuyển quá record cuối cùng hay record đầu tiên. Ta
phải kiểm tra xem EOF có trở thành True khi user click CmdNext, hay BOF có trở thành True khi user click CmdPrevious:
<blockquote>
Private Sub CmdNext_Click()
myRS.MoveNext ' Move to next record
' Display record details if has not gone past the last record
If Not myRS.EOF Then
Displayrecord ' display details of current record
Else
myRS.MoveLast ' Move back to last record
End If
End Sub

Private Sub CmdPrevious_Click()
myRS.MovePrevious ' Move to previous record
' Display record details if has not gone past the first record
If Not myRS.BOF Then
Displayrecord ' display details of current record
Else
myRS.MoveFirst ' Move back to first record
End If
End Sub

Private Sub CmdFirst_Click()
myRS.MoveFirst ' Move back to first record
Displayrecord ' display details of current record
End Sub

Private Sub CmdLast_Click()
myRS.MoveLast ' Move back to last record
Displayrecord ' display details of current record
End Sub
</blockquote>
Khi chạy chương trình bạn sẽ thấy nó hiển thị chi tiết của Record đầu
tiên khác với trong bài trước đây vì các records đã được sorted:
<blockquote></blockquote>
Bạn hãy thử dùng các Navigator buttons cây nhà, lá vườn của mình xem chúng làm việc có đúng không.

Tới đây, không biết bạn có để ý là dù user có vô tình sửa đổi một chi tiết nào trong các textboxes,
không có record nào bị cập nhật hóa trong database khi user di chuyển từ record nầy đến record khác. Lý do
là các Texboxes không có Data Bound với các Fields của Recordset.
Thêm bớt các Records


Giống như chương trình trong bài rồi, ta sẽ thêm phương tiện để thêm (add), bớt (delete) các
records. Bây giờ bạn hãy để vào Form 5 buttons tên: cmdEdit, cmdNew, cmdDelete, cmdUpdatecmdCancel.

Chỗ nào trong chương trình trước ta dùng Data1.Recordset thì bây giờ ta dùng myRS.

Ta sẽ dùng lại Sub SetControls với parameter Editing có trị số False hay True tùy theo user đang Browse
hay Edit. Trong Browse mode, các Textboxes bị Locked (khóa) và
các nút cmdUpdatecmdCancel trở nên bất lực. Trong Edit mode, các Textboxes được unlocked (mở khóa) và
các nút cmdNew, cmdDeletecmdEdit trở nên bất lực.

Vì ở đây không có Data Binding nên đợi cho đến khi Update (cập nhật hóa) ta mới đặt Recordset vào AddNew hay Edit mode.
Do đó ta chỉ cần nhớ là khi user edits là đang Edit một record hiện hữu hay thêm một Record mới. Ta chứa
trị số Boolean ấy trong variable AddNewRecord. Nếu user sắp thêm một record mới thì AddNewRecord = True,
nếu User sắp Edit một record hiện hữu thì AddNewRecord = False.

Ngoài ra, khi User sắp thêm một record mới bằng cách click nút New thì ta phải tự clear (làm trắng) hết các
textboxes bằng cách assign Empty string vào text property của chúng như sau:
<blockquote>
' If Editing existing record then AddNewRecord = False
' Else AddNewRecord = true
Dim AddNewRecord As Boolean

Private Sub ClearAllFields()
' Clear all the textboxes
txtTitle.Text = ""
txtYearPublished.Text = ""
txtISBN.Text = ""
txtPublisherID.Text = ""
End Sub

Private Sub cmdNew_Click()
' Remember that this is Adding a new record
AddNewRecord = True
' Clear all textboxes
ClearAllFields
' Place controls in Edit Mode
SetControls (True)
End Sub

Private Sub CmdEdit_Click()
' Place controls in Edit Mode
SetControls (True)
' Remember that this is Editing an existing record
AddNewRecord = False
End Sub
</blockquote>
Nếu user clicks Cancel trong khi đang edit các textboxes, ta không cần gọi method CancelUpdate vì Recordset
chưa bị đặt vào AddNew hay Edit mode. Ở đây ta chỉ cần hiển thị lại chi tiết của current record, tức là
hủy bỏ những gì user đang đánh vào:
<blockquote>
Private Sub CmdCancel_Click()
' Cancel update
SetControls (False)
' Redisplay details or current record
Displayrecord
End Sub
</blockquote>
Lúc user clicks Update, bạn có dịp để kiểm tra data xem có field nào bị bỏ trống (nhất là Primary Key ISBN
bắt buộc phải có trị số) hay có gì không valid bằng cách gọi
Function GoodData. Nếu GoodData trả lại một trị số False thì ta không xúc tiến với việc Update.
Nếu GoodData trả về trị số True thì ta đặt Recordset vào AddNew hay Edit mode tùy theo trị số của Boolean variable
AddNewRecord.

Giống như khi hiển thị chi tiết của một Record ta phải assign từng Field
vào textbox, thì bây giờ khi Update ta phải làm ngược lại,
tức là assign property Text của từng textbox vào Record Field tương ứng.
Sau cùng ta gọi method Update của
recordset và cho các controls trở lại Browse mode:
<blockquote>
Private Function GoodData() As Boolean
' Check Data here. If Invalid Data then GoodData = False
GoodData = True
End Function

Private Sub CmdUpdate_Click()
' Verify all data, if Bad then do not Update
If Not GoodData Then Exit Sub
' Assign record fields to the appropriate textboxes
With myRS
If AddNewRecord Then
.AddNew ' Place Recordset in AddNew Mode
Else
.Edit ' Place Recordset in Edit Mode
End If
' Assign text of txtTitle to field Title
.Fields("Title") = txtTitle.Text
.Fields("[Year Published]") = txtYearPublished.Text
.Fields("ISBN") = txtISBN.Text
.Fields("PubID") = txtPublisherID.Text
' Update data
.Update
End With
' Return controls to Browse Mode
SetControls (False)
End Sub
</blockquote>
Cũng vì không có Data Binding, nên khi User Delete một record, sau khi di chuyển qua record kế tiếp ta phải tự hiển thị
chi tiết của record đó như sau:
<blockquote>
Private Sub CmdDelete_Click()
On Error GoTo DeleteErr
With myRS
' Delete new record
.Delete
' Move to next record
.MoveNext
If .EOF Then .MoveLast
' Display details of current record
Displayrecord
Exit Sub
End With
DeleteErr:
MsgBox Err.Description
Exit Sub
End Sub
</blockquote>
Tìm một record


Tiếp theo đây, ta muốn liệt kê các sách có tiêu đề chứa một chữ hay câu nào đó, thí dụ như chữ "Guide".
Kế đó user có thể chọn một sách bằng cách select tiêu đề sách ấy và click nút Go. Chương trình sẽ locate (tìm ra)
record của sách ấy và hiển thị chi tiết của nó.

Bây giờ bạn hãy cho vào Form một textbox tên txtSearch và một Image tên ImgSearch. Kế đó
đặt một frame tên fraSearch vào Form. Để lên frame nầy một listbox tên List1 để hiển thị tiêu đề các sách, và hai buttons
tên CmdCloseCmdGo, với caption Close và Go. Sau khi select một sách trong List1, user sẽ click nút Go để hiển thị
chi tiết sách ấy. Nếu đổi ý, user sẽ click nút Close để làm biến mất frame fraSearch.

Bình thường frame fraSearch chỉ hiện ra khi cần, nên lúc đầu hãy set property Visible của nó thành False.
Ta sẽ cho ImgSearch hiển thị hình một ống dòm nên bạn hãy click vào bên phải property Picture trong Properties Window
để chọn Icon BINOCULR.ICO từ folder E:\Program Files\Microsoft Visual Studio\Common\Graphics\Icons\Misc:




Cái Primary Key của table Titles là ISBN. Khi user select một
sách ta muốn biết ISBN của sách ấy để locate
(định chỗ) nó trong Recordset myRS. Do đó trong khi thêm tiêu đề của
một sách vào List1,
ta đồng thời thêm ISBN của sách ấy vào một Listbox thứ hai tên List2. Ta
chỉ sẽ dùng List2 sau hậu trường, nên hãy set property Visible của nó
thành
False. Dưới đây là code để load tiêu đề sách và ISBN vào các Listboxes:

Private Sub ImgSearch_Click()
' Show Search Frame
fraSearch.Visible = True
Dim SrchRS As DAO.Recordset
Dim SQLCommand As String
' Define SQL statement
SQLCommand = "Select * from Titles where Title LIKE '" & "*" & txtSearch & "*" & "' ORDER BY Title"
' Fetch all records having Title containing the text pattern given by txtSearch
Set SrchRS = myDB.OpenRecordset(SQLCommand)
' If Recordset is not Empty then list the books' titles in List1
If SrchRS.RecordCount > 0 Then
List1.Clear ' Clear List1
' We use List2 to contain the Primary Key ISBN corresponding to the books in List1
List2.Clear ' Clear List2
With SrchRS
' Iterate through the Recordset until EOF
Do While Not SrchRS.EOF
' Display Title in List1
List1.AddItem .Fields("Title")
' Store corresponding ISBN in List2
List2.AddItem .Fields("ISBN")
.MoveNext ' Move to next record in the Recordset
Loop
End With
End If
End Sub

Khi user Click ImgSearch với text pattern là chữ Guide, ta sẽ thấy hình dưới đây:
<blockquote></blockquote>
Trong SELECT statement bên trên ta dùng operator LIKE trên text pattern, chữ Guide, có
wildcard character (*) ở hai bên. Wildcard character là chỗ có (hay không có) chữ gì cũng được.
Trong trường hợp nầy có nghĩa là hễ có chữ Guide trong tiêu đề sách là được, không cần biết nó nằm ở đâu.
Ngoài ra sự chọn lựa nầy Không có Case Sensitive, tức là chữ guide, Guide hay GUIDE đều được cả.

Khi user clicks nút Go, ta sẽ dùng method FindFirst của Recordset myRS để định chỗ của record có trị số Primary Key
là hàng text trong List2 tương ứng với tiêu đề dược chọn trong List1 như sau:
<blockquote>
Private Sub CmdGo_Click()
Dim SelectedISBN As String
Dim SelectedIndex As Integer
Dim Criteria As String
' Index of line selected by user in List1
SelectedIndex = List1.ListIndex
' Obtain corresponding ISBN in List2
SelectedISBN = List2.List(SelectedIndex)
' Define Search criteria - use single quotes for selected text
Criteria = "ISBN = '" & SelectedISBN & "'"
' Locate the record, it will become the current record
myRS.FindFirst Criteria
' Display details of current record
Displayrecord
' Make fraSearch disappeared
fraSearch.Visible = False
End Sub
</blockquote>
Lưu ý là trong string Criteria, vì ISBN thuộc loại text, chớ không phải là một con số, nên ta phải
kẹp nó giữa hai dấu ngoặc đơn.
Bookmark


Khi di chuyển từ record nầy đến record khác trong Recordset, đôi khi ta muốn đánh dấu vị trí của
một record để có dịp sẽ trở lại. Ta có thể thực hiện điều ấy bằng cách ghi nhớ Bookmark của
Recordset.

Thí dụ khi user clicks nút Go, ta muốn nhớ vị trí của record lúc ấy để sau nầy quay trở lại khi User clicks nút
Go Back. Bạn hãy thêm vào Form một button tên CmdGoBack với Caption Go Back.
Ta sẽ thêm một variable tên LastBookmark loại data type Variant:
<blockquote>
Dim LastBookMark As Variant
</blockquote>
Lúc đầu
button CmdGoBack invisible, và chỉ trở nên visible sau khi user clicks nút Go. Ta thêm các hàng codes sau vào Sub
CmdGo_Click() như sau:
<blockquote>
' Remember location of current record
LastBookMark = myRS.BookMark
CmdGoback.Visible = True
</blockquote>
Dưới đây là code để quay trở lại vị trí current record trước đây trong Recordset:
<blockquote>
Private Sub CmdGoback_Click()
' Reposition record to last position
myRS.BookMark = LastBookMark
' Redisplay details or current record
Displayrecord
End Sub
</blockquote>
LastModified


LastModified là vi trị của record vừa mới được sửa đổi hay thêm vào trong Recordset. Để thử điều nầy
bạn hãy thêm một button invisible tên CmdLastModified với caption là Last Modified. Button nầy chỉ hiện ra sau khi user clicks
Update. Bất cứ lúc nào bạn Click nút CmdLastModified, record mới vừa được sửa đổi hay thêm vào sẽ hiển thị:
<blockquote>
Private Sub CmdLastModified_Click()
' Reposition record to last position
myRS.BookMark = myRS.LastModified
' Redisplay details or current record
Displayrecord
End Sub
</blockquote>
Dưới đây là hình của Form lúc đang được thiết kế:
<blockquote></blockquote>


Bạn có thể tải về chương trình nầy từ đây DAOPRJ.zip. Nhớ copy MS Access file BIBLIO.MDB, tức là database, vào
trong cùng folder của chương trình trước khi chạy thử.

Ta sẽ học kỹ thuật ADO (ActiveX Data Object) trong bài tới.
Chữ Ký Cá Nhân

Về Đầu Trang Go down
Xem lý lịch thành viên
 

Chương Mười Lăm - Lập trình với kỹ thuật DAO †(Học visual basic Nâng Cao)†

Xem chủ đề cũ hơn Xem chủ đề mới hơn Về Đầu Trang 
Trang 1 trong tổng số 1 trang

Permissions in this forum:Bạn không có quyền trả lời bài viết
Vn-Screen Forum :: Công Nghệ Thông Tin :: Khu Lập Trình :: Visual Basic-
VN-SCREEN.DARKBB.COM
Design by N.H.M - Developed by Vn-Screen Member
Free forum | © phpBB | Free forum support | Liên hệ | Report an abuse | Sosblogs.com