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]
(1)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 đơn hệ quản trị sở liệu (CSDL) quan hệ mà cịn cung cấp mơi trƣờng lập trình với cơng cụ đầy đủ, dễ sử dụng để phát triển ứng dụng quản lý vừa nhỏ
Ngôn ngữ lập trình đƣợc phát triển MS Access Access Basic Tuy nhiên từ phiên MS Access for Windows 95, Access Basic đƣợc thay Visual Basic (VB) Hai ngôn ngữ giống đƣợc phát triển 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 chƣơng trình ứng dụng MS Office bao gồm: Access, Excel, Word, PowerPoint đƣợc gọi VBA (Visual Basic for Applications) Việc có đƣợc ngơn ngữ lập trình chung xuyên suốt chƣơng trình ứng mang lại số lợi điểm quan trọng là:
Ngƣời lập trình cần biết ngơn ngữ lập trình để tùy biến, phát triển ứng dụng
Dễ dàng hợp đối tƣợng chƣơng trình ứng dụng VBA ngơn ngữ có số đặc điểm:
Không phân biệt chữ hoa, thƣờng Hƣớng kiện hƣớng đối tƣợng
Việc tổ chức chƣơng trình theo mơ hình hƣớng đối tƣợng hƣớng kiện khiến cho mã lệnh chƣơng trình, suy nhất, đƣợc gọi có kiện (event) xảy đối tƣợng (object) cụ thể Sự kiện đối tƣợng đƣợc sinh ngƣời dùng tác động chuột/bàn phím vào điều khiển Ví dụ kiện OnClick() điều khiển Button form Sự kiện đƣợc sinh q trình biên dịch Ví dụ kiện Load() form Tuy nhiên, đối tƣợng có kiện Các đối tƣợng điều khiển (control) đƣơng nhiên có kiện Ví dụ TextBox, CommandButton, Form, … có kiện; đối tƣợng DBEngine lại khơng thể có kiện
(2)132 Chƣơng trình bày nội dung sau:
Module Access Class Object Các kiểu liệu, biến Các cấu trúc điều khiển
Hàm thủ tục
Các mơ hình truy cập CSDL 2 Module
Module đối tƣợng nguyên thủy môi trƣờng lập trình VBA Tồn mã lệnh VBA CSDL đƣợc lƣu module dƣới dạng thủ tục (gồm hàm thủ tục con) Các thủ tục độc lập liên quan đến form/report
Nói cách khác, module phƣơng tiện MS Access để giúp ngƣời lập trình tổ chức mã nguồn họ cho “gọn gàng”, dễ kiểm sốt Ví dụ, ngƣời lập trình nên gom đoạn mã (hàm/thủ tục) làm việc với CSDL vào module đặt tên DataAccessModule, gom đoạn mã việc với form vào module đặt tên FormModule hay nên viết lớp Student (Class Module) để làm việc với ghi thuộc bảng Student CSDL, …
MS Access 2013 cung cấp 03 loại module: module chuẩn (Standard Module), module lớp (Class Module) module gắn với form/report (Form/Report Module)
Standard module chủ yếu bao gồm tập hàm/thủ tục Mỗi hàm/thủ tục đƣợc gọi từ hàm/thủ tục khác từ kiện đối tƣợng hay điều khiển Khi đó, tồn mã lệnh chƣơng trình đƣợc tổ chức thành đơn vị hàm/thủ tục Các đơn vị hàm/thủ tục đƣợc gom lại Standard Module để giúp lập trình viên dễ quản lý mã lệnh
Class module thực chất lớp ngƣời dùng định nghĩa Mỗi Class Module lớp ngƣời dùng có tên tên Class Module Lớp ngƣời dùng định nghĩa đƣợc đối xử bình đẳng nhƣ lớp đƣợc định nghĩa hệ thống (built-in language class)
Điều quan trọng bạn phải biết dùng Standard Module dùng Class Module hay hai Nó phụ thuộc vào cách thiết kế ứng dụng bạn Nếu ứng dụng bạn đƣợc tổ chức theo kiểu “hƣớng chức năng” (phần mềm tập chức có quan hệ với nhau) bạn có xu hƣớng sử dụng Standard Module nhiều Nếu ứng dụng 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 liệu) bạn đƣơng nhiên sử dụng Class Module nhiều
(3)133 2.1 Module chuẩn (Standard Module)
Module chứa biến, thủ tục đƣợc gọi từ query, form, report, macro, biểu thức, thủ tục khác từ đâu chƣơng trình ứng dụng
Nhƣ vậy, ta viết Standard Module nội dung sau đây:
Các khai báo tùy chọn dùng chung cho tất hàm/thủ tục Standard
Module Ví dụ: Option Explicit khai báo tùy chọn yêu cầu tất
biến sau dùng hàm/thủ tục phải đƣợc khai báo tƣờng minh trƣớc 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 Standard Module với phạm vi truy xuất public (mặc định) đƣợc gọi từ đâu CSDL bao gồm lời gọi từ:
Các hàm/thủ tục khác Standard Module với
Các hàm/thủ tục Class Module khác
Các thủ tục gắn với form/report MS Access Class Objects
Các hàm/thủ tục có phạm vi truy xuất private đƣợc gọi hàm/thủ tục khác thuộc module với
Để tạo Standard Module, cửa sổ thiết kế CSDL, chọn lệnh CREATE menu, sau chọn nút lệnh Module (vùng khoanh đỏ) nhƣ hình 7.1
(4)134 Kết bạn nhận đƣợc cửa sổ để viết code Standard Module nhƣ hình 7.2
Hình 7.2 : Cửa sổ code Standard Module
Trong hình 7.2, cửa sổ hình đƣợc chia làm 02 panel bao gồm : panel bên trái Project Explorer Panel để hiển thị đối tƣợng module Trong panel này, bạn thêm/bớt sửa tên (F4) Standard Module, …panel bên phải Code Panel, cửa sổ để bạn viết mã cho Standard Module đƣợc chọn bên panel trái
Chú ý : bạn bật/tắt panel theo ý muốn để vùng quan sát bạn đƣợc rộng Ví dụ 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 cách click chuột vào biểu tƣợng dấu X góc bên phải panel Khi cần bạn mở lại cách chọn lệnh VIEW/Project Explore 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) menu Lần lƣu, bạn đƣợc hỏi đặt tên cho Standard Module, lần sau, MS Access 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 commonFunction
Code panel
(5)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 Project Explorer Panel ấ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 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, phân tích Panel Phần Panel hai hộp danh sách thả xuống Hộp danh sách bên trái có mục (General), hộp danh sách bên phải danh sách hàm, thủ tục
Nút lệnh save
Bạn nhập tên cho module thuộc tính
(6)136 Standard Module (trong hình 7.2 chƣa có hàm, thủ tục đƣợc viết Standard Module nên có 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 tùy chọn, khai báo hằng, biến dùng chung cho hàm, thủ tục module phần định nghĩa hàm, thủ tục Standard Module
2.1.1 Khai báo tùy chọn
Các tùy chọn đƣợc khai báo khai báo sau hằng, biến tồn cục nhƣng phải trƣớc phần định nghĩa hàm/thủ tục Phần khai báo tùy chọn có tùy chọn sau đƣợc khai báo:
Option Base Statement
Khai báo số thấp cho mảng toàn module, mặc định Cú pháp khai báo:
Option Base {0 | 1}
Ví dụ: Khi định nghĩa mảng theo cú pháp Dim a(100) as Integer
Mặc định ta đƣợc mảng tên a, số chạy từ đến 99
Nếu có tùy chọn Option Base 1 mảng a có 100 phần tử, số chạy từ đến 100
Tùy chọn (nếu có) phải đƣợc khai báo trƣớc hàm, thủ tục có tác dụng module chứa Option Base đƣợc khai báo lần module phải trƣớc khai báo mảng
Option Compare Statement
Khai báo phƣơng thức so sánh cho 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 theo thứ tự xếp ký tự bảng mã ASCII Đây kiểu mặc định
(7)137 Ví dụ: Khi khai báo Option Compare Text "A" = "a", "B" = "b", …, "À" = "à", "Ê" = "ê", …
Option Compare Database: so sánh xâu dựa trật tự đƣợc xác định cục Database chứa module
Option Explicit Statement
Khai báo để yêu cầu biến phải đƣợc khai báo tƣờng minh trƣớc sử dụng Tùy chọn (nếu có) phải đƣợc đặt trƣớc khai báo biến định nghĩa hàm, thủ tục
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 biến phải đƣợc khai báo tƣờng minh trƣớc sử dụng + dòng [2] khai báo biến a
+ dòng [3] gán cho a giá trị 100
Nhƣ vậy, cuối biến a đƣợc nhận giá tri 100 Ví dụ 2:
[1] Option Explicit [2] a = 100
Trong đoạn mã này:
+ dòng [1]: yêu cầu biến phải đƣợc khai báo tƣờng minh trƣớc 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ã dịch trình biên dịch thơng báo lỗi “Variable not defined” Và cần khai báo biến a trƣớc gán giá trị cho (Dim a) ta bỏ khai báo Option Explicit
(8)138 Khai báo tùy chọn để cấm truy xuất từ bên (các ứng dụng, dự án khác) vào thành phần module
Cú pháp khai báo:
Option Private Module
Chú ý: Tùy chọn cấm truy cập từ dự án (có thể ứng dụng), ứng dụng khác tới thành phần (hằng, biến, hàm, thủ tục, kiểu ngƣời dùng định nghĩa) module Mọi truy xuất từ module, query, form, … khác sở liệu đƣợc
2.1.2 Khai báo hằng, biến tồn cục
Hằng, biến tồn cục có phạm vi hoạt động tồn module mà đƣợc khai báo rộng (từ module khác) tùy thuộc vào việc bạn quy định phạm vi truy xuất cho private hay public Hằng, biến tồn cục đƣợc khai báo trƣớc sau khai báo tùy chọn nhƣng bắt buộc phải khai báo trƣớc hàm/thủ tục Mặc định hằng, biến tồn cục có phạm vi truy xuất private Tức là, bạn truy xuất đƣợc chúng từ hàm, thủ tục module với chúng Bạn truy xuất đƣợc hằng, biến từ 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 đƣợc trình bày chi tiết phần sau 2.1.3 Hàm, thủ tục (function/sub)
Sau khai báo tùy chọn hằng, biến phần định nghĩa hàm/thủ tục module Các hàm/thủ tục đƣợc nhƣ thƣ viện, việc gọi thi hành chúng phải tƣờng minh Mặc định hàm/thủ tục Standard Module có phạm vi truy xuất public Chi tiết hàm thủ tục đƣợc trình bày phần sau
2.1.4 Ví dụ
Sau phân tích Standard Module có tên commonFunction với dụng ý module để lƣu hàm bản, dùng chung Trong commonFunction định nghĩa số hàm làm việc với mảng số double Mục dích ví dụ minh họa thành phần Standard Module
Chú ý: để viết thích (comment) vùng viết code MS Access ta sử dụng dấu „ (dấu phẩy) dịng thích Ví dụ: ‘ This is a comment Khi gặp dòng bắt đầu dấu „, trình biên dịch bỏ qua tất sau dấu „ gặp dòng
(9)139 ‘là tùy chọn phải khai báo biến tường minh trước
‘khi dùng
Option Base Option Explicit
‘Khai báo biến mảng toàn cục dùng chung a
‘Khai báo n dụng ý số phần tử mảng ‘Phạm vi truy xuất mặc định a, n private
Dim a(100) As Double Const n As Integer = 10
‘Định nghĩa hàm/thủ tục
‘Thủ tục khởi tạo ngẫu nhiên giá trị mảng a gồm ‘10 phần tử, phần tử có giá trị <= 100
Sub InitArray()
Dim i As Integer
‘Khởi tạo sinh số ngẫu nhiên từ đến ‘sử dụng cho hàm rnd sau
Randomize
For i = To n
a(i) = Rnd * 100 Next
End Sub
‘Thủ tục in giá trị mảng a hình hộp thoại, ‘mỗi giá trị xuấ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ử
(10)140 Dim i
For i = To n
MsgBox ("a[" & Str(i) & "] = " & Str(a(i))) Next
End Sub
‘Thủ tục xếp phần tử mảng a theo thứ tự tăng dần Sub sortArrayASC()
Dim i, j As Integer For i = To n - For j = i + 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ả giá trị True/False tương ứng ‘x thuộc mảng không
Function containInArray(x As Double) Dim i As Integer
Dim kt As Boolean kt = False
For i = To n
(11)141 Exit For
Next
containInArray = kt End Function
Bạn nên đọc kỹ ý sau Trong đoạn mã trên:
+ Biến mảng a n không khai báo phạm vi truy xuất public hay private, mặc định private Điều có nghĩa là, bạn truy xuất đến a hay n từ bên ngồi module commonFunction Ví dụ sau minh họa với bạn điều Bạn truy xuất a, n từ khắp nơi phạm vi module commonFunction nhƣ đoạn mã nhƣng sang module checkValidFunction bạn khơng thể truy xuất chúng
Hình 7.5 Khơng nhìn thấy a n từ ngồi module commonFunction Bạn sửa cho a, n thành phạm vi public cách khai báo nhƣ sau: Public a(100) As Double
Public Const n As Integer = 10
(12)142 Hình 7.6 Truy xuất a, n từ module chứa chúng
+ Các hàm, thủ tục có phạm vi truy xuất mặc định Public Do vậy, bạn gọi hàm/thủ tục containInArray(), InitArray(), showArray(), sortArray() từ khắp nơi Bạn quan sát lại hình 7.5 7.6 Tuy nhiên, bạn hạn chế phạm vi truy xuất nội module commonFunction khai báo từ khóa Private trƣớc tên hàm mà bạn muốn
Ví dụ: Bạn khai báo cho 02 thủ tục InitArray() showArray() có phạm vi truy xuất private nhƣ sau:
Private Sub InitArray() Dim i As Integer Randomize
For i = To n
a(i) = Rnd * 100 Next
End Sub
(13)143 For i = To n
MsgBox ("a[" & Str(i) & "] = " & Str(a(i))) Next
End Sub
Khi đó, bạn khơng thể truy xuất đến thủ tục InitArray() showArray() từ module checkValidFunction nhƣ hình 7.7 dƣới Tất nhiên, module commonFunction bạn gọi đƣợc thủ tục cách bình thƣờng
(14)144 Hình 7.8 Chạy thử thủ tục InitArray() showArray()
(15)145 Hình 7.9 Chạy thử hàm cửa sổ Immediate
Nhƣ trình bày, nhiều trƣờng hợp bạn khơng nên sử dụng biến, tồn cục Do đó, ví dụ đƣợc viết lại khơng sử dụng biến tồn cục nhƣ sau:
Option Compare Database Option Base
Option Explicit
Sub initArray(ByRef a() As Double, ByRef n As Integer) Dim i As Integer
n = 10 Randomize For i = To n
a(i) = Rnd * 100 Next
End Sub
(16)146 Dim i
For i = To n
MsgBox ("a[" & Str(i) & "] = " & Str(a(i))) Next
End Sub
Sub sortArrayASC(ByRef a() As Double, n As Integer) Dim i, j As Integer
For i = To n - For j = i + 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
Function containInArray(x As Double, a() As Double, n As Integer) Dim i As Integer
Dim kt As Boolean kt = False
For i = To n
If x = a(i) Then kt = True
Exit For End If
Next
(17)147 End Function
Sub callSub()
Dim a(100) As Double Dim n As Integer InitArray a, n showArray a, n End Sub
Trong đoạn mã trên:
+ Mục tiêu hàm/thủ tục không thay đổi
+ Thay đổi tham số đầu vào hàm/thủ tục Bạn ý, cách truyền tham biến cho hàm/thủ tục từ khóa ByRef để sau kết thúc hàm/thủ tục giá trị biến truyền vào sau từ khóa ByRef giữ lại đƣợc giá trị thiết lập nội dung hàm/thủ tục
+ Thêm thủ tục callSub() đƣợc viết để gọi thủ tục/hàm định nghĩa
+ Để chạy thử hàm/thủ tục, bạn cần chọn thủ tục callSub() ấn F5 nhƣ hình 7.10 dƣới
(18)148 Kết nhận đƣợc chạy callSub() mảng a() số double đƣợc khởi tạo thủ tục InitArray() đƣợc giữ nguyên giá trị khỏi thủ tục (hình 7.11)
…
Hình 7.11 Kết khởi tạo mảng a() 2.2 Module lớp (Class Module)
Có thể xem Class Module loại module để định nghĩa lớp ngƣời dùng Lớp ngƣời dùng đƣợc đối xử tƣơng tự nhƣ lớp sẵn có Mỗi Class Module có hai hàm mặc định Class_Initialize() Class_Terminate() Khi tạo đối tƣợng thuộc Class Module, hàm đƣợc tự động gọi tƣơng ứng đối tƣợng đƣợc thiết lập (bằng lệnh set) hủy bỏ (tƣờng minh không tƣờng minh)
2.2.1 Tạo Class Module
Để tạo Class Module, từ menu cửa sổ Database, chọn lệnh CREATE/Class Module (hình 7.12)
(19)149 Hình 7.13 Tạo Class Module từ cửa sổ code
Kết nhận đƣợc cửa sổ để viết mã lệnh cho Class Module nhƣ hình 7.14 dƣới
Hình 7.14 Cửa sổ để viết mã lệnh cho Class Module
Code Panel Project Explorer
(20)150 Trong phần code panel, 02 hộp danh sách Hộp danh sách bên trái có 02 mục General Class Hộp danh sách bên phải tên phƣơng thức lớp mục khai báo (Declarations)
Phần bên dƣới cửa sổ để viết mã lệnh gồm khai báo tùy chọn, định nghĩa thuộc tính định nghĩa phương thức lớp
2.2.2 Khai báo tùy chọn
Phần khai báo gồm khai báo nhƣ Standard Module 2.2.3 Định nghĩa thuộc tính lớp
Khai báo thuộc tính cho lớp sau phần khai báo tùy chọn Các thuộc tính thuộc lớp đƣợc khai báo với cú pháp sau đây:
Public|Private|Dim Tên_Thuộc_Tính as Kiểu_Dữ_Liệu Trong đó:
Tên_Thuộc_Tính: đƣợc đặt theo quy tắc đặt tên: khơng có dấu cách, khơng có ký tự đặc biệt, …
As: từ khóa
Kiểu_dữ_liệu: kiểu liệu hệ thống lớp đƣợc định nghĩa
Public: định thuộc tính có phạm vi truy xuất toàn cục (khắp nơi CSDL) Tuy nhiên, lập trình hƣớng đối tƣợng khơng nên khai báo phạm vi public cho thuộc tính
Private: định thuộc tính có phạm vi truy xuất nội lớp Phạm vi nên đƣợc khai báo cho thuộc tính lớp
Dim: từ khóa chất dùng để khai báo biến, Class Module (lớp) sử dụng Dim trƣờng hợp Dim Private nhƣ Tuy nhiên, không nên sử dụng Dim mà nên sử dụng Public Private mã lệnh đƣợc rõ ràng theo phong cách lập trình hƣớng đối tƣợng chƣơng trình biên dịch dễ dàng thi hành
Ví dụ: Ta khai báo lớp doubleArray gồm thuộc tính sau đây:
Private a(100) As Double Public n As Integer