Phần 2: Sử dụng Access trong quản lý
4.5.2 Report design view.
Như đã nói ở trên, report wizard là một công cụ rất hữu hiệu để người dùng có thể nhanh
chóng tạo ra một báo cáo đơn giản. Tuy nhiên trong thực tế, nhu cầu của người dùng là mong
muốn có được một báo cáo phức tạp hơn. Để làm được điều này, có thể sử dụng công cụ Report
Design view của Access.
Chúng ta sẽ xem xét việc sử dụng report design view để tạo một báo cáo về tình hình nhân
sự như ở phần trước. Các bước tiến hành các bước sau:
Bước 1: Từ cửa sổ chính của Access, chọn Report trong cửa sổ chọn đối tượng. Tiếp theo,
chọn New, sau đó chọn Design view hoặc chọn “Create report by using design view” trong vùng
bên phải. Access sẽ mở một cửa sổ cho phép người dùng thiết kế báo cáo cho mình. Cũng giống
như trong môi trường thiết kế form, cửa sổ thiết kế báo cáo cũng gồm 3 thành phần chính là:
(1) Vùng soạn thảo báo cáo.
(2) Hộp thoại công cụ - chứa các đối tượng được sử dụng trong báo cáo.
(3) Hộp thoại thuộc tính - cho phép người dùng thiết lập các thuộc tính cho báo cáo và các
đối tượng trên báo cáo.
129
Phần 2: Sử dụng Access trong quản lý
Bước 2: Thiết lập nguồn dữ liệu cho báo cáo: Như đã trình bày ở trên, báo cáo là một công
cụ lấy dữ liệu từ các bảng, các truy vấn để hiển thị cho người dùng xem, in ấn. Do đó ta phải thiết
lập nguồn dữ liệu cho báo cáo (lựa chọn bảng, truy vấn để báo cáo lấy dữ liệu ra). Để làm được
điều này, trên cửa sổ thuộc tính, chọn Report trong danh sách đẩy xuống và chọn tab “Data”.
Trên dòng thuộc tính Record Source, ta có thể chọn nguồn dữ liệu từ danh sách các đối
tượng có sẵn của Access (các bảng, các truy vấn) bằng cách click chuột vào nút mũi tên
để
130
Phần 2: Sử dụng Access trong quản lý
Access liệt kê các đối tượng hoặc click chuột vào biểu tượng
để xây dựng một truy vấn mới
làm nguồn dữ liệu cho báo cáo. Thông thường, người dùng hay chọn phương án thứ 2 để có thể
xây dựng 1 nguồn dữ liệu như mong muốn. Khi đó Access sẽ mở một môi trường để người dùng
xây dựng một truy vấn mới cho báo cáo. Cũng giống như qui trình tạo truy vấn đã đề cập đến ở
phần trên, chúng ta sẽ chọn các bảng có liên quan để lấy dữ liệu ra cho báo cáo. Giả sử ta có truy
vấn như sau:
Sau khi tạo xong truy vấn, đóng cửa sổ soạn thảo truy vấn lại. Khi đó, Access sẽ hỏi có ghi
lại sự thay đổi không. Bấm Yes để xác nhận sự thay đổi:
Đến đây, thuộc tính Record source của báo cáo đã được Access xây dựng. Nếu ta để ý thì
đó chính là một câu lệnh SQL.
Bước 3: Trình bày dữ liệu lên báo cáo. Đây là bước người dùng tự định nghĩa khuôn dạng
và kiểu dáng của báo cáo mà mình mong muốn. Có một số lưu ý sau:
- Report header là phần chứa tiêu đề của cả Report. Ví dụ chúng ta đặt tên cho báo cáo là
“Danh sách nhân viên” thì tiêu đề này được đặt trong report header.
- Page header là phần chứa tiêu đề của các cột trong báo cáo. Tiêu đề này được lặp lại nếu
độ dài của report dài quá 1 trang.
Sử dụng các đối tượng trên thanh công cụ Toolbox để xây dựng báo cáo (giả sử ta muốn tạo
một báo cáo có khuôn dạng như sau):
131
Phần 2: Sử dụng Access trong quản lý
Ở đây chúng ta có một số lưu ý sau:
- Ở phần Page header, ta sử dụng tất cả các nhãn (Label) để đặt tên cho các cột dữ liệu. Ở
đây ta muốn có một báo cáo gồm các cột: STT, Họ và tên nhân viên, Phòng mà nhân viên
làm việc và Giới tính của nhân viên. Các nhãn này sẽ được hiển thị ở đầu của tất cả các
trang.
- Ở phần Detail, cột STT ta đưa vào một textbox và thiết lập các thuộc tính Control Source
= 1, Running sum là Over group (Đánh số thư tự). Các cột còn lại ta đưa vào các textbox
và thiết lập các thuộc tính Control source của từng textbox là các tên trường tương ứng
trong truy vấn vừa tạo ra ở trên.
- Ở dưới phần Report footer ta thêm vào một dòng để đếm tổng số nhân viên trong công ty.
Để làm được điều này ta thêm vào một nhãn để ghi dòng chữ “Tổng cộng” và một textbox
để tính tổng số nhân viên. Ta thiết lập thuộc tính Control source cho textbox bằng biểu
thức =Sum(TenNhanvien).
132
Phần 2: Sử dụng Access trong quản lý
Đến đây ta đã tạo được một báo cáo đơn giản về tình hình nhân sự của công ty bằng công
cụ report design view. Bước cuối cùng là ghi lại báo cáo đã tạo. Báo cáo khi chạy sẽ như sau:
Trên đây chỉ là một ví dụ đơn giản để minh họa cho bạn đọc về cách tạo một báo cáo. Trong
thực tế, Access còn cho phép tạo ra nhiều ứng dụng phức tạp và mạnh hơn rất nhiều. Để bạn đọc
có thể nghiên cứu và tự mình tạo ra được các ứng dụng với MS Access, chúng ta sẽ thực hành 2
bài tập cụ thể ở cuối phần. Trong chương tiếp theo, chúng ta sẽ xem xét sâu hơn về khía cạnh lập
trình của Access, đó là lập trình ứng dụng VBA và lập trình CSDL.
133
Phần 2: Sử dụng Access trong quản lý
CHƯƠNG 5: TỔNG QUAN VỀ LẬP TRÌNH ỨNG DỤNG
VBA VÀ DAO
VBA - Visual Basic for Application là một công cụ rất quen thuộc đối với người dùng bộ
sản phẩm MS Office. Nhiều khi, trong Access, chúng ta muốn ứng dụng thực hiện các hành động
mà bản thân Access không thể đáp ứng được. Khi đó, Visual basic là một công cụ rất hữu ích để
chúng ta có thể thực hiện được các yêu cầu này.
Lập trình ứng dụng VBA thực chất là việc người phát triển ứng dụng Access “lập trình” để
tạo ra các đoạn mã nguồn của riêng mình bằng ngôn ngữ lập trình Visual basic. Với các “chương
trình” được tạo ra bởi VBA, ứng dụng được phát triển bằng Access sẽ có được các ưu điểm như sau:
- Ứng dụng dễ bảo trì hơn: Như đã trình bày ở trên, một ứng dụng được phát triển bằng
Access có thể chứa đựng rất nhiều Macro để đáp ứng các tình huống trên form và report
và như vậy, ứng dụng của chúng ta sẽ rất khó bảo trì và sửa chữa. Ngược lại, nếu được
phát triển bằng các đoạn mã lệnh Visual basic thì các đoạn mã lệnh đó sẽ có thể được di
chuyển một cách dễ dàng sang ứng dụng khác.
- Tạo được các thư viện hàm riêng: Bên cạnh các hàm được xây dựng sẵn (built in
function), được sử dụng để thực hiện các tính toán cơ bản, lập trình VBA còn có thể cho
phép chúng ta tự tạo ra các hàm riêng cho mình để thực hiện các phép tính toán phức tạp
và có thể tái sử dụng trong các ứng dụng về sau.
- Xử lý lỗi: Khi có một lỗi không mong đợi xảy ra đối với ứng dụng, Access sẽ hiển thị một
thông báo lỗi - một thông báo lỗi mà người dùng thường khó có thể hiểu được. Với VBA,
chúng ta có thể “bắt” các lỗi này và hiển thị các thông báo lỗi của chính mình hay xử lý
lỗi theo cách của mình.
- Tạo và thao tác với các đối tượng: Trong hầu hết các trường hợp, chúng ta thường tìm
cách dễ nhất để tạo và sửa một đối tượng trong cửa sổ Design view của nó. Tuy nhiên,
trong một số trường hợp, bạn có thể muốn thao tác, định nghĩa một đối tượng bằng mã
chương trình. Dùng Visual basic chúng ta có thể thao tác trên tất cả đối tượng trong cơ sở
dữ liệu, bao gồm cả chính nó.
- Thực hiện các hành động ở cấp độ hệ thống: Từ một ứng dụng Access, chúng ta có thể
dùng “hành động” - action trên RunApp trong một macro để thi hành một ứng dụng
Windows based (ứng dụng chạy trên Windows) nhưng những macro đó không thể thực
hiện được những điều ở ngoài Access. Visual basic cho phép chúng ta thực hiện được
những điều mà macro không thể làm được như: kiểm tra sự tồn tại của file, gọi các hàm
trong các thư viện liên kết động (DLL) của Windows v.v.
- Thao tác với từng bản ghi - record: Với Visual basic, chúng ta có thể “duyệt” lần lượt
từng bản ghi trong một tập các bản ghi và thực hiện các thao tác mong muốn trên bản ghi
cụ thể nào đó. Với macro, chúng ta chỉ có thể làm việc một lúc với toàn bộ các record.
134
Phần 2: Sử dụng Access trong quản lý
- Truyền các đối số tới mã nguồn: Đối số là một giá trị cung cấp thêm thông tin theo yêu
cầu của một số hoạt động (hàm, thủ tục). Chúng ta có thể đặt các đối số cho các hành
động trong cửa sổ macro khi tạo một macro nhưng không thể thay đổi chúng khi macro
đang thi hành. Tuy nhiên, với Visual basic, chúng ta có thể truyền các đối số đến mã
nguồn tại thời điểm nó đang thi hành. Ngoài ra, chúng ta còn có thể sử dụng biến cho các
đối số - điều này không thể thực hiện được trong macro. Đây chính là một sự linh động
rất lớn trong việc điều khiển mã nguồn sẽ thi hành như thế nào.
5.1 CÁC KIỂU DỮ LIỆU VÀ KHAI BÁO
Cũng giống như tất cả các ngôn ngữ lập trình khác, VBA cung cấp một loạt các kiểu dữ liệu
cơ bản sau:
- Kiểu dữ liệu Variant: Kiểu dữ liệu này có thể cất giữ nhiều loại dữ liệu. Giống như một
text box trên một form, một biến variant có khả năng cất giữ các số, chuỗi, ngày tháng
hay giá trị null. Bạn không cần phải chuyển đổi kiểu dữ liệu khi gán chúng vào một biến
variant. Visual basic sẽ tự động thực hiện các chuyển đổi cần thiết.
- Các kiểu dữ liệu số: Byte, Integer, Long, Single, Double. Các kiểu dữ liệu này cho phép
lưu trữ các giá trị số với độ lớn tối đã khác nhau.
- Kiểu dữ liệu xâu ký tự - String: Là kiểu ký tự dùng để lưu trữ các giá trị là một chuỗi xâu
ký tự.
- Kiểu dữ liệu logic - Boolen: Là kiểu dữ liệu chỉ có 2 giá trị Đúng và Sai.
- Kiểu dữ liệu ngày tháng - Date: Lưu trữ giá trị ngày tháng và thời gian.
- Dữ liệu kiểu đối tượng - Object: Các kiểu dữ liệu đối tượng được cất giữ trong các địa chỉ
32 bit để tham chiếu tới các đối tượng trong một ứng dụng hay trong các ứng dụng khác.
Một biến khai báo là Object có thể được gán (bằng các phát biểu Set) để tham chiếu tới
bất cứ đối tượng đã được nhận biết bởi ứng dụng.
- Kiểu dữ liệu tiền tệ - Currency: Bản chất là kiểu số có độ lớn 8 byte. Kiểu dữ liệu tiền tệ
luôn luôn có ký hiệu tiền tệ đi kèm.
5.2 BIẾN VÀ KHAI BÁO BIẾN
Biến (variable) là một đối tượng được sử dụng để cất giữ các giá trị trong khi thi hành mã
nguồn Visual basic. Cú pháp khai báo 1 biến như sau:
Dim/Public <tên biến> [As Kiểu]
Trong đó:
- Dim/Public: là từ khoá của Visual basic để chỉ ra rằng đây là câu lệnh khai báo biến.
Chúng ta sẽ chỉ sử dụng 1 trong 2 từ khoá Dim hay Public tuỳ theo từng ngữ cảnh cụ thể.
Khi nào sử dụng từ khoá nào sẽ được đề cập ở phần phạm vi của biến dưới đây.
- <tên biến>: là tên mà người dùng đặt cho biến (theo qui tắc đặt tên biến của ngôn ngữ lập
trình). Trong mã chương trình ta sẽ không sử dụng dấu < và >.
- As: Từ khoá của Visual basic chỉ ra kiểu của biến.
- Kiểu: Kiểu của biến
135
Phần 2: Sử dụng Access trong quản lý
Cặp dấu [] chỉ ra rằng phần nằm bên trong nó là tuỳ chọn. Người dùng có thể chỉ ra một
cách tường minh kiểu của biến hoặc không (nếu không, Visual basic ngầm hiểu kiểu của biến là
variant).
Trong Visual basic, khác với một số ngôn ngữ lập trình khác (như Pascal hay C), chúng ta
có thể không nhất thiết phải khai báo biến trước khi sử dụng nó. Đây chính là cách “không khai
báo biến tường minh”. Tuy nhiên, để chương trình dễ “đọc” và dễ quản lý, chúng ta có thể khai
báo tường minh các biến trước khi sử dụng nó.
Ví dụ:
Dim strName as string
strName = ‘Nguyễn Văn An”
Ở đây biến strName được sử dụng sau khi đã khai báo. Do đó nó được coi là khai báo tường
minh. Ngược lại, nếu trước đó ta chưa khai báo bằng câu lệnh Dim ở trên thì biến strName được
sử dụng theo kiểu không khai báo tường minh.
Khi được khai báo, một biến sẽ được sinh ra trong Visual basic và sẽ tồn tại trong một phạm
vi nào đó, tức là nó sẽ có giá trị trong một vùng nào đó đã được xác định trước. Ngoài phạm vi đó,
biến sẽ không còn có tác dụng. Trong Visual basic, chúng ta có 2 phạm vi cho biến đó là:
- Biến cục bộ: Là biến được khai báo bởi từ khoá Dim. Biến này chỉ tồn tại trong phạm vi
khai báo nó - trong 1 hàm, một thủ tục hay một module nhất định.
- Biến toàn cục: Là biến được khai báo bởi từ khoá Public. Biến này có ảnh hưởng đến toàn
bộ chương trình, do đó trong 1 chương trình không thể có 2 biến toàn cục có cùng tên.
Tuy nhiên, chúng ta có thể khai báo biến cục bộ trùng tên với biến toàn cục. Khi đó
Visual basic sẽ ưu tiên sử dụng biến cục bộ trong phạm vi của nó.
Ngoài ra, Visual basic còn hỗ trợ việc khai báo các hằng số. Hằng số là các giá trị cố định,
không bị thay đổi trong chương trình. Việc sử dụng hằng số rất tiện lợi khi trong chương trình ta
cần sử dụng lặp đi lặp lại một giá trị nào đó. Để khai báo hằng số, ta sử dụng cú pháp sau:
Const <tên hằng> = <Giá trị>
Ví dụ: Const name = “Nguyễn Văn Nam” - Khai báo hằng có giá trị kiểu chữ
Const dob = #09/17/1980# - Khai báo hằng có giá trị kiểu ngày tháng.
Tương tự như biến, hằng cũng có phạm vi ảnh hưởng của nó. Khi được khai báo trong hàm, thủ
tục hay module nào thì hằng sẽ có ảnh hưởng đến hàm, thủ tục hay module đó. Để có hằng có phạm vi
toàn cục, ta phải khai báo hằng bằng từ khoá Public Const ngay trong phần khai báo của module.
5.3 CÁC CẤU TRÚC ĐIỀU KHIỂN
Các cấu trúc điều khiển cho phép chúng ta điều khiển thứ tự thi hành của các câu lệnh trong
một chương trình. Thông thường, nếu bỏ qua các cấu trúc điều khiển thì thứ tự thi thành của các
câu lệnh trong một đoạn mã sẽ là tuần tự từ trên xuống dưới, bắt đầu với câu lệnh đầu tiên và kết
thúc bởi câu lệnh cuối cùng. Cũng giống như các ngôn ngữ lập trình khác, Visual basic cung cấp
đầy đủ các cấu trúc điều khiển cho phép chúng ta thay đổi thứ tự thực thi của các câu lệnh một
cách linh hoạt và hiệu quả.
136
Phần 2: Sử dụng Access trong quản lý
5.3.1 Cấu trúc lệnh rẽ nhánh
Cấu trúc rẽ nhánh cho phép chúng ta kiểm tra các điều kiện rồi thực hiện các hành động
khác nhau tuỳ thuộc vào kết quả được kiểm tra. Các cấu trúc lựa chọn của Visual basic bao gồm:
If … Then
If Then … Else
Select Case.
Cấu trúc If Then dùng để thi hành một hay nhiều câu lệnh khi một điều kiện kiểm tra
được thoả mãn. Cấu trúc chung của If … Then như sau:
If < điều kiện> Then
<một hoặc nhiều lệnh>
End If.
Với đoạn mã trên, nếu <điều kiện> - thường là một biểu thức logic - là đúng thì chương
trình sẽ thực hiện <một hoặc nhiều lệnh>. Ngược lại, chương trình sẽ không thực hiện gì.
Cấu trúc If …Then … Else là sự phát triển của cấu trúc If … Then. Ở trên, nếu biểu thức là
đúng thì một hoặc nhiều lệnh trong khối được thực hiện, ngược lại chương trình không thực hiện
gì. Tuy nhiên, trong cấu trúc này, nếu điều kiện kiểm tra là sai thì chương trình sẽ thực hiện các
lệnh nằm trong phần Else:
If <điều kiện> Then
<một hoặc nhiều lệnh>
Else
<một hoặc nhiều lệnh khác>
End If
Select Case lại là phần mở rộng hơn của If … Then … Else. Trong cấu trúc If … Then …
Else, chúng ta chỉ có thể xử lý được một trong 2 tình huống là <điều kiện> đúng hoặc sai. Tuy
nhiên, trong thực tế có rất nhiều trường hợp <điều kiện> của chúng ta lại trả về nhiều hơn 2 giá trị.
Do đó biểu thức Select Case được sử dụng để giải quyết các tình huống đó. Cú pháp của biểu thức
này như sau:
Select Case <tên biến>
Case <giá trị 1>
<tập lệnh 1>
Case <giá trị 2>
<tập lệnh 2>
….
Case <giá trị n>
<tập lệnh n>
137
Phần 2: Sử dụng Access trong quản lý
Case Else
<tập lệnh n+1>
End Select
Ý nghĩa của biểu thức này như sau: Chương trình sẽ kiểm tra <tên biến>. Ứng với mỗi giá
trị của <tên biến>, tập lệnh tương ứng sẽ được thực hiện. Ngược lại, nếu không có giá trị nào
trong các giá trị trên thoả mãn thì tập lệnh thứ n+1 nằm sau Case Else sẽ được thực hiện.
Với cấu trúc này, nếu 1 biến có nhiều hơn 1 giá trị thì cũng chỉ tập lệnh đầu tiên ứng với giá
trị đầu tiên được thực hiện và chương trình sẽ tự động thoát ra khỏi cấu trúc Select.
5.3.2 Cấu trúc lặp
Trong lập trình cũng như trong đời sống, chúng ta có thể muốn lặp đi lặp lại một số thao tác
nào đó một số lần nhất định, cho tới khi đạt đến một đích cho trước hay cho tới khi một điều kiện
nào đó được thỏa mãn. Trong lập trình, trường hợp đầu được gọi là một vòng lặp xác định trước
số lần lặp và trường hợp sau gọi là vòng lặp không xác định trước số lần lặp. Với Visual basic,
chúng ta có các cấu trúc lặp như sau:
Do … Loop: Đây là cấu trúc lặp với số vòng lặp không xác định trước. Cú pháp của cấu
trúc này như sau:
Do While <điều kiện>
<các lệnh>
Loop
Với cấu trúc này, nếu <điều kiện> còn đúng thì <các lệnh> sẽ còn được thực hiện. Chỉ khi
nào <điều kiện> là sai thì vòng lặp mới kết thúc. Đây là cấu trúc lặp mà ngay từ lần thực hiện đầu
tiên chương trình đã kiểm tra <điều kiện>. Điều này có nghĩa là có thể vòng lặp sẽ không được
thực hiện lần nào nếu <điều kiện> sai ngay lần thử đầu tiên. Để cải tiến, ta có thể sử dụng cấu trúc
này theo cách sau:
Do
<các lệnh>
Loop While <điều kiện>
Để đảm bảo ít nhất vòng lặp được thực hiện một lần.
Ngoài ra, chúng ta cũng có thể sử dụng cấu trúc lặp này với từ khoá Until thay vì từ khóa
While. Điều khác biệt ở đây là, với từ khoá While, vòng lặp sẽ dừng lại khi <điều kiện> là sai,
còn với từ khoá Until, vòng lặp sẽ dừng lại khi điều kiện là đúng.
For … Next: Vòng lặp Do …Loop ở trên hoạt động rất tốt trong trường hợp chúng ta chưa
biết chính xác số lượng vòng lặp cần thực hiện. Tuy nhiên, trong nhiều trường hợp, khi chúng ta
đã biết chính xác được số lượng vòng lặp rồi thì cấu trúc For … Next là một lựa chọn tốt hơn. Cú
pháp của cấu trúc này như sau:
For <biến đếm> = <bắt đầu> To <kết thúc> [Step <giá trị tăng>]
<các lệnh>
Next
138
Phần 2: Sử dụng Access trong quản lý
Ý nghĩa của cấu trúc này như sau: Chương trình sẽ thực hiện <các lệnh> với số lượng là
<kết thúc> - <bắt đầu> + 1 lần. Ở đây, biến đếm, bắt đầu và kết thúc thường là các số nguyên.
Đầu tiên, chương trình thiết lập <biến đếm> bằng với <bắt đầu> và ngầm định giá trị tăng là 1 và
thực hiện <các lệnh>. Sau mỗi vòng, chương trình tăng <biến đếm> lên 1 giá trị và so sánh nó với
<kết thúc>. Nếu <biến đếm> còn nhỏ hơn <kết thúc> thì thực hiện tiếp <các lệnh>, ngược lại thì
thoát khỏi vòng lặp. Ở đây, Step được ngầm định hiểu là giá trị 1 nếu ta không viết ra tường minh.
Ví dụ, chúng ta muốn in ra màn hình các chữ số từ 1 đến 10. Do đã biết được số vòng lặp là
10 nên ta có thể sử dụng cấu trúc For … Next như sau:
For i = 1 To 10
Debug.Print i
Next i
Nếu muốn in ngược lại từ 10 đến 1, ta sử dụng Step = -1 như sau:
For i = 10 to 1 Step -1
Debug.Print i
Next i
For Each … Next: Là cấu trúc tương tự như For … Next nhưng nó lặp lại một nhóm các câu
lệnh cho từng phần tử trong một tập hợp hay trong một mảng (array) thay vì lặp các câu lệnh một số
lần chỉ định. Điều này đặc biệt có ích nếu chúng ta không biết có bao nhiêu phân tử trong tập hợp.
Cú pháp của cấu trúc này như sau:
For Each <phần tử> In <tập hợp>
<các lệnh>
Next <phần tử>
5.3.3 Các cấu trúc điều khiển lồng nhau.
Chúng ta hoàn toàn có thể đặt các cấu trúc điều khiển bên trong một cấu trúc điều khiển
khác (ví dụ một khối If…Then nằm trong một vòng lặp For …Next). Một cấu trúc điều khiển đặt
bên trong một cấu trúc điều khiển khác được gọi là lồng nhau. Nếu muốn, chúng ta cũng có thể tổ
chức các cấu trúc điều khiển trong Visual basic thành nhiều cấp.
Qui luật về các cấu trúc điều khiển lồng nhau là rất đơn giản. Khi đó, cấu trúc bên trong
phải được hoàn thành trước khi trở thành điều kiện kiểm tra cho cấu trúc bên ngoài trực tiếp chứa
nó. Một kỹ thuật lập trình mà chúng ta nên tham khảo và áp dụng, đó là khi viết các cấu trúc điều
khiển lồng nhau, chúng ta nên căn lề cho từng cấu trúc để đoạn mã chương trình rõ ràng và dễ gỡ
rối khi có lỗi xảy ra.
5.3.4 Thoát khỏi một cấu trúc điều khiển lặp
Như đã trình bày ở trên, các vòng lặp For và Do được lặp đi lặp lại với số lượng lần biết
trước hay không biết trước. Tuy nhiên, trong nhiều ứng dụng, nếu chúng ta đã thực hiện được mục
tiêu thì chúng ta cần thoát ngay ra khỏi vòng lặp. Khi đó, câu lệnh Exit có thể được sử dụng để
139
Phần 2: Sử dụng Access trong quản lý
chương trình ngay lập tức thoát ra khỏi vòng lặp. Cú pháp của câu lệnh này rất đơn giản, từ khoá
exit được sử dụng cùng với từ khoá của vòng lặp For hay Do
Ví dụ: Exit For sẽ thoát ngay ra khỏi vòng lặp For.
5.4 SỬ DỤNG LỆNH DOCMD
Trong nhiều trường hợp, mã lệnh của Visual basic không thể giúp chúng ta thực hiện được
một số hành động - chẳng hạn như đóng hay mở một form, report. Khi đó, lệnh DoCmd của
Access là một công cụ hữu ích giúp chúng ta thực hiện các hành động kiểu này.
DoCmd có cú pháp như sau:
DoCmd.<hành động> <danh sách các tham số>
Ở đây, hành động là các hành động mà Access hỗ trợ như đóng (close), mở (open) form hay
report, thực thi câu lệnh SQL (RunSQL).
<danh sách các tham số> là các tham số mà mỗi <hành động> ở trên hỗ trợ, mỗi tham số
được viết cách nhau bởi 1 dấu phẩy “,”.
Ví dụ, chúng ta có 1 form được đặt tên là frmUser. Để mở form này, chúng ta có thể thực
hiện câu lệnh DoCmd như sau:
DoCmd.OpenForm “frmUser”, acNormal - Mở form ở chế độ thi hành.
Với các hành động mở Form và mở Report, chúng ta thường có các tham số như sau:
[ViewMode], [FilterName], [WhereCondition], [DataMode], [WindowsMode]
Trong đó:
- ViewMode - chế độ mở. Cụ thể:
o acDesign: Mở Report ra chế độ thiết kế
o acNormal: Mở Report ra để thi hành
- FilterName - Đặt lọc
- WhereCondition - Giới hạn các bản ghi trong nguồn dữ liệu
- DataMode - thiết lập chế độ dữ liệu trên Report
- WindowsMode - thiết lập kiểu cửa sổ Report là:
o acDialog: Kiểu hộp thoại
o acWindowsNormal: Kiểu cửa sổ bình thường
Ngoài ra, lệnh DoCmd.RunSQL <câu lệnh SQL> sẽ thực thi một câu lệnh SQL giống như
nó được viết ra trong một truy vấn.
5.5 CHƯƠNG TRÌNH CON - THỦ TỤC VÀ HÀM
Cũng giống như trong tất cả các ngôn ngữ lập trình khác, Visual basic cũng hỗ trợ người lập
trình tạo ra các chương trình con dưới dạng thủ tục hay hàm. Một chương trình con, về mặt cấu
trúc có thể được coi như một chương trình hoàn chỉnh được viết để làm một số việc nhất định nào
140
Phần 2: Sử dụng Access trong quản lý
đó. Thông thường, nhiều khi người lập trình muốn sử dụng lặp đi, lặp lại một đoạn mã lệnh nào
đó. Khi đó, đoạn mã lệnh đó có thể được viết dưới dạng một chương trình con để người lập trình
có thể tái sử dụng nó một cách hiệu quả mà không cần phải viết lại toàn bộ đoạn mã.
Có hai loại chương trình con, đó là Thủ tục (Sub) và Hàm (Function). Sự khác biệt cơ bản
giữa thủ tục và hàm là ở chỗ: Thủ tục là một chương trình con được viết để thực hiện một hoặc
một vài thao tác nhưng không trả về một giá trị nào và không được sử dụng trong một biểu thức,
trong khi đó, hàm là một chương trình con được viết để tính toán và trả về một giá trị nào đó và có
thể được sử dụng trong một biểu thức. Cả hàm và thủ tục đều có thể nhận các đối số.
Cách khai báo thủ tục:
[Private|Public] [Static] Sub <Tên thủ tục>(<Danh sách các đối số>)
<các lệnh>
End Sub.
Trong đó
- Private|Public là các từ khoá khai báo phạm vi của thủ tục là toàn cục hay cục bộ. Nếu
không được chỉ rõ, Visual basic sẽ tự coi thủ tục nó là Private.
- [Static] là từ khoá chỉ ra thủ tục đó là tĩnh.
- Sub và End Sub: Là các từ khoá bắt buộc có trong khai báo thủ tục.
- <Tên thủ tục>: Là tên của thủ tục mà người dùng muốn đặt.
- <Danh sách các đối số>: Là danh sách các đối truyền vào thủ tục. Nếu có nhiều đối số thì
mỗi đối số được phân cách bởi dấu phẩy. Mỗi đối số giống như một khai báo biến và hoạt
động giống như một biến trong thủ tục. Cú pháp khai báo đối số là:
[optional] [byval] <tên biến> as <kiểu>.
Cú pháp khai báo một hàm như sau:
[Private|Public] [Static] Function <tên hàm> (<danh sách các đối số> as <kiểu>)
<các lệnh>
End Function
Ở đây mọi thứ đều giống như trong khai báo thủ tục, điều khác biệt duy nhất là vì hàm trả
về giá trị, cho nên trong khai báo hàm ta có thêm khai báo kiểu giá trị trả về của hàm bằng chỉ thị:
as <kiểu>.
Vì hàm trả về một giá trị cho nên trước khi kết thúc một hàm (trước câu lệnh End Function),
chúng ta luôn phải gán giá trị trả về vào hàm bằng câu lệnh gán như sau:
<tên hàm> = <giá trị trả về>.
Ở đây <tên hàm> chính là tên hàm mà ta định nghĩa ở trên còn <giá trị trả về> có thể là giá
trị nào đó hoặc một biểu thức nào đó.
141
Phần 2: Sử dụng Access trong quản lý
Ví dụ 1:
Ta cần một thủ tục đổi giá trị của 2 số nguyên cho nhau. Mỗi lần thủ tục được gọi với 2 biến
số nguyên bất kỳ thì giá trị của chúng sẽ được hoán đổi cho nhau. Thủ tục sẽ được viết như sau:
Private Sub Hoanvi(so_thu_nhat as Integer, so_thu_hai as Integer)
Dim so_tam_thoi as Integer
so_tham_thoi = so_thu_nhat
so_thu_nhat = so_thu_hai
so_thu_hai = so_tam_thoi
End Sub.
Ở thủ tục này, công việc của ta rất đơn giản, ta sử dụng một biến trung gian là so_tam_thoi
(Số tạm thời) để lưu trữ giá trị cho số thứ nhất, sau đó gắn giá trị của số thứ 2 vào số thứ nhất.
Như vậy số thứ nhất đã có giá trị của số thứ 2. Cuối cùng, ta lấy giá trị của số tạm thời (thực chất
là giá trị của số thứ nhất) để gán cho số thứ 2. Như vậy, sau thủ tục này, giá trị của 2 số nguyên đã
được hoán đổi cho nhau.
Tiếp theo ta sẽ lấy ví dụ về cách tạo hàm. Giả sử ta cần một hàm số tính giai thừa của một
số nguyên. Biến đầu vào là một số nguyên và giá trị trả về là giai thừa của số đó. Ta sẽ viết hàm
như sau:
Ví dụ 2: Tính giai thừa của số nguyên n
Private Function giaithua(songuyen as Integer) as Long
Dim i as Integer
Dim tam as Long
tam = 1
For i = 1 to songuyen
tam = tam * i
Next
giaithua = tam
End Function
Lưu ý: Công thức tính giai thừa của số nguyên N: N! = 1x2x3x xN
Ví dụ 3:
Hàm chuẩn hóa 1 xâu ký tự (Các từ cách nhau 1 dấu cách, chữ cái đầu từ viết hoa, các chữ
còn lại viết thường).
Public Function Chuanhoa(ByVal ST As String)
Dim i As Integer
ST = Trim(ST)
142
Phần 2: Sử dụng Access trong quản lý
Do While InStr(1, ST, " ") > 0
ST = Replace(ST, " ", " ")
Loop
ST = LCase(ST)
ST = " " & ST
For i = 1 To Len(ST) - 1
If Mid(ST, i, 1) = " " Then
ST = Mid(ST, 1, i) & Replace(ST, Mid(ST, i + 1, 1), UCase(Mid(ST, i + 1,
1)), i + 1, 1)
End If
Next
Chuanhoa = Trim(ST)
End Function
Lưu ý: Cách sử dụng các hàm Trim(), Mid(), Replace(), Len(), UCase() v.v. xem hướng dẫn
sử dụng chi tiết trong trợ giúp của Access.
5.6 LẬP TRÌNH CƠ SỞ DỮ LIỆU VỚI DAO
DAO (Data Access Objects) là một lớp thư viện các đối tượng được cung cấp bởi Microsoft
dùng cho việc truy nhập và quản lý CSDL.
Để sử dụng DAO, trước hết cần kiểm tra xem thư viện này đã được nạp vào ứng dụng chưa.
Từ cửa sổ Microsoft Visual Basic, chọn menu Tools -> References. Trong cửa sổ hiện ra, nếu hộp
chọn Microsoft DAO chưa được chọn thì có nghĩa DAO chưa được nạp. Click chọn hộp chọn này,
sau đó click OK để nạp DAO.
143
Phần 2: Sử dụng Access trong quản lý
Các đối tượng chính trong thư viện DAO bao gồm:
Databases
Recordsets
Querydef
Tabledef
5.6.1 Đối tượng Database
Database là đối tượng dùng để làm việc với một cơ sở dữ liệu. Với Access, một cơ sở dữ
liệu được coi như một file .MDB trong ổ đĩa của máy tính.
Khai báo đối tượng database như sau:
Dim objDB as DAO.Database - Khai báo biến objDB có kiểu đối tượng database
Sau khi đã khai báo biến objDB, muốn mở một cơ sở dữ liệu Access trong ổ cứng và gắn
biến objDB vào cơ sở dữ liệu đó, ta dùng chỉ thị:
Set objDB = OpenDatabase(“C:\THQL\Test.MDB”)
Ngoài ra, nếu có một cơ sở dữ liệu đang được mở (hiện tại đang được sử dụng) thì chúng ta
có thể gán biến objDB vào cơ sở dữ liệu hiện tại như sau:
Set objDB = CurrentDB
Mỗi lần mở một biến đối tượng database, hệ thống cần một vùng bộ nhớ nhất định để lưu
trữ nó. Do đó, khi không sử dụng biến đó nữa hoặc trước khi thoát khỏi chương trình, người lập
trình nên giải phóng bộ nhớ bằng cách đóng biến database đó lại. Cú pháp như sau:
objDB.Close
5.6.2 Đối tượng Recordset
Recordset là đối tượng được dùng để lưu trữ tập hợp tất cả các bản ghi của một bảng, một
truy vấn nào đó. Để khai báo và khởi tạo một recordset, ta làm như sau:
Dim rs as DAO.Recordset
Set rs = objDB.OpenRecordset (<nguồn dữ liệu>)
Ở đây, dòng 1 ta khai báo một biến rs có kiểu là đối tượng recordset. Dòng 2, ta thực hiện
việc gắn recordset đó vào một bảng, một tập giá trị trả về nào đó - phụ thuộc vào <nguồn dữ liệu>
trong đối tượng database objDB đã được mở ở trên. <nguồn dữ liệu> là một xâu ký tự chỉ ra
nguồn dữ liệu sẽ trả về cho Recordset. Xâu này có thể là tên 1 bảng trong cơ sở dữ liệu hoặc một
câu lệnh SQL hay một truy vấn trong cơ sở dữ liệu.
Ví dụ, ta có một file Nhansu.MDB lưu trữ trong ổ đĩa C của máy tính. Yêu cầu của chúng ta
là mở cơ sở dữ liệu đó, lấy ra thông tin về tất cả các nhân viên trong bảng “Nhanvien” và gắn nó
vào một Recordset, chúng ta làm như sau:
144
Phần 2: Sử dụng Access trong quản lý
Dim objDB as DAO.Database
Dim rs as DAO.Recordset
Set objDB = OpenDatabase(“C:\Nhansu.MDB”)
Set rs = objDB.OpenRecordset(“Nhanvien”)
…
Rs.Close
objDB.Close
Đối tượng Recordset có một số thuộc tính và phương thức đáng quan tâm sau:
- Thuộc tính AbsolutePosition: Cho biết vị trí của bản ghi hiện tại tính từ giá trị đầu tiên (có
vị trí là 0). Nếu recordset không có bản ghi nào hoặc đang ở bản ghi cuối cùng (EOF –
End Of File) thì thuộc tính này sẽ không thể lấy ra được do đó khi lấy thuộc tính này,
người dùng phải kiểm tra xem Recordset đã có bản ghi nào chưa bằng thuộc tính
RecordCount
- Thuộc tính RecordCount: Trả về số lượng bản ghi chứa trong một Recordset.
- Thuộc tính EOF/BOF: Kiểm tra xem bản ghi hiện tại có là bản ghi cuối cùng hay bản ghi
đầu tiên hay không.
- Thuộc tính Fields: Dùng để tham chiếu tới các trường trên các bản ghi mà Recordset lưu
trữ. Fields có đối số là một số nguyên chỉ vị trí của cột thứ mấy trong cấu trúc recordset
(tính từ vị trí 0) hoặc là một xâu chỉ tên của trường. Ví dụ, chúng ta có 1 recordset chứa
thông tin về nhân sự như sau:
STT Họ tên Tuổi
1 Nguyễn Văn A 19
2 Phạm Văn B 20
… …. …
Khi đó, nếu ta lấy rs.Fields(1) hay rs.Fields(“Họ tên”) thì ta sẽ được cùng 1 giá trị là trường
Họ tên trong rs. Tùy vào vị trí của bản ghi hiện tại, giá trị trường Họ tên của bản ghi đó sẽ được
trả về. Ví dụ, nếu bản ghi hiện tại là bản ghi đầu tiên, rs.Fields(1) = “Nguyễn Văn A”.
- Phương thức Close: Được dùng để đóng lại một Recordset đang mở khi thôi không làm
việc với recordset này nữa.
- Phương thức MoveFirst: Di chuyển bản ghi hiện thời về bản ghi đầu tiên trong Recordset.
- Phương thức MoveLast: Di chuyển bản ghi hiện thời về bản ghi cuối cùng trong
Recordset.
- Phương thức MoveNext: Di chuyển bản ghi hiện thời đến bản ghi kề sau.
145
Phần 2: Sử dụng Access trong quản lý
- Phương thức AddNew: Thêm một bản ghi trắng vào vị trí cuối cùng trong recordset.
Phương thức này luôn luôn phải đi cùng phương thức Update sẽ được trình bày ở dưới.
- Phương thức Edit: Sửa một bản ghi trong recordset bằng cách thay đổi giá trị của các
trường trong nó rồi sử dụng phương thức Update để cập nhật sự thay đổi.
- Phương thức Update: Cập nhật dữ liệu được thêm vào bởi phương thức AddNew hoặc
Edit.
- Phương thức Delete: Xoá bản ghi hiện tại trong recordset.
Ví dụ 1: Xét recordset ở ví dụ trên (bảng NhanVien), nếu muốn thêm 1 bản ghi mới vào
bảng và sửa đổi tuổi của nhân viên ở vị trí đầu tiên thành 50 (ví dụ đơn giản và ở đây trường STT
là tự tăng) ta làm như sau:
(Khai báo và mở cơ sở dữ liệu, mở recordset như đã trình bày ở trên)
//Thêm bản ghi mới
Rs.AddNew
Rs.Fields(“Họ Tên”) = “Nguyễn Văn C”
Rs.Fields(“Tuổi”) = 30
Rs.Update
//Sửa bản ghi đầu tiên
//Di chuyển về bản ghi đầu tiên để tiến hành sửa đổi
Rs.MoveFirst
Rs.Edit
Rs.Fields(“Tuổi”) = 50
Rs.Update
(Đóng recordset và cơ sở dữ liệu như đá trình bày ở trên.)
Ví dụ 2: Vẫn recordset ở ví dụ trên (bảng NhanVien), giả sử ta muốn kiểm tra xem trong
bảng Nhân viên đã có nhân viên nào với 1 mã số cho trước chưa, ta làm như sau:
(Khai báo và mở cơ sở dữ liệu, mở recordset như đã trình bày ở trên)
Dim maso as Integer
Dim timthay as Boolean
maso=<mã số cho trước>
timthay=False
//Di chuyển về bản ghi đầu tiên
Rs.MoveFirst
Do While not Rs.EOF
146