Giáo trình Nhập môn hệ quản trị cơ sở dữ liệu - Nguyễn Kim Sao (Phần 2)
CHƢƠNG 7: LẬP TRÌNH CƠ SỞ DỮ LIỆU TRONG MS ACCESS
1. Giới thiệu lập trình Visual Basic Application
MS Access không chỉ đơn thuần là một hệ quản trị cơ sở dữ liệu (CSDL) quan hệ mà
nó còn cung cấp một môi trƣờng lập trình với các công cụ khá đầy đủ, dễ sử dụng để
phát triển các ứng dụng quản lý vừa và nhỏ.
Ngôn ngữ lập trình đƣợc phát triển trong MS Access là Access Basic. Tuy nhiên từ
phiên bản MS Access for Windows 95, Access Basic đƣợc thay thế bởi Visual Basic
(VB). Hai ngôn ngữ này khá giống nhau và đều đƣợc phát triển từ một thành phần
thiết kế chung. Nhƣng ngày nay, VB trở thành ngôn ngữ lập trình chung của chƣơng
trình ứng dụng MS Office bao gồm: Access, Excel, Word, PowerPoint và đƣợc gọi là
VBA (Visual Basic for Applications). Việc có đƣợc một ngôn ngữ lập trình chung
xuyên suốt mọi chƣơng trình ứng mang lại một số lợi điểm quan trọng là:
Tóm tắt nội dung tài liệu: Giáo trình Nhập môn hệ quản trị cơ sở dữ liệu - Nguyễn Kim Sao (Phần 2)
131 CHƢƠNG 7: LẬP TRÌNH CƠ SỞ DỮ LIỆU TRONG MS ACCESS 1. Giới thiệu lập trình Visual Basic Application MS Access không chỉ đơn thuần là một hệ quản trị cơ sở dữ liệu (CSDL) quan hệ mà nó còn cung cấp một môi trƣờng lập trình với các công cụ khá đầy đủ, dễ sử dụng để phát triển các ứng dụng quản lý vừa và nhỏ. Ngôn ngữ lập trình đƣợc phát triển trong MS Access là Access Basic. Tuy nhiên từ phiên bản MS Access for Windows 95, Access Basic đƣợc thay thế bởi Visual Basic (VB). Hai ngôn ngữ này khá giống nhau và đều đƣợc phát triển từ một thành phần thiết kế chung. Nhƣng ngày nay, VB trở thành ngôn ngữ lập trình chung của chƣơng trình ứng dụng MS Office bao gồm: Access, Excel, Word, PowerPoint và đƣợc gọi là VBA (Visual Basic for Applications). Việc có đƣợc một ngôn ngữ lập trình chung xuyên suốt mọi chƣơng trình ứng mang lại một số lợi điểm quan trọng là: Ngƣời lập trình chỉ cần biết một ngôn ngữ lập trình để tùy biến, phát triển ứng dụng. Dễ dàng hợp nhất các đối tƣợng trong các chƣơng trình ứng dụng. VBA là ngôn ngữ có một số đặc điểm: Không phân biệt chữ hoa, thƣờng Hƣớng sự kiện và hƣớng đối tƣợng Việc tổ chức chƣơng trình theo mô hình hƣớng đối tƣợng và hƣớng sự kiện khiến cho các mã lệnh của chƣơng trình, suy cho đến cùng nhất, chỉ đƣợc gọi khi có sự kiện (event) nào đó xảy ra trên các đối tƣợng (object) cụ thể. Sự kiện của các đối tƣợng đƣợc sinh ra có thể do ngƣời dùng tác động chuột/bàn phím vào điều khiển. Ví dụ sự kiện OnClick() của điều khiển Button trên form. Sự kiện cũng có thể đƣợc sinh ra trong quá trình biên dịch. Ví dụ sự kiện Load() của một form. Tuy nhiên, không phải bất kỳ đối tƣợng nào cũng có các sự kiện. Các đối tƣợng là các điều khiển (control) đƣơng nhiên có các sự kiện. Ví dụ TextBox, CommandButton, Form, đều có các sự kiện; trong khi đó đối tƣợng DBEngine lại không thể có sự kiện nào. Nhƣ vậy, toàn bộ mã lệnh của chƣơng trình ứng dụng Access đƣợc tổ chức là các hàm/thủ tục (function/sub) độc lập, bình đẳng (chúng ta sẽ phân biệt hàm và thủ tục trong phần sau). Không có hàm/thủ tục nào là cha, chứa các hàm/thủ tục khác. Không có “điểm vào” của chƣơng trình. Nghĩa là, không có hàm/thủ nào đƣợc chƣơng trình gọi trƣớc nhất để từ đó gọi đến các hàm/thủ tục khác. Tất cả các hàm/thủ tục chỉ đƣợc gọi để đáp ứng các sự kiện tƣơng ứng hoặc đƣợc gọi tƣờng minh trong hàm/thủ tục khác. 132 Chƣơng này sẽ trình bày các nội dung sau: Module và Access Class Object Các kiểu dữ liệu, hằng và biến Các cấu trúc điều khiển Hàm và thủ tục Các mô hình truy cập CSDL 2. Module Module là một đối tƣợng nguyên thủy của môi trƣờng lập trình VBA. Toàn bộ mã lệnh VBA trong CSDL đƣợc lƣu trong module dƣới dạng các thủ tục (gồm hàm và thủ tục con). Các thủ tục này có thể độc lập hoặc liên quan đến form/report. Nói cách khác, module là một phƣơng tiện của MS Access để giúp ngƣời lập trình tổ chức mã nguồn của họ sao cho “gọn gàng”, dễ kiểm soát. Ví dụ, ngƣời lập trình nên gom các đoạn mã (hàm/thủ tục) làm việc với CSDL vào một module đặt tên là DataAccessModule, gom các đoạn mã là việc với form vào một module đặt tên là FormModule hay nên viết ra một lớp Student (Class Module) để làm việc với các bản ghi thuộc bảng Student trong CSDL, MS Access 2013 cung cấp 03 loại module: module chuẩn (Standard Module), module lớp (Class Module) và module gắn với form/report (Form/Report Module) Standard module chủ yếu bao gồm tập các hàm/thủ tục. Mỗi hàm/thủ tục này đƣợc gọi từ các hàm/thủ tục khác hoặc từ sự kiện của đối tƣợng hay điều khiển. Khi đó, toàn bộ mã lệnh của chƣơng trình đƣợc tổ chức thành các đơn vị hàm/thủ tục. Các đơn vị hàm/thủ tục này đƣợc gom lại trong một hoặc một số Standard Module để giúp lập trình viên dễ quản lý mã lệnh của mình hơn. Class module thực chất là một lớp do ngƣời dùng định nghĩa. Mỗi Class Module là một lớp của ngƣời dùng có tên chính là tên của Class Module. Lớp của ngƣời dùng định nghĩa cũng đƣợc đối xử bình đẳng nhƣ các lớp đã đƣợc định nghĩa bởi hệ thống (built-in language class). Điều quan trọng ở đây là bạn phải biết khi nào dùng Standard Module và khi nào dùng Class Module hay cả hai. Nó phụ thuộc vào cách thiết kế ứng dụng của bạn. Nếu ứng dụng của bạn đƣợc tổ chức theo kiểu “hƣớng chức năng” (phần mềm là một tập các chức năng có quan hệ với nhau) thì bạn sẽ có xu hƣớng sử dụng Standard Module nhiều hơn. Nếu ứng dụng của bạn đƣợc thiết kế theo mô hình lập trình “phân lớp” (03 lớp chẳng hạn: giao diện, logic, truy cập dữ liệu) thì bạn sẽ đƣơng nhiên sẽ sử dụng Class Module nhiều hơn. Sau đây là chi tiết về các loại module. 133 2.1 Module chuẩn (Standard Module) Module này chứa các biến, thủ tục con có thể đƣợc gọi từ query, form, report, macro, biểu thức, thủ tục khác hoặc từ bất cứ đâu trong chƣơng trình ứng dụng. Nhƣ vậy, ta có thể viết trong Standard Module các nội dung sau đây: Các khai báo tùy chọn dùng chung cho tất cả các hàm/thủ tục trong Standard Module. Ví dụ: Option Explicit là một khai báo tùy chọn yêu cầu tất cả các biến sau này dùng trong các hàm/thủ tục phải đƣợc khai báo tƣờng minh trƣớc khi dùng Các khai báo hằng, biến toàn cục Các hàm/thủ tục Các hàm/thủ tục trong Standard Module với phạm vi truy xuất public (mặc định) có thể đƣợc gọi từ bất kỳ đâu trong CSDL bao gồm các lời gọi từ: Các hàm/thủ tục khác trong cùng Standard Module với nó Các hàm/thủ tục trong các Class Module khác Các thủ tục gắn với các form/report trong MS Access Class Objects Các hàm/thủ tục có phạm vi truy xuất private chỉ đƣợc gọi trong các hàm/thủ tục khác thuộc cùng module với nó. Để tạo Standard Module, trong cửa sổ thiết kế CSDL, chọn lệnh CREATE trên thanh menu, sau đó chọn nút lệnh Module (vùng khoanh đỏ) nhƣ trong hình 7.1 Hình 7.1: Tạo Standard Module từ cửa sổ thiết kế CSDL 134 Kết quả bạn nhận đƣợc là cửa sổ để viết code trong Standard Module nhƣ trong hình 7.2 Hình 7.2 : Cửa sổ code của Standard Module Trong hình 7.2, cửa sổ màn hình đƣợc chia làm 02 panel bao gồm : panel bên trái là Project Explorer Panel để hiển thị các đối tƣợng module. Trong panel này, bạn có thể thêm/bớt hoặc sửa tên (F4) Standard Module, panel bên phải là Code Panel, đây là cửa sổ để bạn viết mã cho mỗi Standard Module đƣợc chọn bên panel trái. Chú ý : bạn có thể bật/tắt các panel này theo ý muốn để vùng quan sát của bạn đƣợc rộng hơn. Ví dụ khi code bạn muốn cửa sổ code (Code Panel) đƣợc rộng bạn nên tắt panel bên trái bằng cách click chuột vào biểu tƣợng dấu X ở góc trên bên phải nhất của panel đó. Khi cần bạn có thể mở lại bằng cách chọn lệnh VIEW/Project Explore trên thanh menu. Khi muốn ghi lại code, bạn cần chọn lệnh File/Save hoặc chọn biểu tƣợng save (chiếc đĩa mềm) trên thanh menu. Lần đầu tiên lƣu, bạn sẽ đƣợc hỏi đặt tên cho Standard Module, những lần sau, MS Access sẽ tự ghi vào tên bạn đã đặt từ lần đầu. Hình 7.3 minh họa cửa sổ lƣu Module3 đƣợc đặt tên là commonFunction. Code panel Project Explorer Panel 135 Hình 7.3 Đặt tên cho Standard Module Khi muốn sửa tên module đã đặt, bạn chọn vào tên module đó trong Project Explorer Panel rồi ấn phím F4. Ví dụ hình 7.4 minh họa cửa sổ đổi tên cho module1 thành tên mới là checkValidFunction Hình 7.4 Đổi tên cho Standard Module đã có Chúng ta quan tâm nhiều đến Code Panel. Sau đây, chúng ta sẽ phân tích Panel này. Phần trên cùng của Panel là hai hộp danh sách thả xuống. Hộp danh sách bên trái luôn có một mục là (General), hộp danh sách bên phải là danh sách các hàm, thủ tục trong Nút lệnh save Bạn nhập tên mới cho module ở thuộc tính (Name) 136 Standard Module (trong hình 7.2 vì chƣa có hàm, thủ tục nào đƣợc viết trong Standard Module nên chỉ có một mục (Declarations) đƣợc hiển thị). Cửa sổ soạn thảo mã lệnh gồm 03 phần, phần khai báo các tùy chọn, khai báo các hằng, biến dùng chung cho các hàm, thủ tục trong module và phần định nghĩa các hàm, thủ tục trong Standard Module. 2.1.1 Khai báo các tùy chọn Các tùy chọn nếu đƣợc khai báo có thể khai báo sau hằng, biến toàn cục nhƣng phải trƣớc phần định nghĩa các hàm/thủ tục. Phần khai báo các tùy chọn ở đây có thể có các tùy chọn sau đƣợc khai báo: Option Base Statement Khai báo chỉ số thấp nhất cho mảng trong toàn module, mặc định là 0. Cú pháp khai báo: Option Base {0 | 1} Ví dụ: Khi định nghĩa một mảng theo cú pháp Dim a(100) as Integer Mặc định ta sẽ đƣợc một mảng tên là a, các chỉ số chạy từ 0 đến 99. Nếu có tùy chọn Option Base 1 thì mảng a sẽ có 100 phần tử, chỉ số chạy từ 1 đến 100. Tùy chọn này (nếu có) phải đƣợc khai báo trƣớc bất kỳ hàm, thủ tục nào và nó chỉ có tác dụng trong module chứa nó. Option Base chỉ đƣợc khai báo một lần trong một module và phải trƣớc các khai báo mảng. Option Compare Statement Khai báo phƣơng thức so sánh cho các biểu thức thuộc kiểu chuỗi (String). Cú pháp khai báo: Option Compare {Binary | Text | Database} Option Compare Binary: so sánh chuỗi theo kiểu nhị phân, nghĩa là theo thứ tự sắp xếp của các ký tự trong bảng mã ASCII. Đây là kiểu mặc định Ví dụ: khi có khai báo Option Compare Binary thì ta sẽ có “A” < “B” < ”C” < “a” < “b” < “c” vì mã ASCII của “A” và “a” tƣơng ứng là 65 và 97 (hệ thập phân) Option Compare Text: so sánh theo kiểu trật tự của các ký tự không phân biệt chữ hoa, thƣờng. 137 Ví dụ: Khi khai báo Option Compare Text thì "A" = "a", "B" = "b", , "À" = "à", "Ê" = "ê", Option Compare Database: so sánh xâu dựa trên trật tự đƣợc xác định cục bộ trong Database chứa module đó. Option Explicit Statement Khai báo để yêu cầu các biến phải đƣợc khai báo tƣờng minh trƣớc khi sử dụng. Tùy chọn này (nếu có) phải đƣợc đặt trƣớc mọi khai báo biến và định nghĩa các hàm, thủ tục con. Cú pháp khai báo: Option Explicit Ví dụ 1: [1] Option Explicit [2] Dim a [3] a = 100 Trong đoạn mã này: + dòng [1]: yêu cầu các biến phải đƣợc khai báo tƣờng minh trƣớc khi sử dụng + dòng [2] khai báo một biến a + dòng [3] gán cho a giá trị 100 Nhƣ vậy, cuối cùng biến a đƣợc nhận giá tri là 100 Ví dụ 2: [1] Option Explicit [2] a = 100 Trong đoạn mã này: + dòng [1]: yêu cầu các biến phải đƣợc khai báo tƣờng minh trƣớc khi sử dụng + dòng [2]: gán cho biến a giá trị 100 mà không có khai báo trƣớc Đoạn mã này khi dịch trình biên dịch sẽ thông báo lỗi “Variable not defined”. Và do đó cần khai báo biến a trƣớc khi gán giá trị cho nó (Dim a) hoặc ta bỏ khai báo Option Explicit đi. Option Private Statement 138 Khai báo tùy chọn để cấm các truy xuất từ bên ngoài (các ứng dụng, dự án khác) vào các thành phần của module. Cú pháp khai báo: Option Private Module Chú ý: Tùy chọn này chỉ cấm các truy cập từ các dự án (có thể trong cùng ứng dụng), ứng dụng khác tới các thành phần (hằng, biến, hàm, thủ tục, kiểu ngƣời dùng định nghĩa) của module. Mọi truy xuất từ các module, query, form, khác trong cùng cơ sở dữ liệu là đƣợc. 2.1.2 Khai báo hằng, biến toàn cục Hằng, biến toàn cục có phạm vi hoạt động trong toàn bộ module mà nó đƣợc khai báo hoặc có thể rộng hơn (từ các module khác) tùy thuộc vào việc bạn quy định phạm vi truy xuất cho nó là private hay public. Hằng, biến toàn cục có thể đƣợc khai báo trƣớc hoặc sau các khai báo tùy chọn nhƣng bắt buộc phải khai báo trƣớc các hàm/thủ tục. Mặc định hằng, biến toàn cục ở đây có phạm vi truy xuất là private. Tức là, bạn chỉ có thể truy xuất đƣợc chúng từ các hàm, thủ tục trong cùng module với chúng. Bạn không thể truy xuất đƣợc các hằng, biến này từ các module khác. Tuy nhiên, bạn sõ thể thiết lập phạm vi truy xuất public cho chúng với khai báo từ khóa public trƣớc khai báo tên hằng, biến Chú ý: nên hạn chế việc sử dụng hằng/biến toàn cục Cú pháp khai báo hằng, biến sẽ đƣợc trình bày chi tiết trong phần sau. 2.1.3. Hàm, thủ tục (function/sub) Sau các khai báo tùy chọn và hằng, biến là phần định nghĩa các hàm/thủ tục của module. Các hàm/thủ tục đƣợc ra nhƣ là một thƣ viện, việc gọi thi hành chúng phải là tƣờng minh. Mặc định các hàm/thủ tục trong Standard Module có phạm vi truy xuất là public. Chi tiết về hàm và thủ tục sẽ đƣợc trình bày trong phần sau. 2.1.4 Ví dụ Sau đây chúng ta phân tích một Standard Module có tên là commonFunction với dụng ý là module để lƣu các hàm cơ bản, dùng chung. Trong commonFunction chúng ta sẽ định nghĩa một số hàm làm việc với mảng các số double. Mục dích của ví dụ là minh họa các thành phần trong Standard Module Chú ý: để viết các chú thích (comment) trong vùng viết code của MS Access ta sử dụng dấu „ (dấu phẩy) trong dòng chú thích. Ví dụ: ‘ This is a comment. Khi gặp các dòng bắt đầu bằng dấu „, trình biên dịch sẽ bỏ qua tất cả những gì sau dấu „ cho đến khi gặp dòng tiếp theo. ‘Khai báo tùy chọn chỉ số bắt đầu của mảng từ 1 mặc định 139 ‘là 0 và tùy chọn phải khai báo biến tường minh trước ‘khi dùng Option Base 1 Option Explicit ‘Khai báo một biến mảng toàn cục dùng chung a ‘Khai báo một hằng n dụng ý là số phần tử của mảng ‘Phạm vi truy xuất mặc định của a, n là private Dim a(100) As Double Const n As Integer = 10 ‘Định nghĩa các hàm/thủ tục ‘Thủ tục khởi tạo ngẫu nhiên các giá trị mảng a gồm ‘10 phần tử, các phần tử có giá trị <= 100 Sub InitArray() Dim i As Integer ‘Khởi tạo bộ sinh số ngẫu nhiên từ 0 đến 1 ‘sử dụng cho hàm rnd sau này Randomize For i = 1 To n a(i) = Rnd * 100 Next End Sub ‘Thủ tục in các giá trị của mảng a ra màn hình hộp thoại, ‘mỗi giá trị xuất hiện trong một lần hộp thoại xuất hiện, ‘click vào nút lệnh OK để hiển thị phần tử kế tiếp Sub showArray() 140 Dim i For i = 1 To n MsgBox ("a[" & Str(i) & "] = " & Str(a(i))) Next End Sub ‘Thủ tục xếp các phần tử của mảng a theo thứ tự tăng dần Sub sortArrayASC() Dim i, j As Integer For i = 1 To n - 1 For j = i + 1 To n If (a(i) > a(j)) Then Dim tg As Double tg = a(i) a(i) = a(j) a(j) = tg End If Next Next End Sub ‘Hàm trả về giá trị True/False tương ứng khi ‘x thuộc mảng hoặc không Function containInArray(x As Double) Dim i As Integer Dim kt As Boolean kt = False For i = 1 To n If x = a(i) Then kt = True 141 Exit For Next containInArray = kt End Function Bạn nên đọc kỹ các chú ý sau đây. Trong đoạn mã trên: + Biến mảng a và hằng n không khai báo phạm vi truy xuất là public hay private, thì mặc định là private. Điều này có nghĩa là, bạn không thể truy xuất đến a hay n từ bên ngoài module commonFunction. Ví dụ sau đây minh họa với bạn điều đó. Bạn có thể truy xuất a, n từ khắp nơi trong phạm vi module commonFunction nhƣ trong đoạn mã trên nhƣng sang module checkValidFunction bạn không thể truy xuất chúng nữa. Hình 7.5 Không nhìn thấy được a và n từ ngoài module commonFunction Bạn có thể sửa cho a, n thành phạm vi public bằng cách khai báo nhƣ sau: Public a(100) As Double Public Const n As Integer = 10 Nhƣ hình 7.6 dƣới đây, bạ ... = C:\Users\M11x-R3\Desktop\Access\qldt.accdb; Persist Security Info=False" Set cn = New adodb.Connection Set rec = New adodb.Recordset cn.Open cnstr sql = “SELECT * FROM Course WHERE CName =‟C++‟” rec.Open sql, cn, adOpenDynamic, adLockOptimistic while (not rec.EOf) rec.Delete rec.moveNext wend rec.Close: cn.Close: set cn = Nothing Ví dụ: Lấy một tập các bản ghi Đoạn mã sau đây sẽ lấy tất cả các bản ghi trong bảng Course thuộc CSDL C:\Users\M11x-R3\Desktop\Access\qldt.accdb rồi viết vào cửa sổ Immediate tên các khóa học, mỗi tên trên một dòng. Dim cn As adodb.Connection Dim cnstr, sql Dim rec As adodb.Recordset cnstr = "Provider=Microsoft.ACE.OLEDB.12.0; Data source = C:\Users\M11x-R3\Desktop\Access\qldt.accdb; Persist Security Info=False" Set cn = New adodb.Connection Set rec = New adodb.Recordset cn.Open cnstr sql = "SELECT * FROM Course" rec.Open sql, cn While Not rec.EOF Debug.Print rec.Fields(“CName”) rec.MoveNext 227 Wend rec.Close : cn.close: set cn = Nothing 4. Đối tƣợng Record Là một bản ghi (row) của đối tƣợng Recordset. 5. Field Thể hiện một cột (column) dữ liệu của đối tƣợng Recordset. 6. Property Chứa các thuộc tính động của đối tƣợng ADO đƣợc định nghĩa bởi provider 7. Parameter Chứa các tham số của đối tƣợng Command. Đó là các tham số cho truy vấn tham số và thủ tục nội 8. Đối tƣợng Error Chứa chi tiết về các lỗi truy cập dữ liệu. 9. Đối tƣợng Stream Là một dòng (stream) dữ liệu dạng nhị phân. 10. Tập hợp Errors Chứa tất cả các đối tƣợng Error đƣợc sinh ra khi truy cập với dữ liệu. 11. Tập hợp Fields Chứa tất cả các đối tƣợng Field của đối tƣợng Recordset. 12. Tập hợp Parameters Chứa tất cả các đối tƣợng Parameter của đối tƣợng Command 13. Tập hợp Properties Chứa tất cả các đối tƣợng Property của một đối tƣợng cụ thể. Ví dụ: Sau đây chúng tôi sẽ minh họa lại chƣơng trình trong phần kiến trúc DAO theo kiến trúc ADO. Lƣu ý một số khác biệt bao gồm: 228 + Câu lệnh SELECT với toán tử LIKE, ADO yêu cầu sử dụng ký tự % để đại diện cho mọi ký tự trong khi DAO sử dụng ký tự * + Option Compare Database Dim editingCID As Integer Dim con As ADODB.Connection Const cnstr As String = "Provider=Microsoft.ACE.OLEDB.12.0; Data source = C:\Users\M11x-R3\Desktop\Access\qldt.accdb; Persist Security Info=False" Private Sub cmdAddNew_Click() 'Lay cac du lieu nguoi dung nhap tu form 'Dua vao bang Course 'Hien thi ket qua ra ListBox cmdEdit.SetFocus: cmdEdit.Caption = "Edit": editingCID = -1 Dim cn As String: txtCN.SetFocus: cn = txtCN.Text Dim Duration As String: txtDuration.SetFocus: Duration = txtDuration.Text Dim Des As String: txtDes.SetFocus: Des = txtDes.value If (cn = "") Then MsgBox "The name of the course must be required!" Exit Sub End If Dim rec As ADODB.Recordset If (con Is Nothing) Then Set con = New ADODB.Connection con.Open cnstr End If If (IsNull(con)) Then Set con = New ADODB.Connection con.Open cnstr End If If (IsEmpty(con)) Then Set con = New ADODB.Connection con.Open cnstr End If 229 Set rec = New ADODB.Recordset rec.Open "SELECT * FROM Course", con, adOpenKeyset, adLockOptimistic rec.AddNew rec.Fields("CName").value = cn 'Kiem tra Duration phai la mot so nguyen nho hon 500 If (Duration "") Then If (IsNumeric(Duration) = False) Then MsgBox "Duration must be less than or equal 500!" rec.Close: con.Close Set con = Nothing Exit Sub End If Dim pos1, pos2 As Integer pos1 = -1 pos2 = -1 pos1 = InStr(1, Duration, ",", vbTextCompare) pos2 = InStr(1, Duration, ".", vbTextCompare) If (pos1 > 0) Or (pos2 > 0) Then MsgBox "Duration must be less than or equal 500!" rec.Close: con.Close Set con = Nothing Exit Sub End If Dim num As Integer num = CInt(Duration) If (num = Null) Or (num > 500) Then MsgBox "Duration must be less than or equal 500!" rec.Close: con.Close Set con = Nothing Exit Sub End If 230 rec.Fields("DurationInHour").value = num End If If (Des "") Then rec.Fields("Description").value = Des End If rec.Update: rec.Close: con.Close Set con = Nothing LoadDataToListBox End Sub Private Sub cmdDelete_Click() 'Lay ra cac dong (item) ma nguoi dung chon trong ListBox 'Xoa ban ghi do trong bang Course 'Hien thi lai ket qua trong ListBox cmdEdit.SetFocus: cmdEdit.Caption = "Edit": editingCID = -1 If (lbCourse.ItemsSelected.count = 0) Then MsgBox "You must select at least 1 item in the ListBox to delete!" Exit Sub End If Dim count As Integer: count = lbCourse.ItemsSelected.count Dim varitem As Variant, i As Integer Dim sql As String sql = "SELECT * FROM Course WHERE (CID = " & CStr(lbCourse.Column(0, lbCourse.ItemsSelected.item(0))) & ")" For i = 1 To lbCourse.ItemsSelected.count - 1 sql = sql & " OR (CID=" & CStr(lbCourse.Column(0, lbCourse.ItemsSelected(i))) & ")" Next If (con Is Nothing) Then Set con = New ADODB.Connection con.Open cnstr End If If (IsNull(con)) Then Set con = New ADODB.Connection con.Open cnstr 231 End If If (IsEmpty(con)) Then Set con = New ADODB.Connection con.Open cnstr End If Dim rec As ADODB.Recordset Set rec = New ADODB.Recordset rec.Open sql, con, adOpenDynamic, adLockOptimistic While (rec.EOF = False) rec.Delete rec.MoveNext Wend rec.Close: con.Close: Set con = Nothing LoadDataToListBox End Sub Private Sub cmdEdit_Click() 'Thay lai Text trong Caption cua nut cho phu hop 'kiem tra nguoi dung chi duoc chon 1 item de sua 'tai item do vao cac dieu khien tren form 'nguoi dung sua cac gia tri 'cap nhat lai bang Course cac gia tri moi 'Hien thi ket qua sua item do Dim cap, cn, Dur, Des As String cn = "": Dur = "": Des = "" cmdEdit.SetFocus: cap = cmdEdit.Caption cap = Trim(cap): cap = LCase(cap) If (cap = "edit") Then cap = "Save Edit" If (lbCourse.ItemsSelected.count = 0) Then MsgBox "You must select only 1 item in the ListBox to edit!" Exit Sub End If Dim count As Integer: count = lbCourse.ItemsSelected.count 232 If (count > 1) Then MsgBox "You must select only 1 item in the ListBox to edit!" Exit Sub End If editingCID = lbCourse.Column(0, lbCourse.ItemsSelected.item(0)) If (lbCourse.Column(1, lbCourse.ItemsSelected.item(0)) "") Then cn = lbCourse.Column(1, lbCourse.ItemsSelected.item(0)) End If If (lbCourse.Column(2, lbCourse.ItemsSelected.item(0)) "") Then Dur = lbCourse.Column(2, lbCourse.ItemsSelected.item(0)) End If If (lbCourse.Column(3, lbCourse.ItemsSelected.item(0)) "") Then Des = lbCourse.Column(3, lbCourse.ItemsSelected.item(0)) End If txtCN.SetFocus: txtCN.Text = cn txtDuration.SetFocus: txtDuration.Text = Dur txtDes.SetFocus: txtDes.value = Des Else cap = "Edit" txtCN.SetFocus: cn = txtCN.Text txtDuration.SetFocus: Dur = txtDuration.Text txtDes.SetFocus: Des = txtDes.value If (cn = "") Then MsgBox "The name of the course must be required!" Exit Sub End If Dim sql As String: sql = "SELECT * FROM Course WHERE CID=" & CStr(editingCID) If (con Is Nothing) Then Set con = New ADODB.Connection con.Open cnstr End If If (IsNull(con)) Then 233 Set con = New ADODB.Connection con.Open cnstr End If If (IsEmpty(con)) Then Set con = New ADODB.Connection con.Open cnstr End If Dim rec As ADODB.Recordset Set rec = New ADODB.Recordset rec.Open sql, con, adOpenDynamic, adLockOptimistic rec.Fields("CName").value = cn If (Dur "") Then If (IsNumeric(Dur) = False) Then MsgBox "Duration must be less than or equal 500!" Exit Sub End If Dim pos1, pos2 As Integer pos1 = -1 pos2 = -1 pos1 = InStr(1, Dur, ",", vbTextCompare) pos2 = InStr(1, Dur, ".", vbTextCompare) If (pos1 > 0) Or (pos2 > 0) Then MsgBox "Duration must be less than or equal 500!" Exit Sub End If Dim num As Integer num = CInt(Dur) If (num = Null) Or (num > 500) Then MsgBox "Duration must be less than or equal 500!" Exit Sub End If rec.Fields("DurationInHour").value = num 234 End If If (Des "") Then rec.Fields("Description").value = Des End If rec.Update rec.Close: con.Close: Set con = Nothing End If cmdEdit.SetFocus cmdEdit.Caption = cap LoadDataToListBox End Sub Private Sub cmdRefresh_Click() txtCN.SetFocus: txtCN.Text = "" txtDes.SetFocus: txtDes.value = "" txtDuration.SetFocus: txtDuration.Text = "" editingCID = -1 cmdEdit.SetFocus cmdEdit.Caption = "Edit" LoadDataToListBox End Sub Private Sub cmdSearch_Click() 'Lay cac du lieu nguoi dung nhap tu form 'SELECT du lieu theo dieu kien tim kiem 'Hien thi ket qua ben duoi ListBox cmdEdit.SetFocus: cmdEdit.Caption = "Edit": editingCID = -1 Dim cn As String: txtCN.SetFocus: cn = txtCN.Text Dim Duration As String: txtDuration.SetFocus: Duration = txtDuration.Text Dim Des As String: txtDes.SetFocus: Des = txtDes.value Dim foundCN As Boolean: foundCN = False Dim foundDur As Boolean: foundDur = False Dim foundDes As Boolean: foundDes = False If (cn "") Then foundCN = True 235 End If If (Duration "") Then foundDur = True End If If (Des "") Then foundDes = True End If If (foundCN = False) And (foundDur = False) And (foundDes = False) Then MsgBox "You must input either Name or Duration or Description of the course!" Exit Sub End If Dim sql As String sql = "SELECT * FROM Course WHERE" If (foundCN) And (foundDur) And (foundDes) Then sql = sql & " (CName Like '%" & cn & "%')" sql = sql & " and (DurationInHour = " & Duration & ")" sql = sql & " and (Description LIKE '%" & Des & "%')" Else If (foundCN) And (foundDur) And (Not foundDes) Then sql = sql & " (CName Like '%" & cn & "%')" sql = sql & " and (DurationInHour = " & Duration & ")" Else If (foundCN) And (Not foundDur) And (foundDes) Then sql = sql & " (CName Like '%" & cn & "%')" sql = sql & " and (Description LIKE '%" & Des & "%')" Else If (foundCN) And (Not foundDur) And (Not foundDes) Then sql = sql & " (CName Like '%" & cn & "%')" Else If (Not foundCN) And (foundDur) And (foundDes) Then sql = sql & " (DurationInHour = " & Duration & ")" sql = sql & " and (Description LIKE '%" & Des & "%')" Else 236 If (Not foundCN) And (foundDur) And (Not foundDes) Then sql = sql & " (DurationInHour = " & Duration & ")" Else If (Not foundCN) And (Not foundDur) And (foundDes) Then sql = sql & "(Description LIKE '%" & Des & "%')" End If End If End If End If End If End If End If If (con Is Nothing) Then Set con = New ADODB.Connection con.Open cnstr End If If (IsNull(con)) Then Set con = New ADODB.Connection con.Open cnstr End If If (IsEmpty(con)) Then Set con = New ADODB.Connection con.Open cnstr End If Dim rec As ADODB.Recordset Set rec = New ADODB.Recordset rec.Open sql, con, adOpenDynamic If (rec.RecordCount = 0) Then lblSearch.Caption = "There is no item found!" rec.Close: con.Close Set con = Nothing Exit Sub 237 Else rec.MoveLast lblSearch.Caption = "There are " & CStr(rec.RecordCount) & " items found" Dim i As Integer While (lbCourse.ListCount > 0) i = lbCourse.ListCount - 1 lbCourse.RemoveItem Index:=i Wend lbCourse.ColumnCount = 4 lbCourse.AddItem item:="CID;Course Name;Duration (in hour) ; Description;", Index:=0 Dim item As String: item = "" rec.MoveFirst While (rec.EOF = False) item = CStr(rec.Fields("CID").value) If rec.Fields("CName") "" Then item = item & ";" & rec.Fields("CName").value Else item = item & "; " End If If IsNull(rec.Fields("DurationInHour")) = False Then item = item & ";" & CStr(rec.Fields("DurationInHour").value) Else item = item & "; " End If If rec.Fields("Description") "" Then item = item & ";" & rec.Fields("Description").value Else item = item & "; " End If lbCourse.AddItem item:=item rec.MoveNext 238 Wend rec.Close: con.Close Set con = Nothing End If End Sub Private Sub Form_Load() cmdEdit.SetFocus: cmdEdit.Caption = "Edit": editingCID = -1 LoadDataToListBox End Sub Private Sub LoadDataToListBox() 'Ham nay se tai du lieu tu bang Coourse vao ListBox lbCourse 'lbCourse.RowSource = "" Dim rec As ADODB.Recordset If (con Is Nothing) Then Set con = New ADODB.Connection con.Open cnstr End If If (IsNull(con)) Then Set con = New ADODB.Connection con.Open cnstr End If If (IsEmpty(con)) Then Set con = New ADODB.Connection con.Open cnstr End If Set rec = New ADODB.Recordset rec.Open "SELECT * FROM Course", con, adOpenDynamic If (rec.RecordCount = 0) Then lblSearch.Caption = "There is no item found!" rec.Close: con.Close: Set con = Nothing Exit Sub Else rec.MoveLast 239 lblSearch.Caption = "There are " & CStr(rec.RecordCount) & " items found" rec.MoveFirst Dim i As Integer While (lbCourse.ListCount > 0) i = lbCourse.ListCount - 1 lbCourse.RemoveItem Index:=i Wend lbCourse.AddItem item:="CID;Course Name;Duration (in hour) ; Description;", Index:=0 Dim item As String: item = "" While (rec.EOF = False) item = CStr(rec.Fields("CID").value) If rec.Fields("CName") "" Then item = item & ";" & rec.Fields("CName").value Else item = item & "; " End If If IsNull(rec.Fields("DurationInHour")) = False Then item = item & ";" & CStr(rec.Fields("DurationInHour").value) Else item = item & "; " End If If rec.Fields("Description") "" Then item = item & ";" & rec.Fields("Description").value Else item = item & "; " End If lbCourse.AddItem item:=item rec.MoveNext Wend rec.Close con.Close 240 Set con = Nothing End If End Sub 241 BÀI TẬP CHƢƠNG 7 1. Hãy cài đặt lại chƣơng trình trong ví dụ về một chƣơng trình hoàn chỉnh sử dụng các đối tƣợng khác Recordset trong các kiến trúc DAO và ADO 2. Hãy cài đặt thêm chức năng phân trang cho ListBox của bài tập trên. Số bản ghi trên 1 trang (PageSize) sẽ do ngƣời dùng nhập vào, tại mỗi thời điểm ListBox chỉ hiển thị PageSize bản ghi và các nút 1, 2, 3, 4, để chuyển trang. Khi ngƣời dùng chọn 1 trang bất kỳ thì ListBox chỉ hiển thị các bản ghi thuộc trang đó và nút hiển thị trang đó sẽ nổi bật lên. 242 TÀI LIỆU THAM KHẢO [1] Access 2013, Microsoft, 2013 [2] Đặng Thị Thu Hiền và Đỗ Thanh Thủy, Bài giảng Nhập môn hệ quản trị cơ sở dữ liệu Access, Trƣờng ĐH Giao Thông Vận Tải, 2007. [3] MSDN Library – October 2012 [4] Teresa Hennig, Ben Clothier, George Hepworth and Dagi (Doug) Yudovich, Professional Access 2013 Programming, ISBN: 978-1-118-53083-2, Wrok, August 2013. [5] [6]
File đính kèm:
- giao_trinh_access_dhgtvt1_2_3827_525935.pdf