Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 13

Truyền giá trị từ Worksheet vào VBA Module

Có hai cách để lấy giá trị từ Worksheet vào trong mảng VBA. Bạn có thể dùng vòng lặp để lấy giá trị của
mỗi ô và lưu giá trị này vào các thành phần của một mảng (đây là cách thường hay sử dụng) hoặc
bạn có thể gán một Worksheet Range cho mảng VBA.

Tùy theo cách bạn dùng, mà tốc độ thực hiện chương trình của bạn nhanh hay chậm. Theo bạn hai cách
thức trên cách thức nào nhanh, cách thức nào chậm? Tôi nghĩ bạn có thể dễ dàng so sánh!
Một range xác định có thể dùng như một mảng trong một thủ tục
Nếu một (đối tượng) Range được gán cho một biến trong VBA, thì biến này có thể sử dụng như một
mảng.

Ví dụ: Gán vùng A1:A10 cho biến Mang

Mang=Range(“A1:A10”)

Hoặc nếu bạn đã đặt tên cho vùng A1:A10 là MangTam thì các bạn có thể dùng như sau:

Mang=Range(“MangTam”)

Lúc này mảng chúng ta sẽ có hai chiều, chiều của hàng và chiều của cột. Số hàng trở thành số phần tử
của chiều 1, số cột trở thành số phần tử của chiều 2.

Array(Rows, Columns)

Một điều chú ý nữa là cho dù bạn không khai báo Option Base 1 (có nghĩa là thứ tự mảng sẽ được bắt
đầu từ 1) thì khi bạn dùng mảng theo kiểu này (tức là từ một Range) thì thứ tự mảng bao giờ cũng bắt
đầu từ 1.

Chú ý nữa là, giá trị trong các ô của Range chưa được chuyển vào mảng VBA (internal VBA array);
mảng VBA chỉ đơn giản trỏ (points) vào mảng trên worksheet. Tuy nhiên các giá trị trong Range có thể
được truy cập giống như trong một mảng.

Theo các bạn sự khác nhau giữa

Mang=Range(“A1:A10”) ' Cách 1

Set Mang=Range(“A1:A10”) ' Cách 2

Là gì?

Đối với cách 1, bạn có thể dùng các hàm LBound và UBound để xác định cận trên và cận dưới của mảng.

Đối với cách 2, bạn phải dùng

Mang.Rows.Count

Mang.Columns.Count

để xác định số phần tử.

Chuyển các giá trị từ một mảng VBA sang Worksheet

Bạn có ít nhất hai cách để chuyển các giá trị từ một mảng VBA vào Worksheet.
1. Dùng vòng lập.
2. Gán giá trị từ mảng VBA vào các ô của Worksheet Range.

Cách thứ hai có thể gây lỗi khi bạn làm việc với mảng một chiều. Xin xem ví dụ sau:

Range(“E1:E10”).Value=TestArray

Dòng lệnh này tạo ra các giá trị giống nhau

Giả sử tôi có các giá trị từ ô A1 đến ô A10 như hình trên. Sau đó các bạn hãy copy đọan mã sau vào một
module và thực hiện thủ tụcTestArray.

1
2 Option Explicit
Option Base 1
3
4 Sub TestArray()
5 Dim Mang1(10)
6 Dim i As Integer
7 For i = 1 To 10
Mang1(i) = Range("A" & i).Value
8 Next i
9 Range("B1:B10").Value = Mang1
10 End Sub
11

Kết quả sẽ như hình sau:


Giá trị của ô A1 (phần tử đầu tiên của Mang1, tức là bằng 1) sẽ được gán cho các ô từ B1 đến B10 như
hình trên.

Nhưng nếu, Giả sử tôi có các giá trị từ ô A1 đến ô A10 và B1 đến B10 như hình trên. Sau đó các bạn hãy
copy đọan mã sau vào một module và thực hiện thủ tục TestArray1.

1 Option Explicit
Option Base 1
2
3 Sub TestArray1()
4 Dim Mang1(10, 10)
5 Dim i As Integer
6 For i = 1 To 10
Mang1(i, 1) = Range("A" & i).Value
7 Mang1(i, 2) = Range("B" & i).Value
8 Next i
9 Range("C1:D10").Value = Mang1
10
11 End Sub
12
13

Bạn sẽ được kết quả như hình sau:

Các giá trị trong mảng sẽ được gán trở lại cho Range đúng như các bạn mong đợi.

Với lỗi này chúng ta có ít nhất ba cách để khắc phục.

 Cách thứ nhất chúng ta sẽ dùng vòng lập. Đây là cách thường dùng (đã ví dụ ở phần trên).
 Cách thứ hai chúng ta sẽ khai báo thêm chiều thứ hai của mảng.

1 Option Explicit
Option Base 1
2
Sub TestArray2()
3 Dim Mang1(10, 1)
4 Dim i As Integer
5
6 For i = 1 To 10
Mang1(i, 1) = Range("A" & i).Value
7 Next i
8 Range("B1:B10").Value = Mang1
9 End Sub
10

Và chúng ta sẽ có kết quả đúng như hình dưới.

 Cách thứ ba chúng ta dùng hàm TRANSPOSE của Application.WorksheetFunction

1
2 Option Explicit
Option Base 1
3 Sub TestArray3()
4 Dim Mang1(10)
5 Dim i As Integer
6 For i = 1 To 10
Mang1(i) = Range("A" & i).Value
7
Next i
8 Range("B1:B10").Value = Application.WorksheetFunction.Transpose(Mang1)
9 End Sub
10

Tác giả: Lê Văn Duyệt

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.

Xem các trao đổi về mảng trong VBA rất sôi nổi tại đây
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 Sub TestArray2()
2
Dim Mang1()
3 Dim SoPhanTu As Integer, i As Integer
4 SoPhanTu = 100
5
6 ReDim Mang1(SoPhanTu)
7 For i = 1 To SoPhanTu
8 Mang1(i) = i
9 Next i
10
11
12
SoPhanTu = 101
13
14 ReDim Mang1(SoPhanTu)
15
16 Mang1(SoPhanTu) = SoPhanTu
17
Debug.Print Mang1(SoPhanTu)
18
19 End Sub
20
21

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

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.

You might also like