Làm việc với mảng trong một thủ tục

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ộtWorksheet 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ục TestArray.

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


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


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


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

Share on Google Plus