Array_Mảng | Tự Học VBA

Menu Tự học VBA
  • Trang chủ
  • Diễn đàn Bài viết mới Tìm chủ đề
  • Có gì mới Bài viết mới Hoạt động mới nhất
Đăng nhập Đăng ký Có gì mới? Tìm kiếm

Tìm kiếm

Everywhere Chủ đề This forum This thread Chỉ tìm trong tiêu đề Bởi: Tìm Tìm kiếm nâng cao…
  • Bài viết mới
  • Tìm chủ đề
Menu Đăng nhập Đăng ký
  • Cách upload ảnh lên diễn đàn
  • Trang chủ
  • Diễn đàn
  • Kỹ thuật xử lý Excel
  • Lập trình VBA
Array_Mảng
  • Thread starter tuhocvba
  • Ngày gửi 8/6/19
  • 1
  • 2
Tiếp 1 of 2

Đi đến trang

Tới Tiếp Last tuhocvba

tuhocvba

Administrator
Thành viên BQT 1. Khái niệm mảng (array): Sách tin học đã quá nhiều, các bạn cũng có thể google. Tuy nhiên mình trình bày đơn giản như thế này: Mảng là một dãy các phần tử có cùng tính chất. Ví dụ ta có 2000 phần tử là số nguyên. Vậy thì ta sẽ khai báo mảng có kích thước là 2000 phần tử, rồi nạp giá trị số nguyên cho các phần tử của mảng. Hoặc: Ta có 2000 phần tử là chuỗi ký tự. Vậy thì ta sẽ khai báo mảng có kích thước là 2000 phần tử, rồi nạp giá trị là chuỗi ký tự cho các phần tử của mảng. Các phần tử chưa được nạp giá trị sẽ có giá trị là rỗng (null). 2. Các thông số cơ bản của mảng: Kích thước mảng: Là số phần tử của mảng. Ở hình vẽ dưới đây, kích thước mảng là 6. Mảng có 6 phần tử. Bạn cần đăng nhập để thấy đính kèm // Hình ảnh minh họa trên có sai sót. array size = 6 là đúng. Kiểu giá trị của mảng: Tùy thuộc vào khai báo. Thông thường hay sử dụng là String (chuỗi ký tự). Hoặc không khai báo, tùy ý xử lý sau. Chỉ mục của mảng: Phần tử số 0, phần tử số 1, phần tử số 2,... Vậy các số 0,1,2,... là chỉ mục của mảng. Thông thường chỉ mục bắt đầu từ 0 hoặc từ 1. Ở hình ảnh minh họa ở trên, chỉ mục bắt đầu từ 0 cho tới 5. Chú ý, trong VBA chúng ta dùng dấu ngoặc tròn để thể hiện phần tử mảng. Ví dụ arr(5) là phần tử mảng ở chỉ mục số 5. Mã: Sub vidu1() Dim arr(0 To 5) As Integer Dim n1 As Integer Dim n2 As Integer arr(0) = 19 arr(1) = 2019 arr(2) = 2015 arr(3) = 20 arr(4) = 21 arr(5) = 22 n1 = LBound(arr) n2 = UBound(arr) End Sub Chương trình trên có kích thước được khai báo là từ 0 tới 5, tức kích thước mảng là 6. Chúng có kiểu giá trị là số nguyên integer. Ta chú ý tới Lbound, là chỉ số nhỏ nhất của mảng, ở code trên, chỉ số này sẽ là 0. Ubound là chỉ số lớn nhất của mảng, ở code này, chỉ số này sẽ là 5. Như vậy kích thước mảng theo toán học sẽ tính bằng công thức: Ubound - Lbound + 1 3. Dẫn giải qua các ví dụ: Ví dụ số 1: Kết quả của chương trình như sau: Bạn cần đăng nhập để thấy đính kèm Ở kết quả trên, tôi đã cho các bạn thấy Lbound được tính ra là 0 (chỉ số nhỏ nhất của mảng), Ubound là 5 (chỉ số lớn nhất của mảng). Bây giờ câu hỏi đặt ra là: Các phần tử của mảng nếu chưa được nạp giá trị thì nó có giá trị mặc định là bao nhiêu? Ta sẽ chặn chương trình tại vị trí nạp phần tử mảng số 3. Bạn cần đăng nhập để thấy đính kèm Như vậy câu trả lời là: Với dạng khai báo là số nguyên (integer), giá trị mặc định là 0. Do đó nếu chưa được nạp giá trị thì nó có giá trị là 0. Nếu mảng được khai báo là chuỗi kí tự, và khi chưa được nạp giá trị nó sẽ như thế nào? Ví dụ số 2: Mã: Sub vidu2() Dim arr(0 To 5) As String Dim n1 As Integer Dim n2 As Integer arr(0) = "hay tham gia website nhe" arr(1) = "tuhocvba.net" arr(2) = "chuc cac ban" arr(3) = "luon tim duoc" arr(4) = "nhung bai hoc" arr(5) = "bo ich" n1 = LBound(arr) n2 = UBound(arr) End Sub Chúng ta cùng xem kết quả dưới đây: Bạn cần đăng nhập để thấy đính kèm Như vậy kết quả là chuỗi kí tự rỗng "". Chúng ta hãy chú ý điều này để có cách xử lý phù hợp trong các chương trình khi sử dụng mảng. Euler

Euler

Administrator
Thành viên BQT Thực tế với excel có hàng và cột, do đó ta nghĩ ngay tới mảng hai chiều. Đây cũng là mảng thường được dùng. Tất nhiên không chỉ là mảng hai chiều, chúng ta có thể khai báo mảng nhiều chiều, tùy vào mục đích sử dụng. Bạn cần đăng nhập để thấy hình ảnh Mảng hai chiều: Chú ý lúc này muốn truy vấn các chỉ số của mảng ta phải thêm tham số. Ví dụ: Lbound(arr) thì không còn hiểu được, phải ghi là Lbound(arr,1) để macro hiểu là đang muốn truy vấn chỉ số nhỏ nhất của chiều thứ nhất (số thứ tự hàng), và Lbound(arr,2) thì macro hiểu là đang muốn truy vấn chỉ số nhỏ nhất của chiều thứ hai (số thứ tự cột). Ví dụ: Mã: Sub vidu2() Dim arr(0 To 3, 0 To 4) As String Dim d1 As Integer Dim d2 As Integer Dim n1 As Integer Dim n2 As Integer arr(1, 2) = 200 d1 = LBound(arr, 1) d2 = UBound(arr, 1) n1 = LBound(arr, 2) n2 = UBound(arr, 2) End Sub Kết quả: Bạn cần đăng nhập để thấy hình ảnh Nạp giá trị từ excel vào mảng, ta được mảng hai chiều, mặc định các chỉ mục nhỏ nhất bắt đầu từ 1. Bạn cần đăng nhập để thấy hình ảnh Mã: Sub Test1() Dim Arr Dim d1 As Integer Dim d2 As Integer Dim n1 As Integer Dim n2 As Integer Arr = Range("A1:J2").Value d1 = LBound(Arr, 1) d2 = UBound(Arr, 1) n1 = LBound(Arr, 2) n2 = UBound(Arr, 2) End Sub Kết quả: Bạn cần đăng nhập để thấy hình ảnh Hiện chưa thấy có khuyến cáo khi nạp giá trị excel vào mảng phải active workbook và sheet cần lấy, tuy nhiên để tránh nhầm lẫn, bạn nên ghi rõ workbook nào, sheet nào. Mã: Arr = ThisWorkbook.Sheets(2).Range("A1:J2").Value Gán giá trị excel bằng mảng cũng tương tự, không có khuyến cáo phải active nhưng cần ghi rõ thông tin workbook và sheet để tránh nhầm lẫn: Mã: ThisWorkbook.Sheets(1).Range("A1:J2").Value = Arr vbano1

vbano1

SMod
Thành viên BQT Xóa phần tử trong mảng: Bài toán của tôi hôm nay là xóa một phần tử trong mảng. Nghe tới điều này, có lẽ nhiều bạn sẽ nghĩ rằng, mình cần phải khai báo lại mảng. Nếu phần tử cần xóa nằm ở cuối danh sách (hoặc đầu danh sách) trong mảng, mọi chuyện sẽ dễ dàng. Tôi ví dụ: Bạn cần đăng nhập để thấy đính kèm Nếu tôi khai báo lại bằng Redim thì kích thước mảng sẽ thay đổi nhưng giá trị mảng vốn có sẽ bị mất hết. Do đó chúng ta không dùng Redim, chúng ta dùng Redim preserve: Mã: Redim preserve arr(1 to 5) Kích thước mảng sẽ thay đổi, giá trị các phần tử của mảng như thế nào thì vẫn được giữ nguyên. Mọi chuyện sẽ trở nên phức tạp hơn nếu phần tử mảng cần xóa nằm ở giữa danh sách. Và như vậy chúng ta có một cách khác như sau, hi vọng có ích cho những người quan tâm: Mã: Private Sub Form_Load() Dim arr As New Collection arr.Add "Viet Nam" arr.Add "Nhat Ban" arr.Add "Cam pu chia" arr.Add "Han Quoc" MsgBox "SL: " & arr.Count & " Key: " & arr.Item(3) arr.Remove 3 MsgBox "SL: " & arr.Count & " Key: " & arr.Item(3) End Sub Kết quả: Bạn cần đăng nhập để thấy đính kèm tuhocvba

tuhocvba

Administrator
Thành viên BQT 1. Làm việc bằng mảng trên excel. Nếu chúng ta chỉ quan tâm tới dữ liệu mà không quan tâm tới format (định dạng cells như màu mè, kẻ ô), khi đó gán giá trị bảng tính vào mảng sẽ cho tốc độ chương trình nhanh hơn là xử lý trực tiếp trên bảng tính excel. 1.1 Active sheet cần làm việc. Bước 1: Active sheet chúng ta muốn làm việc. Nếu không tiến hành, có thể xảy ra lỗi trong quá trình gán. Workbooks(tên_workbook_làm_việc).Sheets(tên_sheet).Activate 1.2 Thực hiện gán giá trị cho mảng Bước 2: Thực hiện gán. arr = Workbooks(tên_workbook_làm_việc).Sheets(tên_sheet).Range(địa_chỉ_vùng_range).value Ví dụ: Mã: Sub ganmang() Dim arr As Variant ThisWorkbook.Sheets(1).Activate arr = ThisWorkbook.Sheets(1).Range(Cells(3, 2), Cells(19, 3)).Value End Sub Các chỉ số của mảng sẽ bắt đầu bắt đầu từ 1. Lbound(arr,1) = 1 'chỉ số đầu tiên của dòng Lbound(arr,2) = 1 'chỉ số đầu tiên của cột Ubound(arr,1) = 17 'chỉ số cuối cùng của dòng Ubound(arr,2) = 2 'chỉ số cuối cùng của cột Bạn cần đăng nhập để thấy đính kèm Tương tự, ta cũng có thể làm ngược lại để gán giá trị một vùng Range: Mã: ThisWorkbook.Sheets(1).Range(Cells(3, 2), Cells(19, 3)).Value = arr 2. Chú ý khi gán Range = Mảng: Chúng ta hãy xem xét ví dụ dưới đây: Mã: Sub gan2() Dim arr(1 To 17) As Integer Dim i As Integer For i = 1 To 17 Step 1 arr(i) = i Next i ThisWorkbook.Sheets(1).Range(Cells(3, 2), Cells(19, 2)).Value = arr() End Sub Kết quả dưới đây sẽ làm các bạn bất ngờ: Bạn cần đăng nhập để thấy đính kèm Cái gì thế này. Giá trị của mảng hoàn toàn đúng ý đồ. Vậy tại sao gán trên cột B lại thành ra như thế này hả trời? Chúng ta sẽ quay trở lại với vấn đề này sau. Nào bây giờ, tiếp tục thử phép gán khác nhé: Mã: Sub gan2b() Dim arr(1 To 17) As Integer Dim i As Integer For i = 1 To 17 Step 1 arr(i) = i Next i ThisWorkbook.Sheets(1).Range(Cells(3, 2), Cells(3, 18)).Value = arr End Sub Bạn cần đăng nhập để thấy đính kèm ồ, lần này thì mọi thứ diễn ra suôn sẻ, theo đúng ý đồ rồi. Chúng ta đã lờ mờ đoán ra vấn đề nằm ở đâu. Nó tương tự như thao tác copy và paste từ cột thành hàng. Và ở đây, chúng ta hiểu mảng một chiều tương tự một hàng. Và khi chuyển nó thành cột ta cần phải qua một thủ thủ tục trung gian Transpose: Mã: Sub gan3() Dim arr(1 To 17) As Integer Dim i As Integer For i = 1 To 17 Step 1 arr(i) = i Next i ThisWorkbook.Sheets(1).Range(Cells(3, 2), Cells(19, 2)).Value = WorksheetFunction.Transpose(arr) End Sub Kết quả bây giờ đã đúng như ý muốn của chúng ta: Bạn cần đăng nhập để thấy đính kèm Để tìm hiểu xem nó là cái gì, ta sẽ cho thêm mảng brr vào để xem đi qua Transpose nó thành cái gì nhé. Mã: Sub gan3b() Dim arr(1 To 17) As Integer Dim brr As Variant Dim i As Integer For i = 1 To 17 Step 1 arr(i) = i Next i brr = WorksheetFunction.Transpose(arr) 'Mảng brr sẽ biến thành mảng hai chiều ThisWorkbook.Sheets(1).Range(Cells(3, 2), Cells(19, 2)).Value = brr 'Phép gán cho kết quả đúng ý đồ End Sub Bạn cần đăng nhập để thấy đính kèm //Hình minh họa trên có sai sót. Đính chính: Mảng một chiều, không có chỉ số cột. Thì ra là vậy, sau khi đi qua Transpose thì mảng một chiều trở thành mảng hai chiều, và để gán cột = mảng thì mảng đó phải là mảng hai chiều. giaiphapvba

giaiphapvba

Administrator
Thành viên BQT Như vậy, chúng ta thấy rằng, gán cho cột thì phải dùng mảng hai chiều. Và gán cho hàng sẽ phải dùng mảng một chiều. Thật vậy: Ta xét ví dụ sau: Mã: Sub ganmang1() Dim arr(1 To 10, 1 To 1) As Integer Dim i As Integer For i = 1 To 10 Step 1 arr(i, 1) = i Next i ThisWorkbook.Sheets(1).Range(Cells(1, 1), Cells(1, 10)) = arr End Sub Ở trên ta dùng mảng hai chiều (có một cột) và gán cho hàng. Và đây là kết quả: Bạn cần đăng nhập để thấy đính kèm Vấn đề tương tự như bài viết trước đã xuất hiện. Kết quả trên không như mong muốn của chúng ta. Bây giờ ta sửa lại code: Mã: Sub ganmang2() Dim arr(1 To 10, 1 To 1) As Integer Dim brr As Variant Dim i As Integer For i = 1 To 10 Step 1 arr(i, 1) = i Next i brr = WorksheetFunction.Transpose(arr) 'Biến mảng hai chiều thành mảng một chiều ThisWorkbook.Sheets(1).Range(Cells(1, 1), Cells(1, 10)) = brr End Sub Kết quả: Bạn cần đăng nhập để thấy đính kèm Như vậy ta đi tới kết luận: -Hàm Transpose sẽ biến mảng một chiều thành mảng hai chiều(có một cột), và ngược lại, biến mảng hai chiều (có một cột) thành mảng một chiều. -Gán cho cột thì phải dùng mảng hai chiều. Và gán cho hàng thì phải dùng mảng một chiều. (Điều quan trọng cần phải nhớ) Tổng quát về Transpose: Chúng ta biết excel có lệnh copy và paste. Tuy nhiên bây giờ thay vì paste thông thường, ta paste Transpose, thì bạn sẽ thấy nó biến hình chữ nhật đứng thành nằm ngang và ngược lại. Từ đó chúng ta hiểu rằng, thực ra đó là đảo chiều mảng. Bạn cần đăng nhập để thấy đính kèm Thật vậy, tôi sẽ chạy code sau để kiểm tra hình dung của mình là đúng hay sai nhé. Bạn cần đăng nhập để thấy đính kèm Mảng brr có 2 hàng và 3 cột đúng như chúng ta dự đoán. Giá trị của hàng 1 lần lượt là : 1,2,3 Giá trị của hàng 2 lần lượt là: 4,5,6. Kết quả này hoàn toàn giống với thao tác bằng tay khi tôi thực hiện copy và paste transpose. Vậy đến đây các bạn đã rõ về Transpose chưa nào :) Euler

Euler

Administrator
Thành viên BQT Các bài viết trên, chúng ta thấy rằng khi gán mảng arr = Range(địa chỉ range).value, chúng ta sẽ có được mảng hai chiều, các chỉ số bắt đầu ở cả chiều ngang và chiều dọc là 1: arr(1,y) dòng bắt đầu là 1, cột y bất kỳ; hoặc arr(x,1) cột bắt đầu là 1, dòng x bất kỳ. Liên quan tới mảng, tôi muốn các bạn nhớ lại lệnh phân tách ký tự trả kết quả là mảng. Split(Ký_tự_nguồn,Ký_tự_phân_tách) Tôi ví dụ: Tôi có chuỗi "1,2,3,4,5,6,7,8" các ký tự được phân tách bởi dấu phẩy ",". Vậy thì tôi sẽ dùng lệnh split để tách chuỗi này ra. Và câu hỏi bây giờ là: Phần tử đầu tiên có chỉ số trong mảng là 1 hay 0? Câu trả lời là 0. Hãy xem ví dụ dưới đây: Mã: Sub test() Dim str_op As String Dim arr As Variant str_op = "1,2,3,4,5,6,7,8" arr = Split(str_op, ",") End Sub Bạn cần đăng nhập để thấy đính kèm Như vậy, các bạn chú ý sự khác biệt khi phân tách, chỉ số đầu tiên của mảng là 0:arr(0). Bạn cần đăng nhập để thấy đính kèm V

vothanhthu

Guest
Qua ví dụ trên, ta có thể thấy được rằng mảng có thể được tách ra khi dùng hàm Split. Vậy có trường hợp nào ngược lại để nối các phần tử trong mảng lại với nhau không, câu trả lời là có và đó là hàm Join. Join(Mảng_cần_nối,[Dấu_phân_cách]) Trong đó: Mảng_cần_nối: Đây là tham số bắt buộc. Mảng chứa các phần tử mang giá trị cần nối [Dấu_phân_cách]: Ngoặc [] biểu thị cho đây là một tham số tùy chọn, có thể có hoặc có thể không. Nếu để trống, các phần tử sẽ nối với nhau bằng dấu cách. Nếu có kí tự, các phần tử sẽ nối với nhau bằng kí tự đó. Ví dụ: Mình có mảng đặt tên là Arr gồm 5 phần tử là các chuỗi kí tự, mình sẽ dùng hàm Join để nối các phần tử này lại với nhau bằng cả 2 cách(có tham số Dấu_phân_cách và không có tham số Dấu_phân_cách) Mã: Sub Join_Arr() Dim Arr(0 To 4) As String Dim RQ_0 As String Dim RQ_1 As String Arr(0) = "Chung toi" Arr(1) = "Chinh la" Arr(2) = "Dien dan" Arr(3) = "Tu hoc" Arr(4) = "VBA" RQ_0 = Join(Arr) RQ_1 = Join(Arr, "-") End Sub Bạn cần đăng nhập để thấy đính kèm Bạn cần đăng nhập để thấy đính kèm Qua ví dụ chúng ta có thể thấy rằng, hàm Join này sẽ nối các phần tử trong mảng lại với nhau thông qua tham số Dấu_phân_cách. Thật đơn giản và dễ sử dụng. tuhocvba

tuhocvba

Administrator
Thành viên BQT Gán giá trị cho mảng: Nếu viết như thế này thì oải thật. Mã: arr(0) ="A" arr(1) ="B" arr(2) ="C" Chúng ta có cách viết gọn hơn như sau: Mã: Sub test() Dim arr arr = Array("A", "B", "C") End Sub Euler

Euler

Administrator
Thành viên BQT Trong excel có sort để sắp xếp, rất nhanh. Trong mảng thì sao đây? Nếu là số, thuật toán sắp xếp đã có nhiều trong các sách tin học tôi không bàn nữa, nhưng các bạn lưu ý, đã từng có phàn nàn về tốc độ xử lý sắp xếp chậm nếu số lượng phần tử trong mảng lên tới khoảng 2000 phần tử, ấy là chưa nói tới việc sắp xếp chạy vòng lặp nhiều lần, và chúng ta hãy nhớ tới topic sau nếu chúng ta cần sắp xếp mảng là số theo thứ tự tăng/giảm: Bạn cần đăng nhập để thấy link Tuy nhiên nếu là alphabe (A~Z), tức là giá trị của các phần tử của mảng là ký tự, chúng ta sắp xếp như thế nào đây? Không lẽ phải ghi ra excel để sort rồi nạp lại vào mảng? Hôm nay, xin đưa ra một giải pháp xử lý sắp xếp này trên mảng: Mã: Sub RunTheSortMacro() Dim i As Long Dim myArray As Variant 'Set the array myArray = Array("p", "A", "G", 3, "l", "6", 10, "K", 7) 'myArray variable set to the result of SortArrayAtoZ function myArray = SortArrayAtoZ(myArray) 'Output the Array through a message box For i = LBound(myArray) To UBound(myArray) MsgBox myArray(i) Next i End Sub Phần code chính: Sort the array A-Z Mã: Function SortArrayAtoZ(myArray As Variant) Dim i As Long Dim j As Long Dim Temp 'Sort the Array A-Z For i = LBound(myArray) To UBound(myArray) - 1 For j = i + 1 To UBound(myArray) If UCase(myArray(i)) > UCase(myArray(j)) Then Temp = myArray(j) myArray(j) = myArray(i) myArray(i) = Temp End If Next j Next i SortArrayAtoZ = myArray End Function Sort the array Z-A Mã: Function SortArrayZtoA(myArray As Variant) Dim i As Long Dim j As Long Dim Temp 'Sort the Array Z-A For i = LBound(myArray) To UBound(myArray) - 1 For j = i + 1 To UBound(myArray) If UCase(myArray(i)) < UCase(myArray(j)) Then Temp = myArray(j) myArray(j) = myArray(i) myArray(i) = Temp End If Next j Next i SortArrayZtoA = myArray End Function Nguồn tham khảo: Bạn cần đăng nhập để thấy link giaiphapvba

giaiphapvba

Administrator
Thành viên BQT Chèn thêm (hoặc xóa) phần tử vào vị trí bất kỳ trong mảng. 1. Đặt vấn đề : Nói tới chủ đề này nhiều người sẽ nghĩ ngay tới Bạn cần đăng nhập để thấy link . Tuy nhiên nó chỉ giúp chúng ta thêm bớt phần tử vào cuối mảng. Nếu vị trí muốn thêm bớt nằm ở giữa mảng thì sao? Đây là vấn đề vẫn luôn làm đau đầu nhiều người, vì trong VBA không cung cấp cho chúng ta công cụ này. Do đó, chỉ còn cách là tự xây dựng hàm hay thủ tục riêng để thực hiện điều này. 2. Thêm phần tử vào vị trí bất kỳ trong mảng: Mã: Sub InsertToArray(a_Ary, a_Data, a_iPosition) Dim i '// Dùng để chạy vòng lặp Dim iCount '// Số phần tử của mảng '// Số phần tử của mảng, ta muốn thêm 1 phần tử vào mảng cho nên: iCount = UBound(a_Ary) + 1 '// Lưu lại giá trị vốn có của mảng ReDim Preserve a_Ary(iCount) '// Trường hợp vị trí muốn thêm phần tử mới vượt ra ngoài phạm vi kích thước mảng: If a_iPosition > iCount Then a_iPosition = iCount End If '// Từ vị trí cuối của mảng tới vị trí thêm phần tử mới: For i = iCount To a_iPosition + 1 Step -1 '// Lưu lại giá trị vốn có từ vị trí i-1 trở về vị trí đầu tiên trong mảng a_Ary Call SetValue(a_Ary(i - 1), a_Ary(i)) Next '// Thêm dữ liệu a_Data vào vị trí a_iPosition của mảng a_Ary Call SetValue(a_Data, a_Ary(a_iPosition)) End Sub 3. Xóa vị trí bất kỳ trong mảng: Mã: Sub EraseToArray(a_Ary, a_iPosition) Dim i '// Thực hiện vòng lặp Dim iCount '// Số phần tử của mảng '// Lấy số phần tử của mảng iCount = UBound(a_Ary) '// Từ vị trí chỉ định cho tới ngay trước vị trí kết thúc của mảng: For i = a_iPosition To iCount - 1 Call SetValue(a_Ary(i + 1), a_Ary(i)) Next '// Xóa một phần tử: ReDim Preserve a_Ary(iCount - 1) End Sub 4. Hàm copy dữ liệu: Trong mục 2 và mục 3 đã trình bày ở trên, dữ liệu đầu vào của mảng là cái gì cũng OK. Có nghĩa là mảng đó là integer hay string, hay Range, hay là kiểu Dictionary thì cũng đều hoạt động. Tuy nhiên có sự khác biệt nếu biến là kiểu Object hoặc không phải Object. Nếu biến là Object thì phép gán dữ liệu phải dùng Set. Nếu bạn không nhớ kiến thức này, xin xem lại Bạn cần đăng nhập để thấy link . Do đó, chúng ta cần xây dựng hàm copy dữ liệu có thể làm được viện toàn năng, là Object hay không phải là Object thì cũng chẳng quan tâm, tôi vẫn thực hiện copy được dữ liệu cho bạn. Mã: Sub SetValue(a_From, a_To) Dim bType As Boolean '// Kiểu dữ liệu của mảng là Object hay không? '// Kiểm tra kiểu dữ liệu là Object hay không bType = IsObject(a_From) '// Là Object thì: If bType = True Then Set a_To = a_From '// Không phải là Object thì: Else a_To = a_From End If End Sub 5. Ví dụ về cách sử dụng: Kiểu dữ liệu là String hay là Range thì cũng chẳng quan tâm. Ta sẽ thực hiện thêm dữ liệu vào vị trí tùy ý trong mảng. Sau đó ta sẽ thực hiện xóa dữ liệu ở vị trí tùy ý trong mảng: Mã: Sub InsertEraseToArrayTest() Dim arString() As String '// Mảng có kiểu dữ liệu là String Dim arRange() As Range '// Mảng có kiểu dữ liệu là Range Dim i As Long '// Thực hiện vòng lặp '// Khởi tạo mảng ReDim arString(7) ReDim arRange(7) arString(0) = "a" arString(1) = "b" arString(2) = "c" arString(3) = "d" arString(4) = "e" arString(5) = "f" arString(6) = "g" arString(7) = "h" Set arRange(0) = Range("A1") Set arRange(1) = Range("A2") Set arRange(2) = Range("A3") Set arRange(3) = Range("A4") Set arRange(4) = Range("A5") Set arRange(5) = Range("A6") Set arRange(6) = Range("A7") Set arRange(7) = Range("A8") '// Thêm phần tử mới vào mảng vào vị trí thứ 1 trong mảng string, vào vị trí 0 trên mảng Range Call InsertToArray(arString, "abc", 1) Call InsertToArray(arRange, Range("G100"), 0) '// Ghi kết quả với mảng String: For i = 0 To UBound(arString) Debug.Print CStr(i) & " - " & arString(i) Next '// Ghi kết quả với mảng Range For i = 0 To UBound(arRange) Debug.Print CStr(i) & " - " & arRange(i).Address(False, False) Next Debug.Print "" '// Xóa dữ liệu Call EraseToArray(arString, 1) Call EraseToArray(arRange, 0) '// Ghi kết quả với mảng String For i = 0 To UBound(arString) Debug.Print CStr(i) & " - " & arString(i) Next '// Ghi kết quả với mảng Range For i = 0 To UBound(arRange) Debug.Print CStr(i) & " - " & arRange(i).Address(False, False) Next End Sub Kết quả: Mã: 0 - a 1 - abc 2 - b 3 - c 4 - d 5 - e 6 - f 7 - g 8 - h 0 - G100 1 - A1 2 - A2 3 - A3 4 - A4 5 - A5 6 - A6 7 - A7 8 - A8 0 - a 1 - b 2 - c 3 - d 4 - e 5 - f 6 - g 7 - h 0 - A1 1 - A2 2 - A3 3 - A4 4 - A5 5 - A6 6 - A7 7 - A8 Nguồn tham khảo và dịch: Bạn cần đăng nhập để thấy link tuhocvba

tuhocvba

Administrator
Thành viên BQT Lấy các phần tử của mảng mà chúng chứa chuỗi ký tự mà ta chỉ định bằng Filter: Cấu trúc: Function Filter(SourceArray, Match As String, [Include As Boolean = True], [Compare As VbCompareMethod = vbBinaryCompare]) As Variant
SourceArrayĐối tượng mảng mà chúng ta thực thi tìm kiếm trong đó. Chú ý chỉ dùng được mảng một chiều. Nếu không phải mảng một chiều thì sẽ lỗi.
MatchChỉ định chuỗi ký tự (từ khóa) tìm kiếm
Include (có thể giản lược)Tìm phần tử mảng chứa từ khóa tìm kiếm thì để là True. Nếu không chứa từ khóa tìm kiếm thì để là False. Nếu giản lược, tham số này mặc định là True.
Compare (Chế độ so sánh-có thể giản lược)
Hằng sốGiá trịNội dung
vbBinaryCompare0Phân biệt chữ in hoa và chữ thường, người dùng Nhật Bản: phân biệt bộ gõ zenkaku và hankaku, phân biệt hiragana và katakana
vbTextCompare 1Không phân biệt chữ in hoa và chữ thường,...
Nếu giản lược, mặc định sẽ là vbBinaryCompare
Giá trị trả vềTrả về là mảng
Code mẫu: Mã: Sub FilterTest() Dim ar(5) Dim v ar(0) = "abc" ar(1) = "A" ar(2) = " a " ar(3) = " b " ar(4) = " B " ar(5) = " B " v = Filter(ar, "B", True, vbTextCompare) Dim s For Each s In v Debug.Print "[" & s & "]" Next End Sub Kết quả: Mã: [abc] [ b ] [ B ] [ B ] Nguồn tham khảo và dịch: Bạn cần đăng nhập để thấy link P

PTHhn

Yêu THVBA như điếu đổ
Trước hết cho tôi cám ơn các viết bổ ích của các bạn trên diễn đàn. Tôi có mấy kiến thức sau chia sẻ cùng các bạn. Nạp giá trị khởi tạo cho mảng: Trên VBA, ta không thể khai báo một mảng toàn cục kiểu như thế này: Mã: Const c_mangArray() As String _ = Array("XinchaoCacBan", "tuhocvba.net", "VN") Thử biên dịch, các bạn sẽ thấy là có thông báo lỗi hiện ra. Tôi thấy Bạn cần đăng nhập để thấy link , admin tuhocvba đã có xử lý rất khéo. Mã: Public ngaylerr As Variant Sub thietdinhngayle() ngaylerr = Array("1/1", "9/2") End Sub Mặc dù không khai báo dưới đạng hằng số rồi gán giá trị trực tiếp ngay khi khai báo, nhưng bằng cách gọi một thủ tục để thực hiện phép gán, đây cũng là một cách. Nhân vấn đề này, tôi muốn thảo luận thêm. Cách 1: Tôi sử dụng thuộc tính Get của Function để định nghĩa. Mã: Property Get c_mangArray(ByVal vIdx As Long) As String Dim wtemp As String '---------------- Select Case vIdx Case 0: wtemp = "XinChaoCacBan" Case 1: wtemp = "tuhocvba.net" Case 2: wtemp = "VBA" End Select '---------------- c_mangArray = wtemp End Property Sub Main() Dim i As Long For i = 0 To 2 Debug.Print c_mangArray(i) Next i End Sub Kết quả: Mã: XinChaoCacBan tuhocvba.net VBA Tôi nghĩ đây là cách đơn giản, tham số (vIdx) của Function là chỉ mục của mảng. Tuy nhiên, tôi nghĩ nhiều người sẽ không thích cách này, vì mọi người muốn khai báo mảng chỉ trong một dòng. Càng ngắn gọn thì mọi người càng thích. Điều này có thể tốt nếu mảng của bạn là giá trị không đổi, nhưng nếu sau này các bạn muốn áp dụng cho code khác, số lượng phần tử mảng nhiều hơn, thì cách viết ở trên không tốt. Do đó tôi thấy cách làm của admin tuhocvba là tốt. Tôi muốn giới thiệu cách khác, chắc hẳn mọi người Bạn cần đăng nhập để thấy link nhưng thường quên áp dụng trong các trường hợp cụ thể. Cách 2: Sử dụng khai báo hằng số là chuỗi ký tự (việc này có thể dễ dàng thay đổi nội dung khi cần), rồi dùng Split để lấy mảng. Mã: Const c_mangArray As String = "XinChaoCacBan,tuhocvba.net,VBA" Sub Main() Dim i As Long Dim wStrArray() As String wStrArray = Split(c_mangArray, ",") For i = 0 To UBound(wStrArray) Debug.Print wStrArray(i) Next i End Sub Kết quả: Mã: XinChaoCacBan tuhocvba.net VBA V

vanthanhVBA

VIP

Kiểm tra có phải là mảng hay không Tương tự như kiểm tra số ta có Isnumeric, thì với mảng ta có IsArray. Cụ thể: Mã: Sub vidu() Dim MyArray(1 To 5) As Integer, YourArray ' Declare array variables. Dim MyCheck As Boolean Dim a As Double Dim b 'variant YourArray = Array(1, 2, 3) ' Use Array function. MyCheck = IsArray(MyArray) ' Returns True. If MyCheck = True Then MsgBox "MyArray La mang" 'La mang MyCheck = IsArray(YourArray) ' Returns True. If MyCheck = True Then MsgBox "YourArray La mang" 'La mang a = 10 MyCheck = IsArray(a) If MyCheck = True Then MsgBox "a La mang" 'Khong phai la mang b = 100 MyCheck = IsArray(b) If MyCheck = True Then MsgBox "b La mang" 'Khong phai la mang End Sub Nguồn tham khảo: Bạn cần đăng nhập để thấy link L

Linhvba

Yêu THVBA
Thành thật cám ơn rất nhiều . vbano1

vbano1

SMod
Thành viên BQT Xóa mảng: Khi chạy chương trình, nếu mảng mà khai báo trong chương trình: Mã: Sub vidu() Dim arr arr = thisworkbook.sheets(1).Range.... End sub Nếu mảng khai báo nội bộ như thế này, khi chạy hết thủ tục trên là mảng biến mất, bộ nhớ không có vấn đề gì. Tuy nhiên khi khai báo public Mã: Public arr Sub vidu() arr = thisworkbook.sheets(1).Range.... End sub Dù chạy hết thủ tục chính, thì mảng này vẫn còn mang giá trị, sẽ ảnh hưởng tới bộ nhớ. Ở đây, mọi ngwowif thường dùng lệnh ReDim để giải phóng bộ nhớ mảng Mã: Public arr Sub vidu() arr = thisworkbook.sheets(1).Range.... .... Redim arr(1 to 1) End sub Tuy nhiên cách này vẫn chưa triệt để, sẽ chặt hơn nếu ta dùng lệnh Erase: Mã: Public arr Sub vidu() arr = thisworkbook.sheets(1).Range.... .... Erase arr() End sub Tham khảo: Bạn cần đăng nhập để thấy link vbano1

vbano1

SMod
Thành viên BQT Xác định số chiều của mảng: Input : arr(1,2) Output: 2 Input: arr(1) Output:1 Mã: Function sochieu_arr(ByVal arr As Variant) As Long Dim i As Long, Tempdata As Long On Error Resume Next i = 0 Do While Err.Number = 0 i = i + 1 Tempdata = UBound(arr, i) Loop On Error GoTo 0 sochieu_arr = i - 1 End Function Sub test() Dim arr(1, 2) MsgBox sochieu_arr(arr) End Sub Nguồn tham khảo: Bạn cần đăng nhập để thấy link tuhocvba

tuhocvba

Administrator
Thành viên BQT Đảo chiều mảng: Mã: Function transposeArray(ByVal myarr As Variant) As Variant Dim myvar As Variant 'Output Dim i As Long, j As Long ReDim myvar(LBound(myarr, 2) To UBound(myarr, 2), LBound(myarr, 1) To UBound(myarr, 1)) For i = LBound(myarr, 2) To UBound(myarr, 2) Step 1 For j = LBound(myarr, 1) To UBound(myarr, 1) Step 1 myvar(i, j) = myarr(j, i) Next j Next i transposeArray = myvar End Function Euler

Euler

Administrator
Thành viên BQT Xóa cột trong mảng hai chiều: Mã: 'Nguon tham khao: https://vba-create.jp/vba-array2d-remove-column/ 'Xoa cot chi dinh trong mang 2 chieu Public Function Call_Array2D_RemoveColumn(arr As Variant, DelCol As Long) Dim rMin As Long: rMin = LBound(arr, 1) Dim rMax As Long: rMax = UBound(arr, 1) Dim cMin As Long: cMin = LBound(arr, 2) Dim cMax As Long: cMax = UBound(arr, 2) 'So cot - 1 Dim temp As Variant ReDim temp(rMin To rMax, cMin To cMax - 1) Dim R As Long 'Row Dim C As Long 'Column Dim i As Long: i = cMin 'start from cMin 'Neu den cot can xoa thi nhay i len i + 1 For R = rMin To rMax For C = cMin To cMax - 1 If C = DelCol Then i = i + 1 End If temp(R, C) = arr(R, i) i = i + 1 Next C i = cMin Next R Call_Array2D_RemoveColumn = temp End Function Public Sub test() Dim data() As Variant Dim i&, j& ReDim data(1 To 2, 1 To 3) data(1, 1) = 1 data(2, 1) = 2 data(1, 2) = "a" data(2, 2) = "b" data(1, 3) = "A" data(2, 3) = "B" '1 a A '2 b B 'Xoa cot 1 cua mang data data = Call_Array2D_RemoveColumn(data, 1) '1 a '2 b For i = LBound(data, 1) To UBound(data, 1) Step 1 For j = LBound(data, 2) To UBound(data, 2) Step 1 Debug.Print data(i, j) & vbTab Next j Debug.Print Chr(10) Next i End Sub Euler

Euler

Administrator
Thành viên BQT Xóa dòng trong mảng hai chiều: Mã: 'Tham khao: https://vba-create.jp/vba-array2d-remove/ 'Xoa dong chi dinh trong mang hai chieu Public Function Call_Array2D_Remove(arr As Variant, DelRow As Long) Dim rMin As Long: rMin = LBound(arr, 1) Dim rMax As Long: rMax = UBound(arr, 1) Dim cMin As Long: cMin = LBound(arr, 2) Dim cMax As Long: cMax = UBound(arr, 2) Dim temp As Variant ReDim temp(rMin To rMax - 1, cMin To cMax) Dim R As Long Dim C As Long Dim i As Long: i = rMin For R = rMin To rMax - 1 'Neu toi dong can xoa thi tang i len i + 1 If R = DelRow Then i = i + 1 End If For C = cMin To cMax temp(R, C) = arr(i, C) Next C i = i + 1 Next R Call_Array2D_Remove = temp End Function Public Sub test() Dim data() As Variant Dim i&, j& ReDim data(1 To 3, 1 To 2) data(1, 1) = 1 data(2, 1) = 2 data(3, 1) = 3 data(1, 2) = "a" data(2, 2) = "b" data(3, 2) = "c" '1 a '2 b '3 c data = Call_Array2D_Remove(data, 2) '1 a '3 c For i = LBound(data, 1) To UBound(data, 1) Step 1 For j = LBound(data, 2) To UBound(data, 2) Step 1 Debug.Print data(i, j) & vbTab Next j Debug.Print Chr(10) Next i End Sub H

haocaocu

Yêu THVBA
Bài viết quá hay, quá dễ hiểu. Thanks
  • 1
  • 2
Tiếp 1 of 2

Đi đến trang

Tới Tiếp Last Bạn phải đăng nhập hoặc đăng ký để bình luận. Chia sẻ: Facebook Twitter WhatsApp Email Link
  • Trang chủ
  • Diễn đàn
  • Kỹ thuật xử lý Excel
  • Lập trình VBA
Top

Từ khóa » Dãy Trong Vba