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à [r]
Trang 1131
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
Trang 2132
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
Trang 3133
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:
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 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 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
Trang 4134
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
Trang 5135
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)
Trang 6136
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
Trang 7137
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
Trang 8138
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
Trang 9139
‘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()
Trang 10140
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
Trang 11141
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ạn đang ở module checkvalidFunction, bạn hoàn toàn có thể nhìn thấy (truy xuất) a và n trong module commonFunction vì bạn đã có khai báo phạm vi truy xuất Public cho chúng theo cú pháp trên