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,600
Được thích
2,907
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ị
 
Hàm isnumber sẽ không đảm bảo chính xác.
Mã:
MsgBox IsNumeric("123")

- Đúng là không chính xác, 02 câu lệnh sau đều trả về True.
PHP:
Sub abc()
' B2="123"
' B3=123
    Dim arr
    arr = Range("B2:B3")
    Debug.Print IsNumeric(arr(1, 1))
    Debug.Print IsNumeric(arr(2, 1))
End Sub

Vậy giải pháp ở đây là gì, để xác định là number hay number được lưu dưới dạng text.
 
Upvote 0
- Đúng là không chính xác, 02 câu lệnh sau đều trả về True.
PHP:
Sub abc()
' B2="123"
' B3=123
    Dim arr
    arr = Range("B2:B3")
    Debug.Print IsNumeric(arr(1, 1))
    Debug.Print IsNumeric(arr(2, 1))
End Sub

Vậy giải pháp ở đây là gì, để xác định là number hay number được lưu dưới dạng text.
Nếu mảng đọc từ range, thì số nó chỉ có mấy dạng là: double, boolean, date. Dùng hàm vartype kiểm tra lần lượt. Còn là string chứa các con số thì cũng dùng vartype kiểm tra xem nó là string không, rồi dùng hàm isnumber nữa.
 
Upvote 0
Cho em hỏi em khai báo mảng như sau
PHP:
Dim Arr()
Dim Rws As Integer, J As Integer
Rws = Range("B65536").End(xlUp).Row

 Arr = Range("B11").Resize(Rws, 97).Value
...

Nếu em khai báo như này thì không sao nhưng nếu mảng em khai là:

Arr = Range("B11").Resize(Rws, 98).Value

Thì báo lỗi ở mảng này (Khai báo cột cứ lớn hơn 97 là lỗi).
RWS của em bằng 3987 dòng.

Sao lại như vậy nhỉ?
 
Upvote 0
Cho em hỏi em khai báo mảng như sau
PHP:
Dim Arr()
Dim Rws As Integer, J As Integer
Rws = Range("B65536").End(xlUp).Row

 Arr = Range("B11").Resize(Rws, 97).Value
...

Nếu em khai báo như này thì không sao nhưng nếu mảng em khai là:

Arr = Range("B11").Resize(Rws, 98).Value

Thì báo lỗi ở mảng này (Khai báo cột cứ lớn hơn 97 là lỗi).
RWS của em bằng 3987 dòng.

Sao lại như vậy nhỉ?
cái này cũng khó nói lắm, có thể có 2 vấn đề
thứ nhất là bạn đang chạy chương trình khác, máy chiếm dụng bộ nhớ tạm nhiều quá , nên có khả năng nó thông báo là tràn bộ nhớ
thứ 2 là có thể ở cột 98 trong sheet có chứa giá trị lỗi. Lỗi này tôi thường xuyên bị
 
Upvote 0
cái này cũng khó nói lắm, có thể có 2 vấn đề
thứ nhất là bạn đang chạy chương trình khác, máy chiếm dụng bộ nhớ tạm nhiều quá , nên có khả năng nó thông báo là tràn bộ nhớ
thứ 2 là có thể ở cột 98 trong sheet có chứa giá trị lỗi. Lỗi này tôi thường xuyên bị


Chứa giá trị lỗi bạn ạ, cảm ơn nhiều nhé :)
 
Upvote 0
Hôm Mình có đọc đâu đó trên GPE nói giới hạn của hàm Application.Transpose tối đa của nó là bao nhiêu ký tự trong 1 Cells ...gì gì đó mà mình không nhớ !!??
và tối đa của nó là bao nhiêu dòng ....

vì mình có sử dụng biến Arr() trong Excel để lấy duy nhất mã hàng trong table Access hiên tại dữ liệu ít thấy xài tốt VD: dữ liệu dòng (Record trong Access) lớn hơn 1048576 thì nó có lỗi hay không ...??!!!!

Mong các Bạn ai biết xin giải thích dùm ....
Xin cảm ơn


Arr = Application.Transpose(Dic.Keys)
 
Upvote 0
Hôm Mình có đọc đâu đó trên GPE nói giới hạn của hàm Application.Transpose tối đa của nó là bao nhiêu ký tự trong 1 Cells ...gì gì đó mà mình không nhớ !!??
và tối đa của nó là bao nhiêu dòng ....

vì mình có sử dụng biến Arr() trong Excel để lấy duy nhất mã hàng trong table Access hiên tại dữ liệu ít thấy xài tốt VD: dữ liệu dòng (Record trong Access) lớn hơn 1048576 thì nó có lỗi hay không ...??!!!!

Mong các Bạn ai biết xin giải thích dùm ....
Xin cảm ơn


Arr = Application.Transpose(Dic.Keys)
có đó anh kiều mạnh, nó sẽ xuất hiện lỗi tràn bộ nhớ, vì tôi hay làm việc với số liệu lớn, máy khách hàng thì không sao? chứ đem về máy tôi, nếu mảng quá lớn thì sẽ báo lỗi.
chưa tính đến là nó chạy cà dựt, lúc báo lỗi lúc không? nếu chạy nhiều cái khác cùng một lúc, nó sẽ báo là tràn bộ nhớ nếu máy cấu hình không mạnh
 
Lần chỉnh sửa cuối:
Upvote 0
có đó anh kiều mạnh, nó sẽ xuất hiện lỗi tràn bộ nhớ, vì tôi hay làm việc với số liệu lớn, máy khách hàng thì không sao?(vì khách hàng máy rất cừ) chứ đem về máy tôi, nếu mảng quá lớn thì sẽ báo lỗi.
 
Upvote 0
Hôm Mình có đọc đâu đó trên GPE nói giới hạn của hàm Application.Transpose tối đa của nó là bao nhiêu ký tự trong 1 Cells ...gì gì đó mà mình không nhớ !!??
và tối đa của nó là bao nhiêu dòng ....

vì mình có sử dụng biến Arr() trong Excel để lấy duy nhất mã hàng trong table Access hiên tại dữ liệu ít thấy xài tốt VD: dữ liệu dòng (Record trong Access) lớn hơn 1048576 thì nó có lỗi hay không ...??!!!!

Mong các Bạn ai biết xin giải thích dùm ....
Xin cảm ơn


Arr = Application.Transpose(Dic.Keys)
Anh thử 2 ví dụ sau xem...
PHP:
Sub vidu1()
'Lân 1: Nhâp vao [A1]=REPT("1",255) rôi F5
'Lân 2: Nhâp vao [A1]=REPT("1",256) rôi F5
Dim a, t
a = Sheet1.Range("A1:A2").Value
t = Application.Transpose(a)
End Sub

'-------'
Sub Vidu2()
Dim maxLong As Long
maxLong = (2) ^ 31      'Lân 1    
'maxLong = (2) ^ 31 - 1  'Lân 2 : Đây là giá trị max nhưng chạy được hay không thì còn phụ thuộc bộ nhớ RAM của hệ thống (xem link)
ReDim a(1 To maxLong, 0)
End Sub
Link:
https://msdn.microsoft.com/en-us/library/b388cb5s(v=vs.90).aspx

https://stackoverflow.com/questions/7817427/excel-2007-vba-array-size-limit
 
Upvote 0
Anh thử 2 ví dụ sau xem...
PHP:
Sub vidu1()
'Lân 1: Nhâp vao [A1]=REPT("1",255) rôi F5
'Lân 2: Nhâp vao [A1]=REPT("1",256) rôi F5
Dim a, t
a = Sheet1.Range("A1:A2").Value
t = Application.Transpose(a)
End Sub

'-------'
Sub Vidu2()
Dim maxLong As Long
maxLong = (2) ^ 31      'Lân 1   
'maxLong = (2) ^ 31 - 1  'Lân 2 : Đây là giá trị max nhưng chạy được hay không thì còn phụ thuộc bộ nhớ RAM của hệ thống (xem link)
ReDim a(1 To maxLong, 0)
End Sub
Link:
https://msdn.microsoft.com/en-us/library/b388cb5s(v=vs.90).aspx

https://stackoverflow.com/questions/7817427/excel-2007-vba-array-size-limit
Vidu1 Mình hiểu tối đa trong 1 Cells là 255 ký tự nếu 256 là lỗi
Vidu2 máy Mình chạy thấy lỗi ..........Máy RAM 6G
 
Upvote 0
Upvote 0
Mới thử maxLong = (2) ^ 23 - 1 => OK .......... vậy là nó phụ thuộc vào RAM
cách tính (2) ^ 23 chi tiết nó ra như thế nào chưa hiểu lắm ....???!!! Bạn biết giải thích dùm

Ví dụ #850 dùng mảng Variant cho nên khó xác định kích cỡ. Nếu chưa chứa gì thì có lẽ mỗi phần tử của mảng Variant dài 4 bytes
vậy là mảng này cần 1 khoảng 4*2^23 bytes LIÊN TỤC trong bộ nhớ (lên 2^24 có nghĩa là gấp đôi lên). Vì windows quản lý bộ nhớ dở nên bị giới hạn. OS xịn có thể dùng bộ nhớ ảo ngay cả cho mảng.

Ở đây có ngừoi rành cái này hơn tôi. Nếu ngừoi ấy rảnh sẽ trả lời rõ hơn.
 
Upvote 0
Ví dụ #850 dùng mảng Variant cho nên khó xác định kích cỡ. Nếu chưa chứa gì thì có lẽ mỗi phần tử của mảng Variant dài 4 bytes
vậy là mảng này cần 1 khoảng 4*2^23 bytes LIÊN TỤC trong bộ nhớ (lên 2^24 có nghĩa là gấp đôi lên). Vì windows quản lý bộ nhớ dở nên bị giới hạn. OS xịn có thể dùng bộ nhớ ảo ngay cả cho mảng.

Ở đây có ngừoi rành cái này hơn tôi. Nếu ngừoi ấy rảnh sẽ trả lời rõ hơn.
Mình Nghĩ Anh batman1 có khả năng rành vụ này quá ....??!!!
nếu Anh có ghé qua chỉ dùm Em một chút .... để Cập nhật thêm kiến thức code két
 
Upvote 0
Mình Nghĩ Anh batman1 có khả năng rành vụ này quá ....??!!!
Lại bị gọi lên bảng ;-)

Vụ này nghĩa là vụ nào?

Nếu nói về bộ nhớ thì vd. ta có 6 GB RAM. Nhưng sau khi nạp system và các ct khác thì còn bao nhiêu? Vd. còn A GB. Nhưng đâu phải là còn A GB thì có thể dùng mảng có độ lớn A GB? Thế không gian làm việc thì lấy ở đâu?

Mà vd. mảng 2^27 dòng, 2 cột với các phần tử Variant thì kích thức là 2^27*2*16 (Variant = 16 bai) = 4294967296 B = 4 GB. Thế còn system, các ct khác và không gian làm việc? Với 6 GB RAM thì dùng mảng 4 GB là khó.

Nếu mảng khủng hơn - maxLong = 2^31 - 1 thì mảng = (2^31 - 1)*2*16 = 68719476704 B ≈ 64 GB. Ai có RAM tới chừng đó?

Nếu nói về kiểu Variant thì ...

Tôi đã nói qua ở đây - bài #2

http://www.giaiphapexcel.com/dienda...-trong-bộ-nhớ-tốc-độ-nhanh.77981/#post-480480

Trước hết ta thống nhất là chỉ xét system 32 bit. Như thế để biết là trong system 32 bit thì mọi địa chỉ trong bộ nhớ là 32 bit. Tức địa chỉ của bất cứ chỗ nào cũng là giá trị 32 bit - dùng 4 bai để ghi nhớ địa chỉ.

Khi ta khai báo
Mã:
Dim a As Byte, b As Integer, c As Long, d As Double, s As String, e As Object
thì "ở đâu đó" trong bộ nhớ memory manager sẽ "phân" 2, 2, 4, 8, 4, 4 bai để dùng cho 6 biến. Ta không cần quan tâm là sau cánh gà thì manager memory sẽ "phân" ở đâu, lấy bộ nhớ từ đâu, bao nhiêu. Tất nhiên không phải là cần mấy bai thì manager memory lại xin system. Manager memory "xin" system bộ nhớ và trả lại khi không cần thiết, và mỗi lần xin và trả là cả khối lớn chứ không phải cứ chốc chốc lại xin hoặc trả vài bai. Xin một khối và "chi" lúc này lúc kia, chỗ này chỗ kia, thiếu lại xin thêm, khi không cần thì lại trả, mỗi lần xin và trả là cả khối. Tự Manager memory sẽ "biết" và làm việc.

Theo tôi nếu khai báo As BYTE thì manager memory sẽ vẫn cứ phân 2 bai dùng cho biến. Tức "phân" ít nhất 2 bai.

Khi biến là Byte, Integer, Long, Double thì "ở chỗ đó" giá trị của 2, 2, 4, 8 bai được "phân" chính là giá trị của biến. Khi biến là String hoặc Object thì "ở chỗ đó" giá trị của 4 bai chỉ là địa chỉ trong bộ nhớ mà ở đó mới có chuỗi hoặc Object. Cái này dễ hiểu vì vd. chuỗi có độ dài là 15 ("Anh an com chua") thì làm sao ghi được trong 4 bai?

Khi ta khai báo
Mã:
Dim a
Dim a As Variant
thì ở đâu đó memory manager sẽ "phân" 16 bai để dùng cho biến a. Chỉ khai báo thôi memory manager sẽ "phân" 16 bai dùng cho a.

Trong 8 bai đầu (thực ra là 2 bai đầu. Nếu tôi không lầm thì 6 bai kia là Reserved) được ghi VarType. Trong 8 bai sau được ghi data. Tức nếu biến là numeric (<= 8 bai) thì giá trị trong 8 bai thứ 2 chính là giá trị numeric. Tất nhiên compilator biết là cần lấy mấy bai từ 8 bai kia). Nếu hiện thời biến chứa Object thì trong 8 bai sau ta có Pointer (4 bai) tới Object nằm ở nơi khác trong bộ nhớ. Nếu hiện thời biến chứa String thì trong 8 bai sau ta có Pointer (4 bai) tới String được ghi ở chỗ khác trong bộ nhớ (thì trong 8 bai làm sao ghi được String với độ dài bất kỳ)

Vân vân và vân vân. Mỗi người tự nghiên cứu.

Để hiểu thêm thì chạy code
Mã:
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
    (Destination As Any, Source As Any, ByVal Length As Long)

Sub test()
Dim a, vartypefrommemory As Integer, b As Long, c As Double, m() As Byte, s As String
    a = 1000
    CopyMemory vartypefrommemory, ByVal VarPtr(a), 2
    Debug.Print "a = " & a & ", VarTypeFromMemory: " & vartypefrommemory & ", VarType: " & VarType(a)
    CopyMemory b, ByVal VarPtr(a) + 8, 4
    Debug.Print "Gia tri tu memory a = " & b
   
    a = 1234567890
    CopyMemory vartypefrommemory, ByVal VarPtr(a), 2
    Debug.Print "a = " & a & ", VarTypeFromMemory: " & vartypefrommemory & ", VarType: " & VarType(a)
    CopyMemory b, ByVal VarPtr(a) + 8, 4
    Debug.Print "Gia tri tu memory a = " & b
   
    a = 2234567890#
    CopyMemory vartypefrommemory, ByVal VarPtr(a), 2
    Debug.Print "a = " & a & ", VarTypeFromMemory: " & vartypefrommemory & ", VarType: " & VarType(a)
    CopyMemory c, ByVal VarPtr(a) + 8, 8
    Debug.Print "Gia tri tu memory a = " & c
   
    a = "hic hic he he"
    CopyMemory vartypefrommemory, ByVal VarPtr(a), 2
    Debug.Print "a = " & a & ", VarTypeFromMemory: " & vartypefrommemory & ", VarType: " & VarType(a)
    CopyMemory b, ByVal VarPtr(a) + 8, 4
    Debug.Print "Dia chi chuoi lay tu memory: " & b & ", dia chi chuoi tu StrPtr: " & StrPtr(a)
    ReDim m(1 To 2 * Len(a))
    CopyMemory m(1), ByVal b, UBound(m)
    s = m
    Debug.Print "Chuoi lay tu memory a = " & s
End Sub
 
Upvote 0
Lại bị gọi lên bảng ;-)

Vụ này nghĩa là vụ nào?

Nếu nói về bộ nhớ thì vd. ta có 6 GB RAM. Nhưng sau khi nạp system và các ct khác thì còn bao nhiêu? Vd. còn A GB. Nhưng đâu phải là còn A GB thì có thể dùng mảng có độ lớn A GB? Thế không gian làm việc thì lấy ở đâu?

Mà vd. mảng 2^27 dòng, 2 cột với các phần tử Variant thì kích thức là 2^27*2*16 (Variant = 16 bai) = 4294967296 B = 4 GB. Thế còn system, các ct khác và không gian làm việc? Với 6 GB RAM thì dùng mảng 4 GB là khó.

Nếu mảng khủng hơn - maxLong = 2^31 - 1 thì mảng = (2^31 - 1)*2*16 = 68719476704 B ≈ 64 GB. Ai có RAM tới chừng đó?

Nếu nói về kiểu Variant thì ...

Tôi đã nói qua ở đây - bài #2

http://www.giaiphapexcel.com/diendan/threads/tặng-các-bạn-module-modfastarray-các-hàm-xử-lý-mảng-trong-bộ-nhớ-tốc-độ-nhanh.77981/#post-480480

Trước hết ta thống nhất là chỉ xét system 32 bit. Như thế để biết là trong system 32 bit thì mọi địa chỉ trong bộ nhớ là 32 bit. Tức địa chỉ của bất cứ chỗ nào cũng là giá trị 32 bit - dùng 4 bai để ghi nhớ địa chỉ.

Khi ta khai báo
Mã:
Dim a As Byte, b As Integer, c As Long, d As Double, s As String, e As Object
thì "ở đâu đó" trong bộ nhớ memory manager sẽ "phân" 2, 2, 4, 8, 4, 4 bai để dùng cho 6 biến. Ta không cần quan tâm là sau cánh gà thì manager memory sẽ "phân" ở đâu, lấy bộ nhớ từ đâu, bao nhiêu. Tất nhiên không phải là cần mấy bai thì manager memory lại xin system. Manager memory "xin" system bộ nhớ và trả lại khi không cần thiết, và mỗi lần xin và trả là cả khối lớn chứ không phải cứ chốc chốc lại xin hoặc trả vài bai. Xin một khối và "chi" lúc này lúc kia, chỗ này chỗ kia, thiếu lại xin thêm, khi không cần thì lại trả, mỗi lần xin và trả là cả khối. Tự Manager memory sẽ "biết" và làm việc.

Theo tôi nếu khai báo As BYTE thì manager memory sẽ vẫn cứ phân 2 bai dùng cho biến. Tức "phân" ít nhất 2 bai.

Khi biến là Byte, Integer, Long, Double thì "ở chỗ đó" giá trị của 2, 2, 4, 8 bai được "phân" chính là giá trị của biến. Khi biến là String hoặc Object thì "ở chỗ đó" giá trị của 4 bai chỉ là địa chỉ trong bộ nhớ mà ở đó mới có chuỗi hoặc Object. Cái này dễ hiểu vì vd. chuỗi có độ dài là 15 ("Anh an com chua") thì làm sao ghi được trong 4 bai?

Khi ta khai báo
Mã:
Dim a
Dim a As Variant
thì ở đâu đó memory manager sẽ "phân" 16 bai để dùng cho biến a. Chỉ khai báo thôi memory manager sẽ "phân" 16 bai dùng cho a.

Trong 8 bai đầu (thực ra là 2 bai đầu. Nếu tôi không lầm thì 6 bai kia là Reserved) được ghi VarType. Trong 8 bai sau được ghi data. Tức nếu biến là numeric (<= 8 bai) thì giá trị trong 8 bai thứ 2 chính là giá trị numeric. Tất nhiên compilator biết là cần lấy mấy bai từ 8 bai kia). Nếu hiện thời biến chứa Object thì trong 8 bai sau ta có Pointer (4 bai) tới Object nằm ở nơi khác trong bộ nhớ. Nếu hiện thời biến chứa String thì trong 8 bai sau ta có Pointer (4 bai) tới String được ghi ở chỗ khác trong bộ nhớ (thì trong 8 bai làm sao ghi được String với độ dài bất kỳ)

Vân vân và vân vân. Mỗi người tự nghiên cứu.

Để hiểu thêm thì chạy code
Mã:
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
    (Destination As Any, Source As Any, ByVal Length As Long)

Sub test()
Dim a, vartypefrommemory As Integer, b As Long, c As Double, m() As Byte, s As String
    a = 1000
    CopyMemory vartypefrommemory, ByVal VarPtr(a), 2
    Debug.Print "a = " & a & ", VarTypeFromMemory: " & vartypefrommemory & ", VarType: " & VarType(a)
    CopyMemory b, ByVal VarPtr(a) + 8, 4
    Debug.Print "Gia tri tu memory a = " & b
 
    a = 1234567890
    CopyMemory vartypefrommemory, ByVal VarPtr(a), 2
    Debug.Print "a = " & a & ", VarTypeFromMemory: " & vartypefrommemory & ", VarType: " & VarType(a)
    CopyMemory b, ByVal VarPtr(a) + 8, 4
    Debug.Print "Gia tri tu memory a = " & b
 
    a = 2234567890#
    CopyMemory vartypefrommemory, ByVal VarPtr(a), 2
    Debug.Print "a = " & a & ", VarTypeFromMemory: " & vartypefrommemory & ", VarType: " & VarType(a)
    CopyMemory c, ByVal VarPtr(a) + 8, 8
    Debug.Print "Gia tri tu memory a = " & c
 
    a = "hic hic he he"
    CopyMemory vartypefrommemory, ByVal VarPtr(a), 2
    Debug.Print "a = " & a & ", VarTypeFromMemory: " & vartypefrommemory & ", VarType: " & VarType(a)
    CopyMemory b, ByVal VarPtr(a) + 8, 4
    Debug.Print "Dia chi chuoi lay tu memory: " & b & ", dia chi chuoi tu StrPtr: " & StrPtr(a)
    ReDim m(1 To 2 * Len(a))
    CopyMemory m(1), ByVal b, UBound(m)
    s = m
    Debug.Print "Chuoi lay tu memory a = " & s
End Sub
Em cảm ơn Anh ... Cái Em hỏi thì Anh đã trả lời ... Em đọc tới lui bài này và link Anh cho U cả đầu ...Từ từ Em nghiền ngẫm có gì chưa biết Mong Anh chỉ thêm
Em Cảm ơn Anh rất nhiều
 
Lần chỉnh sửa cuối:
Upvote 0
Web KT
Back
Top Bottom