Làm việc với mảng trong VBA

Nếu bạn đã làm quen với các ngôn ngữ lập trình khác, tôi tin rằng bạn cũng đã từng nghe qua khái niệm về mảng.

Mảng là một tập hợp của nhiều biến liên quan (related variables) được gọi qua một tên. Ví dụ: Samples. Bạn có thể xác định một thành phần trong mảng thông qua một chỉ mục. Ví dụ: Samples(1): tức là lấy giá trị của phần tử có thứ tự là 1 trong mảng Samples.




KÍCH THƯỚC CỦA MỘT MẢNG

Khai báo Dim (viết tắt của chữ Dimention) được dùng để khai báo kích thước của một mảng. Thông thường phần tử của mảng sẽ được bắt đầu bằng chỉ mục 0. Vì vậy khi khai báo

Dim Samples(10)

Khi bạn khai báo như trên, có nghĩa mảng Samples của bạn có 11 phần tử.
Nếu muốn mảng được bắt đầu bằng chỉ mục 1, bạn phải khai báo

Option Base 1

ở đầu mỗi module mà bạn muốn.

Nhằm tránh việc nhằm lẫn các bạn nên luôn sử dụng mảng được bắt đầu bằng phần tử có chỉ mục 0.

Trong trường hợp khác bạn cũng có thể thực hiện được điều này bằng việc khai báo tường minh như sau:

Dim Samples(1 to 10)

Sử dụng tên của biến mảng để tham chiếu đến một mảng.
Mảng có thể có nhiều chiều, nhưng thông thường là mảng hai chiều.

Ví dụ khai báo mảng hai chiều như sau:

Option Base 1
Dim GPE(500,2) ‘Mảng 500 dòng, 2 cột


Tương đương với khai báo sau:

Dim GPE(1 to 500,1 to 2) ‘Mảng 500 dòng, 2 cột


KHAI BÁO KIỂU BIẾN CỦA MẢNG

Khai báo kiểu biến cho các phần tử rất quan trọng tại sao? Vì với một mảng có nhiều phần tử, nếu bạn khai báo không rỏ ràng thì tài nguyên bộ nhớ sẽ bị chiếm dụng.

Dim TenBien(Lower To Upper) As Type 'Lower: cận dưới; Upper: cận trên

Ví dụ: Dim GPE(1 to 500) as Long

Khi khai báo nhiều biến bạn có thể dùng một khai báo Dim, nhưng phải cách nhau bằng As Type cho mỗi biến. Vì vậy bạn phải khai báo như sau:

Dim J As Integer, K As Integer

TRẢ VỀ KÍCH THƯỚC CỦA MỘT MẢNG

Chúng ta dùng hai hàm LBound và UBound để xác định kích thước dưới và trên của mảng.

LBound(ArrayName, Dimension)
UBound(ArrayName, Dimension)


ArrayName: tên mảng.
Dimension: chiều của mảng cần kiểm tra.

Ví dụ: khi chúng ta khai báo mảng 2 chiều

Dim GPE(1 to 500,1 to 2) ‘mảng 2 chiều: 500 dòng, 2 cột

LBound(GPE,1) → sẽ trả về 1
UBound(GPE,1) → sẽ trả về 500

LBound(GPE,2) → sẽ trả về 1
UBound(GPE,2) → sẽ trả về 2


MẢNG ĐỘNG (DYNAMIC ARRAY)

Nếu bạn không biết kích thước của mảng khi khai báo, bạn phải dùng mảng động. Mảng động cho phép bạn khai báo mảng và khai báo kích thước mảng sau.

Bạn sẽ khai báo mảng bình thường nhưng không cần khai báo kích thước như sau:

Dim Mang1(), Mang2()

Sau đó để khai báo lại bạn dùng từ ReDim

Giả sử sau khi bạn khai báo mảng động như trên, sau đó bạn biết được mảng bạn sử dụng cần bao nhiêu phần tử bạn sẽ dùng ReDim để khai báo lại như sau:

Dim Mang1(), Mang2()

SoPhanTu= 100

ReDim Mang1(SoPhanTu), Mang2(SoPhanTu)


Trong một thủ tục bạn có thể dùng nhiều lần ReDim. Khi bạn dùng ReDim thì các phần tử bên trong của mảng sẽ bị xóa. Ví dụ:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Sub TestArray2()
  
    Dim Mang1()
    Dim SoPhanTu As Integer, i As Integer
    SoPhanTu = 100
  
    ReDim Mang1(SoPhanTu)
  
    For i = 1 To SoPhanTu
        Mang1(i) = i
    Next i
  
    SoPhanTu = 101
  
    ReDim Mang1(SoPhanTu)
  
    Mang1(SoPhanTu) = SoPhanTu
  
    Debug.Print Mang1(SoPhanTu)
  
End Sub


Trong ví dụ trên, lần đầu tiên bạn khai báo số phần tử là 100, sau đó gán giá trị cho các phần tử của mảng là chính số thứ tự của các phần tử. Sau đó bạn dùng ReDim để khai báo lại số phần tử và gán phần tử mới, tức là phần tử thứ 101 của mảng, với giá trị là 101.

Bạn chú ý cho rằng các phần từ từ 1 đến 100 đã bị xóa giá trị khi bạn dùng khai báo ReDim.

Vậy nếu muốn không xóa giá trị của các phần tử trước đây chúng ta phải dùng từ khóa Preserve để khai báo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Sub TestArray3()
  
    Dim Mang1()
    Dim SoPhanTu As Integer, i As Integer
    SoPhanTu = 100
  
    ReDim Mang1(SoPhanTu)
  
    For i = 1 To SoPhanTu
        Mang1(i) = i
    Next i
  
    SoPhanTu = 101
  
    ReDim Preserve Mang1(SoPhanTu)
  
    Mang1(SoPhanTu) = SoPhanTu
  
    Debug.Print Mang1(100)
  
End Sub


Chú ý rằng khai báo Preserve chỉ có tác dụng ở cận trên của chiều (của mảng) cuối cùng mà thôi. Do đó nếu bạn khai báo như sau là hợp lệ:

Dim Mang1(2,100)
.
.
ReDim Preserve Mang1(2,SoPhanTu)

Nhưng nếu bạn khai báo như sau sẽ bị lỗi

Dim Mang1(2,100)
.
.
ReDim Preserve Mang1(SoPhanTu,2)

Nếu bạn sử dụng Preserve, bạn không thể dùng ReDim để thay đổi số phần tử của một mảng.
Share on Google Plus