Các câu hỏi về mảng trong VBA (Array)

Liên hệ QC

viehoai

Thành viên gắn bó
Tham gia
22/5/09
Bài viết
2,599
Được thích
2,908
Xin các anh chị giúp đỡ Code Gán các giá trị của một Range là các phần tử của Mãng
Ví dụ: Tôi có các giá trị của Range("A1:A10"). Tôi muốn viết code để gán giá trị của các cells từ A1:A10 là các phần tử của Mãng Arr chẳn hạn.
Xin cảm ơn các anh chị
 
Không đúng

cứ để thế thì biến là empty chứ không phải Variant
Khi bạn khai báo Dim trungvdb thì biến trungvdb là Empty
Nếu bạn gán trungvdb =1 thì trungvdb là Integer
Nếu bạn gán trungvdb ="Concogia" thì trungvdb là String
Nếu bạn gán trungvdb =Range("A1:A100") thì trungvdb là Variant
Nếu bạn gán Set trungvdb =Range("A1:A100") thì trungvdb là Range
Híc

Không đúng (sic)
Không khai báo kiểu thì biến nhận kiểu variant, và giá trị ban đầu là không có (empty)

Cái này là rất, rất, rất căn bản:

Cú pháp khai báo biến:

Dim <VarName> [As <VarType>]
Dim <tên biến> [As <kiểu>]

Kiểu có nhiều loại, trong đó có kiểu variant, kính thưa quan viên hai họ!
trong dấu [...] là có thể bỏ qua, nếu bỏ qua, thì là kiểu variant, kính thưa 2 bác Cò!
 
Lần chỉnh sửa cuối:
Upvote 0
Không đúng (sic)
Không khai báo kiểu thì biến nhận kiểu variant, và giá trị ban đầu là không có (empty)

Cái này là rất, rất, rất căn bản:

Cú pháp khai báo biến:

Dim <VarName> [As <VarType>]
Dim <tên biến> [As <kiểu>]

Kiểu có nhiều loại, trong đó có kiểu variant, kính thưa quan viên hai họ!
trong dấu [...] là có thể bỏ qua, nếu bỏ qua, thì là kiểu variant, kính thưa 2 bác Cò!
Híc
Đúng là nhầm, hổng sao, hột vịt còn lộn mà ( chẳng bao giờ khai báo kiểu biến trong code của mình mà vẫn lộn)
Khi không khai báo thì không có giá trị ban đầu của biến, sau đó muốn gán kiểu quái gì thì gán
Thanks Lão Chết Tiệt
Híc
 
Upvote 0
Còn cái này:

Tức là khi khai báo biến thằng nào chắc chắn là mảng thì khai báo ..., nếu biết chắc chắn là Long thì khai báo long, còn các cái khác cứ để chung chung không nói gì thì nó tự hiểu là Variant hả thày?

Không phải chắc chắn "nó" (biến nào) là String hoặc chắc chắn "nó" là Long; mà là chắc chắn mình muốn sử dụng "nó" (biến nào) là String hay sử dụng biến nào là Long.

Tương tự, ta muốn sử dụng tuỳ ý 1 biến nào đó tương ứng với bất kỳ kiểu dữ liệu nào gán vào, thì khai báo kiểu variant, hoặc không khai báo kiểu.

Ta khai báo, là ta chủ động bắt "nó" là kiểu nào, chứ không phải bị "nó" áp đặt.

Dù là đã hiểu rồi, cũng phải phát biểu cho chính xác.
 
Lần chỉnh sửa cuối:
Upvote 0
Híc...Cảm ơn các thày, thế mà từ trước đến nay tôi toàn hiểu khái niệm Range và Mảng là giống nhau.

Tôi tự hỏi: Khi đã có Range là đủ, sao cần có mảng nữa. Bởi theo cá nhân tôi hiểu, nếu xét về mặt tính chất thì Range rộng hơn mảng (tựa như trong Toán học thì tập hợp R là tập hợp số thực > tập Q là tập hợp số hữu tỷ).
Phải chăng do Mảng có tính "cơ động" hơn là Range?

Nếu có thể xin các thày hướng dẫn cụ thể cho cho chút nữa, đó là bản chất của Rangemảng khác nhau như thế nào, chúng tương tác với nhau ra sao?
 
Lần chỉnh sửa cuối:
Upvote 0
Nếu có thể xin các thày hướng dẫn cụ thể cho cho chút nữa, đó là bản chất của Rangemảng khác nhau như thế nào, chúng tương tác với nhau ra sao?
Range là một vùng trên Sheet còn mảng là 1 vùng ảo được lưu trử trong bộ nhớ củamáy khi ta viết code mà muốn vùng ảo thành vùng thật thì ta phải gán xuống sheet để thấy giá trị của chúng
 
Upvote 0
Híc...Cảm ơn các thày, thế mà từ trước đến nay tôi toàn hiểu khái niệm Range và Mảng là giống nhau.

Tôi tự hỏi: Khi đã có Range là đủ, sao cần có mảng nữa. Bởi theo cá nhân tôi hiểu, nếu xét về mặt tính chất thì Range rộng hơn mảng (tựa như trong Toán học thì tập hợp R là tập hợp số thực > tập Q là tập hợp số hữu tỷ).
Phải chăng do Mảng có tính "cơ động" hơn là Range?

Nếu có thể xin các thày hướng dẫn cụ thể cho cho chút nữa, đó là bản chất của Rangemảng khác nhau như thế nào, chúng tương tác với nhau ra sao?

Range là tập hợp tất cả các giá trị, định dạng, công thức, sự kiện, thuộc tính, v.v... Range là cái ta có thể nhìn thấy trực tiếp trên Sheet.

Mảng là tập hợp các phần tử chứa giá trị. Mảng chứa trong bộ nhớ tạm, chúng ta không thể thấy, tạm gọi là giá trị ảo.

Vì Range bao gồm tất cả các tập hợp trên nên khi xử lý trực tiếp trong Range sẽ bị chậm hơn so với mảng vì mảng chỉ có chứa tập hợp là giá trị. Vì vậy, khi xử lý dữ liệu, người ta thường dùng mảng để xử lý trước rồi gán xuống sheet mà không làm trực tiếp trên sheet sẽ cho tốc độ chậm.

Trên đây là theo sự hiểu biết của mình, hy vọng bạn sẽ hiểu về nó.
 
Upvote 0
Híc...Cảm ơn các thày, thế mà từ trước đến nay tôi toàn hiểu khái niệm Range và Mảng là giống nhau.

Tôi tự hỏi: Khi đã có Range là đủ, sao cần có mảng nữa. Bởi theo cá nhân tôi hiểu, nếu xét về mặt tính chất thì Range rộng hơn mảng (tựa như trong Toán học thì tập hợp R là tập hợp số thực > tập Q là tập hợp số hữu tỷ).
Phải chăng do Mảng có tính "cơ động" hơn là Range?

Nếu có thể xin các thày hướng dẫn cụ thể cho cho chút nữa, đó là bản chất của Rangemảng khác nhau như thế nào, chúng tương tác với nhau ra sao?
Chính vì nó "rộng" hơn (như bạn nói) nên nó phải ôm đồm nhiều thứ, dẫn đến nó sẽ xử lý dữ liệu chậm hơn
Vậy nên, những bài toán liên quan đến xử lý dữ liệu (không quan tâm đến format, chỉ quan tâm giá trị), nếu chuyển về mảng để xử lý sẽ nhanh hơn
Xử lý mảng khó hơn, vì chúng chẳng có bất cứ thuộc tính nào như range nhưng cũng vì thế mà nhanh hơn
Việc chuyển từ Range sang mảng hoặc ngược lại rất đơn giản, chỉ là Arr = Range("...").Value hoặc Range("...").Value = Arr
Lưu ý thêm rằng: mảng do range chuyển vào sẽ luôn là mảng 2 chiều (Range nằm trên 1 "mặt phẳng", đương nhiên phải 2 chiều rồi)
Ẹc... Ẹc...
 
Upvote 0
Chính vì nó "rộng" hơn (như bạn nói) nên nó phải ôm đồm nhiều thứ, dẫn đến nó sẽ xử lý dữ liệu chậm hơn
Vậy nên, những bài toán liên quan đến xử lý dữ liệu (không quan tâm đến format, chỉ quan tâm giá trị), nếu chuyển về mảng để xử lý sẽ nhanh hơn
Xử lý mảng khó hơn, vì chúng chẳng có bất cứ thuộc tính nào như range nhưng cũng vì thế mà nhanh hơn
Việc chuyển từ Range sang mảng hoặc ngược lại rất đơn giản, chỉ là Arr = Range("...").Value hoặc Range("...").Value = Arr
Lưu ý thêm rằng: mảng do range chuyển vào sẽ luôn là mảng 2 chiều (Range nằm trên 1 "mặt phẳng", đương nhiên phải 2 chiều rồi)
Ẹc... Ẹc...
Vì mới bập bẹ về mảng nên câu hỏi hơi bị "ngu":
Ví dụ gán Mảng Arr = Range("A4:E15").Value
Dùng hàm gì để biết mảng 2 chiều Arr có 1 chiều = 12 phần tử, một chiều = 5 phần tử, số phần tử trong mảng là 60?
 
Upvote 0
Vì mới bập bẹ về mảng nên câu hỏi hơi bị "ngu":
Ví dụ gán Mảng Arr = Range("A4:E15").Value
Dùng hàm gì để biết mảng 2 chiều Arr có 1 chiều = 12 phần tử, một chiều = 5 phần tử, số phần tử trong mảng là 60?
Anh dùng hàm Ubound. Thí nghiệm với MsgBox UBound(Arr, 1) và MsgBox UBound(Arr, 2)
 
Upvote 0
Anh dùng hàm Ubound. Thí nghiệm với MsgBox UBound(Arr, 1) và MsgBox UBound(Arr, 2)
Lưu ý cái này nha:
- UBound không phải tổng số phần tử mà là chỉ số thứ tự phần tử cuối cùng
- Tương tự LBound là chỉ số thứ tự phần tử đầu tiên
Với Option Base 0 thì STT phần tử đầu tính từ 0, vì thí tổng số phần tử sẽ = UBound(...) +1
Với mảng gán từ range thì Base luôn = 1 nên khỏi phải cộng thêm 1
Nói thế để mai này khỏi bị nhầm
 
Upvote 0
Sau khi nghiên cứu về mảng, tôi tự làm bài đầu tiên như sau mà chạy không nổi, chẳng biết sai ở đâu, xin hãy chỉ giúp.

PHP:
Sub Loc()
Dim DL As Range, Arr(), KQ(), i As Long, j As Long
DL = Range([A1], [A65000].End(xlUp))
Arr = DL.Value
For i = 1 To UBound(Arr, 1)
j = 1
If Arr(i, 1) <> "" Then
KQ(j, 1) = Arr(i, 1)
j = j + 1
Next i
Range("B1:B10").Value = KQ
End Sub
 
Upvote 0
Sau khi nghiên cứu về mảng, tôi tự làm bài đầu tiên như sau mà chạy không nổi, chẳng biết sai ở đâu, xin hãy chỉ giúp.

PHP:
Sub Loc()
Dim DL As Range, Arr(), KQ(), i As Long, j As Long
DL = Range([A1], [A65000].End(xlUp))
Arr = DL.Value
For i = 1 To UBound(Arr, 1)
j = 1
If Arr(i, 1) <> "" Then
KQ(j, 1) = Arr(i, 1)
j = j + 1
Next i
Range("B1:B10").Value = KQ
End Sub
Bạn phải đặt dòng j = 1 ra ngoài vòng lặp thì mới được. Vì bạn đặt dòng đó trong vòng lặp nên cứ mỗi lần duyệt qua 1 phần tử của mảng Arr thì j lại được gán lại giá trị bằng 1. Vì vậy dữ liệu luôn được gán vào phần tử đầu tiên của mảng KQ
 
Upvote 0
Ngoài lỗi đó ra thì chắc vẫn còn lỗi gì đó anh ah, vì tôi đã sửa như anh nói mà chạy vẫn không được

PHP:
Sub Loc()
Dim DL As Range, Arr(), KQ(), i As Long, j As Long
DL = Range([A1], [A65000].End(xlUp))
Arr = DL.Value
j = 1
For i = 1 To UBound(Arr, 1)
If Arr(i, 1) <> "" Then
KQ(j, 1) = Arr(i, 1)
j = j + 1
Next i
Range("B1:B10").Value = KQ
End Sub
 
Upvote 0
- Biến DL khai báo là Range, và gán giá trị cho nó là 1 Range, thì phải có Set
- Thực ra cũng không cần qua trung gian DL, có thể gán thẳng giá trị cho Arr bằng giá trị của 1 range
- Có If nhưng không có End If
- Array KQ chưa có kích thước.
 
Upvote 0
Ngoài lỗi đó ra thì chắc vẫn còn lỗi gì đó anh ah, vì tôi đã sửa như anh nói mà chạy vẫn không được

PHP:
Sub Loc()
Dim DL As Range, Arr(), KQ(), i As Long, j As Long
DL = Range([A1], [A65000].End(xlUp))
Arr = DL.Value
j = 1
For i = 1 To UBound(Arr, 1)
If Arr(i, 1) <> "" Then
KQ(j, 1) = Arr(i, 1)
j = j + 1
Next i
Range("B1:B10").Value = KQ
End Sub
Sai nhiều quá
Sửa vầy mới đúng:
PHP:
Sub Loc()
  Dim Arr, KQ(), i As Long, j As Long
  Arr = Range([A1], [A65000].End(xlUp)).Value
  ReDim KQ(1 To UBound(Arr, 1), 1 To 1)
  For i = 1 To UBound(Arr, 1)
    If Arr(i, 1) <> "" Then
      j = j + 1
      KQ(j, 1) = Arr(i, 1)
    End If
  Next
  Range("B1").Resize(j).Value = KQ
End Sub
 
Upvote 0
Cảm ơn thày nhiều, thế mà tôi cứ tưởng j chạy đến đâu thì kích thước mảng kết quả sẽ tự thay đổi theo đó?

Xin cho phép hỏi thêm chút nữa là nếu trong Code

PHP:
Sub Loc()
  Dim Arr, KQ(), i As Long, j As Long
  Arr = Range([A1], [A65000].End(xlUp)).Value
  ReDim KQ(1 To UBound(Arr, 1), 1 To 1)
  For i = 1 To UBound(Arr, 1)
    If Arr(i, 1) <> "" Then
      j = j + 1
      KQ(j, 1) = Arr(i, 1)
    End If
  Next
  Range("B1").Resize(j).Value = KQ
End Sub

Bây giờ tôi thay "em Rờ Đim" tức dòng ReDim KQ(1 To UBound(Arr, 1), 1 To 1) bằng Dim KQ(1 To UBound(Arr, 1), 1 To 1) thì sao?
--------------
Nếu ReDim KQ có tính co dãn, tôi hiểu không biết có đúng không: Tức là khai báo tại ban đầu ReDim KQ(1 To UBound(Arr, 1), 1 To 1) nó chỉ là kích thước "tạm thời" (kiểu như dự toán vậy), sau này kích thước mảng KQ khi chạy hết vòng lặp đuợc xác định quyết toán theo thực tế?

(Ví dụ ban đầu KQ ban đầu khai báo ReDim nó tạm thời là mảng 2 chiều có 10 dòng, 1cột tức KQ (10,1), nhưng sau khi bỏ qua 4 ô trống lúc này j = 6 thôi thì lúc này KQ(6,1) mới là kích thước thật?

Nếu có gì sai, xin thày chỉ bảo cho.
 
Lần chỉnh sửa cuối:
Upvote 0
Cảm ơn thày nhiều, thế mà tôi cứ tưởng j chạy đến đâu thì kích thước mảng kết quả sẽ tự thay đổi theo đó?

Xin cho phép hỏi thêm chút nữa là nếu trong Code

PHP:
Sub Loc()
  Dim Arr, KQ(), i As Long, j As Long
  Arr = Range([A1], [A65000].End(xlUp)).Value
  ReDim KQ(1 To UBound(Arr, 1), 1 To 1)
  For i = 1 To UBound(Arr, 1)
    If Arr(i, 1) <> "" Then
      j = j + 1
      KQ(j, 1) = Arr(i, 1)
    End If
  Next
  Range("B1").Resize(j).Value = KQ
End Sub

Bây giờ tôi thay "em Rờ Đim" tức dòng ReDim KQ(1 To UBound(Arr, 1), 1 To 1) bằng Dim KQ(1 To UBound(Arr, 1), 1 To 1) thì sao?
--------------
Nếu ReDim KQ có tính co dãn, tôi hiểu không biết có đúng không: Tức là khai báo tại ban đầu ReDim KQ(1 To UBound(Arr, 1), 1 To 1) nó chỉ là kích thước "tạm thời" (kiểu như dự toán vậy), sau này kích thước mảng KQ khi chạy hết vòng lặp đuợc xác định quyết toán theo thực tế?

(Ví dụ ban đầu KQ ban đầu khai báo ReDim nó tạm thời là mảng 2 chiều có 10 dòng, 1cột tức KQ (10,1), nhưng sau khi bỏ qua 4 ô trống lúc này j = 6 thôi thì lúc này KQ(6,1) mới là kích thước thật?

Nếu có gì sai, xin thày chỉ bảo cho.
Mảng hơi khó "nhai" trong mấy vụ "rờ đim" này đấy
Ví dụ:
Mã:
Dim KQ(1 to 10,  1 to 1)[/B]
sẽ không có vấn đề gì, nhưng nếu viết
Mã:
[/B]
[B]n = 5[/B]
[B]ReDim KQ(1 to n, 1 to 1)[/B][B]
thì VBA nó cóc chịu
Khai báo mảng ban đầu phải là 1 số cụ thể nào đó, không thể cho biến vào được
Ở trường hợp bên dưới, phải viết vầy mới được
Mã:
[/B]
[B]Dim KQ()[/B]
[B]n = 5[/B]
[B]ReDim KQ(1 to n, 1 to 1)[/B][B]
Tức khai báo trước, xong muốn "rờ.." cái gì thì "rờ..."
 
Upvote 0
Mảng hơi khó "nhai" trong mấy vụ "rờ đim" này đấy
Ví dụ:
Mã:
Dim KQ(1 to 10,  1 to 1)
sẽ không có vấn đề gì, nhưng nếu viết
Mã:
[B]n = 5[/B]
[B]ReDim KQ(1 to n, 1 to 1)[/B]
thì VBA nó cóc chịu
Khai báo mảng ban đầu phải là 1 số cụ thể nào đó, không thể cho biến vào được
Ở trường hợp bên dưới, phải viết vầy mới được
Mã:
[B]Dim KQ()[/B]
[B]n = 5[/B]
[B]ReDim KQ(1 to n, 1 to 1)[/B]
Tức khai báo trước, xong muốn "rờ.." cái gì thì "rờ..."

Rắc rối quá nhỉ, thế để cho tổng quát ban đầu sao mình không cho nó lớn hết cỡ đi ví dụ
ReDim KQ(1 to 65536, 1 to 1) chẳng hạn, lúc đó sẽ chẳng cần quan tâm đến cái anh Arr làm chi.
 
Upvote 0
Rắc rối quá nhỉ, thế để cho tổng quát ban đầu sao mình không cho nó lớn hết cỡ đi ví dụ
ReDim KQ(1 to 65536, 1 to 1) chẳng hạn, lúc đó sẽ chẳng cần quan tâm đến cái anh Arr làm chi.
Làm vậy cũng được mà nó sẽ tốn bộ nhớ máy tính bạn ah khi làm việc sẽ chậm hơn
 
Upvote 0
Web KT

Bài viết mới nhất

Back
Top Bottom