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ị
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.
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.
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?
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
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?
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
Set uv = Range("C9:C5000").FormatConditions.AddUniqueValues
uv.DupeUnique = xlDuplicate
uv.Interior.Color = vbYellow
Code trên dùng để đổ màu vàng với các giá trị trùng lặp, vậy có cách nào thay vì đổ màu vàng thì nếu phát hiện giá trị trùng nhau thì tại cột A của dòng đó đổ giá trị là 2 không anh chị? Hiện tại em đang dùng countif để đếm giá trị trùng lặp sau đó gán mảng đó vào cột A nhưng mà chậm quá.
Set uv = Range("C9:C5000").FormatConditions.AddUniqueValues
uv.DupeUnique = xlDuplicate
uv.Interior.Color = vbYellow
Code trên dùng để đổ màu vàng với các giá trị trùng lặp, vậy có cách nào thay vì đổ màu vàng thì nếu phát hiện giá trị trùng nhau thì tại cột A của dòng đó đổ giá trị là 2 không anh chị?
Vâng em cảm ơn thầy!. Vậy có cách nào khác tối ưu hơn so với dùng hàm countif không ạ?
Ngoài ra em đang tập viết code về mảng mà đang mắc ở đây:
PHP:
sArray = Sheets("Check").Range("A1").Resize(22, 31).Value
ReDim dArr(1 To 30, 1 To 30)
k = 0
For j = 1 To 32
If ActiveSheet.Name = sArray(1, j).Value Then
For i = 1 To 22
If sArray(i, j) = 0 Then
k = k + 1
dArr(k, 1) = sArray(i, 1)
End If
Next i
End If
Next j
[D13].Resize(k, 1) = dArr
Code này có gì sai mà toàn báo lỗi ở dòng If ActiveSheet.Name = sArray(1, j).Value Then ?
Với cả code đang tạo mảng 1 chiều (em cứ gọi là mảng dọc) thì gán thành mảng ngang như nào vậy thầy?
Giả sử có mảng một chiều:
mang1c=array(1,2,3,4) có số phần tử n = ubound(mang1c)-lbound(mang1c)+1
Khởi tạo mảng 2 chiều:
Dim mang2c(1 to n, 0) 'Mảng 2 chiều có n hàng, 1 cột) (1)
'Hoặc Dim mang2c(0, 1 to n) 'Mảng 2 chiều có 1 dòng, n cột) (2)
Khai báo biến chạy:
Dim i as long, j as long
Vòng lặp chuyển phần tử mang1c sang mang2c:
Mã:
For i=lbuound(mang1c) to ubound(mang1c)
j=j+1
'(1):
mang2c(j,0)=mang1c(i)
'(2):
'mang2c(0,j)=mang1c(i)
next i
For j = 1 To 32
trong khi ubound(sArray,2)=31 --> sArray(1,32)?
Giả sử có mảng một chiều:
mang1c=array(1,2,3,4) có số phần tử n = ubound(mang1c)-lbound(mang1c)+1
Khởi tạo mảng 2 chiều:
Dim mang2c(1 to n, 0) 'Mảng 2 chiều có n hàng, 1 cột) (1)
'Hoặc Dim mang2c(0, 1 to n) 'Mảng 2 chiều có 1 dòng, n cột) (2)
Khai báo biến chạy:
Dim i as long, j as long
Vòng lặp chuyển phần tử mang1c sang mang2c:
Mã:
For i=lbuound(mang1c) to ubound(mang1c)
j=j+1
'(1):
mang2c(j,0)=mang1c(i)
'(2):
'mang2c(0,j)=mang1c(i)
next i
Befaint ơi mình đã sửa 32 thành 31 rồi mà vẫn báo lỗi ở dòng lệnh Activesheet.Name. (Mặc dù dòng 1 kéo dài từ cột 1 đến cột 32 có giá trị là tên sheet hiện hành). Lạ quá
Befaint ơi mình đã sửa 32 thành 31 rồi mà vẫn báo lỗi ở dòng lệnh Activesheet.Name. (Mặc dù dòng 1 kéo dài từ cột 1 đến cột 32 có giá trị là tên sheet hiện hành). Lạ quá
Mình thêm lệnh On Error Resume Next thì không lỗi nữa
PHP:
sArray = Sheets("Check").Range("A1").Resize(22, 31).Value
ReDim dArr(1 To 31, 1 To 31)
On Error Resume Next
k = 0
For j = 1 To 31
If ActiveSheet.Name = sArray(1, j).Value Then
For i = 2 To 22
If sArray(i, j) = 0 Then
k = k + 1
dArr(k, 1) = sArray(i, 1)
End If
Next i
End If
Next j
[D13].Resize(k, 1) = dArr
Tuy nhiên mảng khi gán có 31 giá trị đúng và thừa 130 giá trị #N/A không biết ở đâu ra.
Còn thay vì gán dọc mình chuyển gán ngang bằng cái này, cách của befaint mình sẽ học hỏi thêm.
Dịch câu đó nghĩa là gì? Đang tìm và xử lý lỗi thì sao lại bỏ qua? Làm sao biết kết quả đúng hay sai?
Mã:
For i = 2 To 22
k = k + 1
dArr(k, 1) = sArray(i, 1)
Kết quả cần trả về là 1 cột, có tối đa 22-2+1=21 dòng thì sao lại có ReDim dArr(1 To 31, 1 To 31)??
Redim dArr(1 to 21, 1 to 1)
Trước khi gán kết quả cần kiểm ta có gì để gán không đã:
if k>0 then [D13].Resize(k, 1) = dArr
Để giảm số lần xét, giả sử không cần chạy hết vòng lặp đã thỏa điều kiện thì nên thoát vòng lặp:
Mã:
For j = 1 To 31
If vba.ucase(activesheet.name) like vba.ucase(sArray(1, j).Value) Then
For i = 2 To 22
'...
Next i
Exit for
End If
Next j
[D13].Resize(1, k) = WorksheetFunction.Transpose(dArr)
Cái này có thể gặp lỗi, chịu khó tìm đọc trên diễn đàn.
Gán xuống 1 hàng thì tạo sao không làm vậy: Redim dArr(1 to 1, 1 to 21)
Bạn xem file giúp mình nhé, hoa mắt rồi (. Mục đích của mình là tại sheet có tên 19 mình sẽ lấy cột có giá trị 19 ở sheet Check. Tiếp tục kiểm tra ở cột đó từ dòng 1 đến 22 nếu dòng nào có giá trị 0 thì lấy giá trị dòng đó tại cột A.
Bạn xem file giúp mình nhé, hoa mắt rồi (. Mục đích của mình là tại sheet có tên 19 mình sẽ lấy cột có giá trị 19 ở sheet Check. Tiếp tục kiểm tra ở cột đó từ dòng 1 đến 22 nếu dòng nào có giá trị 0 thì lấy giá trị dòng đó tại cột A.
Sub hochoi()
Dim mangDL(), i As Integer, j As Integer, k As Integer
Dim maxRow As Long, maxCol As Long
mangDL = Sheets("Check").Range("A1").Resize(22, 31).Value
maxRow = UBound(mangDL, 1): maxCol = UBound(mangDL, 2)
ReDim KQngang(0, 1 To maxRow)
ReDim KQdoc(1 To maxRow, 0)
For j = 1 To maxCol
If ActiveSheet.Name Like mangDL(1, j) Then
For i = 1 To maxRow
If mangDL(i, j) = 0 Then
k = k + 1
KQngang(0, k) = mangDL(i, 1)
KQdoc(k, 0) = mangDL(i, 1)
End If
Next i
Exit For
End If
Next j
If k Then ActiveSheet.Range("A1").Resize(k, 1) = KQdoc
If k Then ActiveSheet.Range("A1").Resize(1, k) = KQngang
End Sub
Sub hochoi()
Dim mangDL(), i As Integer, j As Integer, k As Integer
Dim maxRow As Long, maxCol As Long
mangDL = Sheets("Check").Range("A1").Resize(22, 31).Value
maxRow = UBound(mangDL, 1): maxCol = UBound(mangDL, 2)
ReDim KQngang(0, 1 To maxRow)
ReDim KQdoc(1 To maxRow, 0)
For j = 1 To maxCol
If ActiveSheet.Name Like mangDL(1, j) Then
For i = 1 To maxRow
If mangDL(i, j) = 0 Then
k = k + 1
KQngang(0, k) = mangDL(i, 1)
KQdoc(k, 0) = mangDL(i, 1)
End If
Next i
Exit For
End If
Next j
If k Then ActiveSheet.Range("A1").Resize(k, 1) = KQdoc
If k Then ActiveSheet.Range("A1").Resize(1, k) = KQngang
End Sub
Sub In_loc()
Dim MangIn as Variant
Dim I As Integer, Row As Integer
Row = Range("A65536").End(xlUp).Row
MangIn = Range("A1").Resize(Row, 16).Value
For I = 1 To Row
MangIn.AutoFilter Field:=16, Criteria1:=I
Next I
End Sub
Có phải Autofilter không nhận mảng mà em làm toàn báo lỗi? Và sau mỗi vòng lặp lọc tự động in thì em thêm câu lệnh nào nữa?
Sub In_loc()
Dim MangIn as Variant
Dim I As Integer, Row As Integer
Row = Range("A65536").End(xlUp).Row
MangIn = Range("A1").Resize(Row, 16).Value
For I = 1 To Row
MangIn.AutoFilter Field:=16, Criteria1:=I
Next I
End Sub
Có phải Autofilter không nhận mảng mà em làm toàn báo lỗi? Và sau mỗi vòng lặp lọc tự động in thì em thêm câu lệnh nào nữa?
Sub In_loc()
Dim MangIn as Variant
Dim I As Integer, Row As Integer
Row = Range("A65536").End(xlUp).Row
MangIn = Range("A1").Resize(Row, 16).Value
For I = 1 To Row
MangIn.AutoFilter Field:=16, Criteria1:=I
Next I
End Sub
Có phải Autofilter không nhận mảng mà em làm toàn báo lỗi? Và sau mỗi vòng lặp lọc tự động in thì em thêm câu lệnh nào nữa?
- Phương thức của Autofilter chi đi với đối tượng Range thôi.
- Nếu bạn đã dùng Mảng rồi, thì chơi Mảng luôn, không cần đụng tới Phương thức Autofilter nữa.
Với bài #874 thì code sau cho kết quả vẫn chưa như mong muốn. Tự làm từ A đến Z oải thật.
PHP:
Sub hochoi2()
Dim mangDL(), i As Integer, j As Integer, k As Integer, l As Long
Dim maxRow As Long, maxCol As Long
With Sheets("Check")
mangDL = .Range("A1").Resize(22, 31).Value
maxRow = UBound(mangDL, 1): maxCol = UBound(mangDL, 2)
k = 0
ReDim KQ(1 To maxRow, 1 To maxCol)
For i = 2 To maxRow
For j = 2 To maxCol
If mangDL(i, j) > 400 Then
k = k + 1
KQ(k, 1) = mangDL(i, 1)
KQ(k, j) = mangDL(i, j)
End If
Next j
Next i
MsgBox k
If k Then
Sheets("19").Range("A9").Resize(k, j) = KQ
End If
End With
End Sub