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

  • Thread starter Thread starter viehoai
  • Ngày gửi Ngày gửi
Liên hệ QC

Người dùng đang xem chủ đề này

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ị
 
Nếu cột C có công thức thì lại... phiền
Ủng hộ cách dùng 2 mảng riêng, không đụng chạm gì nhau sẽ không.. mích lòng

Thầy ơi em dùng hai mảng riêng rồi mà sao em làm không chuẩn ở đâu mà không được như kết quả mong muốn nhỉ. mảng tarr đang bị lệch đi một ô.
 
Upvote 0
Dùng 1 mảng có cái lợi là tách rời phần code tổng hợp dữ liệu ra phỏi phần code ghi lại dữ liệu. Dễ kiểm soát hơn

Range("A1").Resize(Ubound(dArr), 2).Value = dArr ' copy 2 cột đầu xuống cột A và B
For i = 1 to UBound(dArr) ' chuyển giá trị từ cột thứ 4 sang cột 1
dArr(i, 1) = dArr(i, 4)
Next i
Range("D1").Resize(Ubound(dArr), 1).Value = dArr ' copy cột 1 xuống cột D

Dùng 2 mảng có thể nhanh hơn 1chút, vì tiết kiệm được phần chuyển giá trị. Nếu dữ liệu là số thì đoạn này rất nhanh, không thành vấn đề.
 
Upvote 0
Dùng 1 mảng có cái lợi là tách rời phần code tổng hợp dữ liệu ra phỏi phần code ghi lại dữ liệu. Dễ kiểm soát hơn

Range("A1").Resize(Ubound(dArr), 2).Value = dArr ' copy 2 cột đầu xuống cột A và B
For i = 1 to UBound(dArr) ' chuyển giá trị từ cột thứ 4 sang cột 1
dArr(i, 1) = dArr(i, 4)
Next i
Range("D1").Resize(Ubound(dArr), 1).Value = dArr ' copy cột 1 xuống cột D

Dùng 2 mảng có thể nhanh hơn 1chút, vì tiết kiệm được phần chuyển giá trị. Nếu dữ liệu là số thì đoạn này rất nhanh, không thành vấn đề.

Bạn VetMini có thể xem cách mình làm ở bài #812 xem vì sao nó không nhảy đúng được không?
 
Upvote 0
Không biết về đường dài, find có nhanh hơn hay không. Nhưng với dữ liệu hiện tại, thì mảng nhanh hơn đó.
Mã:
    lIndex = Application.WorksheetFunction.Match(sArr1(i, 1), Rng, 0)
xử lý trên range thường chậm hơn trên mảng, dùng find hoặc Match mặc dù code giảm 1 vòng lập nhưng không bù được tốc độ, rất nhiều bài dùng mảng kết hợp Dic là nhanh nhất, nếu dữ liệu phù hợp, như bài nầy không cần dùng Dic vẫn giảm được số vòng lập
 
Upvote 0
Em có 2 vùng dữ liệu (về kích thước bằng nhau). Em dùng hàm Application.Union nối hai vùng đó lại và gán nó vào mảng (Cụ thể trong file đính kèm em thấy không đúng)). Vậy mong Thầy, Anh(Chị) cho em hỏi mình có thể tạo mảng bằng cách như vậy không ạ
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Em có 2 vùng dữ liệu (về kích thước bằng nhau). Em dùng hàm Application.Union nối hai vùng đó lại và gán nó vào mảng (Cụ thể trong file đính kèm em thấy không đúng)). Vậy mong Thầy, Anh(Chị) cho em hỏi mình có thể tạo mảng bằng cách như vậy không ạ
Khi 2 vùng không liên tục như trường hợp của bạn thì không được.
Bạn kiểm tra: msgbox cot (kết quả =1)
Nếu thay Set eRng = .Range("B6:B18") khi đó Rng là vùng liên lục, và kết quả (1) = (2)
 
Upvote 0
Khi 2 vùng không liên tục như trường hợp của bạn thì không được.
Bạn kiểm tra: msgbox cot (kết quả =1)
Nếu thay Set eRng = .Range("B6:B18") khi đó Rng là vùng liên lục, và kết quả (1) = (2)
Dạ cám ơn anh. Em đang tập tành viết hàm tìm dữ liệu theo cấu trúc kiểu (Vungdulieu; MaTK;Vungdulieu) nên em định ép 2 vùng đó vào 1 mảng và thực thi trên mảng đó .
 
Upvote 0
Định nghĩa của mảng là vùng dữ liệu liên tục.
VBA cho phép bạn chuyển 1 vùng range sang mảng vì nó không đi ngược định nghĩa này. Nếu vùng range của bạn khong liên tục, VBA phải có cách định nghĩa lại cách chuyển biến (map) từ 2 vùng khong liên tục thành 1 vùng liên tục.
Hiện thời thì MS chưa thấy cần thiết phải định nghĩa lại cho nên nó chưa cho phép làm.

Kỹ thuật gần nhất là tạo 1 mảng với 2 mảng
Dim mang(1 to 2) as variant
mang(1) = range1.value
mang(2) = range2.value

Lúc xét mảng thì nhét code, hễ hết mang(1) thì chuyển sang mang(2)
(code như thế nào thì phải tuỳ cách dùng)
 
Upvote 0
Định nghĩa của mảng là vùng dữ liệu liên tục.
VBA cho phép bạn chuyển 1 vùng range sang mảng vì nó không đi ngược định nghĩa này. Nếu vùng range của bạn khong liên tục, VBA phải có cách định nghĩa lại cách chuyển biến (map) từ 2 vùng khong liên tục thành 1 vùng liên tục.
Hiện thời thì MS chưa thấy cần thiết phải định nghĩa lại cho nên nó chưa cho phép làm.

Kỹ thuật gần nhất là tạo 1 mảng với 2 mảng
Dim mang(1 to 2) as variant
mang(1) = range1.value
mang(2) = range2.value

Lúc xét mảng thì nhét code, hễ hết mang(1) thì chuyển sang mang(2)
(code như thế nào thì phải tuỳ cách dùng)
Cám ơn thầy cho em hiểu thêm kiến thức về mảng. Lúc đầu em nhầm tưởng dùng hàm Union gép lại thì tạo được 1 vùng liên tục
 
Upvote 0
Ý định của em là muốn bớt cái tArr cho nhẹ bớt như trong file đính kèm. Anh sửa hộ em với
Bạn để ý thêm:
- Nếu vùng chọn là 1 cell thì sao?
- Nếu vùng chọn nhiều hơn 1 cột, nhiều hơn 1 hàng thì sao?
- Có cần phải xoay lại vùng về chiều đứng không?
- Nếu vùng chọn là nhiều hàng, nhiều cột thì mặc định bạn chọn hàng 1 (cột 1) chẳng hạn, và xét các phần tử ở 2 vùng khi cùng chỉ số.
 
Upvote 0
Trường hợp của bạn tôi nghĩ có lẽ dùng kỹ thuật 1 mảng lớn liên tục là DỄ NHẤT.

1. Tìm số dòng tổng cộng.
2. Lúc copy từ range1 ra mảng copy dư thêm luôn tất cả số dòng
3. copy từ range2 ra 1 mảng tạm
4. copy mảng tạm vào phần dư trên mảng chính.

Tôi nhớ hình như thớt này đã có bài như thế rồi. Bạn chịu khó tìm. Nếu không thấy thì tôi nghĩ khả năng bạn viết code này không khó.
 
Upvote 0
Trường hợp của bạn tôi nghĩ có lẽ dùng kỹ thuật 1 mảng lớn liên tục là DỄ NHẤT.

1. Tìm số dòng tổng cộng.
2. Lúc copy từ range1 ra mảng copy dư thêm luôn tất cả số dòng
3. copy từ range2 ra 1 mảng tạm
4. copy mảng tạm vào phần dư trên mảng chính.

Tôi nhớ hình như thớt này đã có bài như thế rồi. Bạn chịu khó tìm. Nếu không thấy thì tôi nghĩ khả năng bạn viết code này không khó.
Dạ . Trước em làm theo cấu trúc hàm VLOOKUP (được có 1 chiều thôi ạ). Nhưng thấy cấu trúc hàm Sumif hay hay nên thử xem có được không
Cám ơn thầy nhiều. Rất mong được sự giúp đỡ từ thầy./
 
Upvote 0
Code Vlookup nhiều vùng nè:

Mã:
' hàm sử dụng VLookup để tìm trên nhiều ranges
' lưu ý là hàm được đơn giản hoá, khong có các code trắc nghiệm sự hợp lý của tham số
' tham số:
' vl: trị cần tìm
' rgs: mảng các ranges
' col: cột cần trả về
' khong có tham thứ tư vì tìm từng range khong thể thực hiện theo kiểu tìm khoảng (1, -1)
' nếu muốn tìm kiểu này bắt buộc phải chập các ranges lại và sắp xếp tăng/giảm dần

Function MRVLookup(byVal vl, byVal rgs, byVal col)
Dim rg as range
For each rg in rgs
MRVLookup = Application.Vlookup(vl, rg, col, 0)
If Not IsError(MRVLookup) Then Exit Function
Next rg
End Function

' code gọi hàm
ketqua = MRVLookup(tricantim, Array( Sheet1.Range("A1:C10"), Sheet1.Range("A100:C150"), Sheet2.Range("B1:D10") ), 3)
If Not IsError(ketqua) Then
 
Upvote 0
Em có 2 vùng dữ liệu (về kích thước bằng nhau). Em dùng hàm Application.Union nối hai vùng đó lại và gán nó vào mảng (Cụ thể trong file đính kèm em thấy không đúng)). Vậy mong Thầy, Anh(Chị) cho em hỏi mình có thể tạo mảng bằng cách như vậy không ạ
Làm vầy nè:
Mã:
Function BigRange(ByVal SrcRng As Range) As Range
  Set BigRange = Range(Replace(SrcRng.Address, ",", ":"))
End Function
Sub Taomang2()
  Dim SRng As Range, eRng As Range
  Dim Rng As Range, hang As Long, Cot As Long
  Dim sArr
  With Sheet1
    Set SRng = .Range("A6:A18"): Set eRng = .Range("C6:C18")
    Set Rng = BigRange(.Range(SRng, eRng))
    sArr = Rng.Value
    hang = UBound(sArr, 1): Cot = UBound(sArr, 2)
    .Range("I6").Resize(hang, Cot) = sArr
  End With
End Sub
 
Upvote 0
Code tạo một mảng lớn liên tục từ 2 ranges
Mã:
' có 2 ranges, rg1 và rg2. Tạo một mảng lớn với dữ liệu từ 2 ranges này
Dim mang, mangPhu
Dim soCot as Long, soDong as Long, i as Long, j as long
soCot = Application.Max(rg1.columns.count, rg2.columns.count) ' số cột bắt buộc phải là số lớn giữa 2 ranges
soDong = rg1.rows.count + rg2.rows.count ' số dòng là tổng 2 ranges
mang = rg1.Resize(soDong, soCot).Value ' chép rg1 vào mảng, với số dòng dư
mangPhu = rg2.Resize(, soCot).Value ' chép rg2 vào mảng phụ
soDong = rg1.rows.count ' bắt đầu chép mảng phụ vào mảng chính
For i = 1 to rg2.rows.count
  soDong = soDong + 1
  For j = 1 to soCot
    mang(soDong, j) = mangPhu(i, j)
  Next j
Next i
 
Upvote 0
Ủa cái tên "Lười Biếng Nhấc Máy" ấy là phụ nữ hở? còn phya mới tin.

@LBNM: ndu không thường dùng tiếng Tây nên hang có nghĩa là Tùy Chọn : { "hang", "háng", "hàng", "hãng", "hạng" }
Nếu gặp mấy người hay viết Đía Ồn thì hang có nghĩa là treo, và cot có nghĩa là cái giường em bé
 
Upvote 0
Cho em hỏi có câu lệnh nào để kiểm tra trong một mảng có chứa giá trị là số hay không ? Tạm thời em dùng phương thức Find.
 
Lần chỉnh sửa cuối:
Upvote 0
Cho em hỏi có câu lệnh nào để kiểm tra trong một mảng có chứa giá trị là số hay không ? Tạm thời em dùng phương thức Find.
+ Nếu bạn đầu, khai báo mảng có kiểu dữ liệu rõ ràng, thì đã biết.
+ Nếu khai báo mảng không đi kèm kiểu dữ liệu, thì mình thường dùng vòng lặp duyệt qua các phần tử của mảng.Để kiểm tra số mình sẽ dùng Isnumeric function để kiểm tra.
 
Upvote 0
+ Nếu bạn đầu, khai báo mảng có kiểu dữ liệu rõ ràng, thì đã biết.
+ Nếu khai báo mảng không đi kèm kiểu dữ liệu, thì mình thường dùng vòng lặp duyệt qua các phần tử của mảng.Để kiểm tra số mình sẽ dùng Isnumeric function để kiểm tra.
Hàm isnumber sẽ không đảm bảo chính xác.
Mã:
MsgBox IsNumeric("123")
 
Upvote 0
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
PHP:
  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á.
 
Lần chỉnh sửa cuối:
Upvote 0
PHP:
  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ị?
Chắc là không có cách!
 
Upvote 0
Chắc là không có cá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?
 
Upvote 0
Code này có gì sai mà toàn báo lỗi ở dòng If ActiveSheet.Name = sArray(1, j).Value Then
For j = 1 To 32
trong khi ubound(sArray,2)=31 --> sArray(1,32)?

Mảng thì không có thuộc tính .Value: sArray(1, j).Value

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
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
 
Lần chỉnh sửa cuối:
Upvote 0
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á
 
Upvote 0
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á
So sánh chuỗi trong VBA thì dùng Like
ví dụ:
PHP:
vba.ucase(activesheet.name) like vba.ucase(sArray(1, j).Value)
 
Upvote 0
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.

[D13].Resize(1, k) = WorksheetFunction.Transpose(dArr)
 
Lần chỉnh sửa cuối:
Upvote 0
Mình thêm lệnh On Error Resume Next thì không lỗi nữa
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)
 
Lần chỉnh sửa cuối:
Upvote 0
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.
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
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.
PHP:
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
 
Upvote 0
PHP:
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

Cảm ơn befaint nhé, bài này mình học được nhiều kiến thức hay rồi :)
 
Upvote 0
Cho em hỏi về in có điều kiện như sau:

PHP:
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?
 
Upvote 0
Cho em hỏi về in có điều kiện như sau:

PHP:
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?
Thông thường để in hàng loạt, người ta thiết kế 1 sheet làm Form để in (chứ không dùng cách filter ở bảng dữ liệu rồi in).

http://www.giaiphapexcel.com/diendan/threads/lấy-dữ-liệu-từ-file-excel-vào-word.121498/#post-761300
http://www.giaiphapexcel.com/dienda...excel-từ-bảng-lương-excel.125319/#post-785780
 
Upvote 0
Với một bài về mảng gần tương tự bài trước mình gửi mà không biết vì sao code nó không chạy ra kết quả mong muốn. Mọi người giúp mình nhé.
 

File đính kèm

Upvote 0
Cho em hỏi về in có điều kiện như sau:

PHP:
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.
 
Upvote 0
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
 
Upvote 0
Với một bài về mảng gần tương tự bài trước mình gửi mà không biết vì sao code nó không chạy ra kết quả mong muốn. Mọi người giúp mình nhé.
PHP:
Sub hochoi2()
Dim mangDL(), i As Integer, j As Integer, k As Integer
Dim maxRow As Long, maxCol As Long

With Sheets("Check")
    mangDL = .Range("B2").Resize(21, 31).Value
    maxRow = UBound(mangDL, 1): maxCol = UBound(mangDL, 2)
ReDim KQ(1 To maxRow, 1 To maxCol)
    For i = 1 To maxRow
        For j = 1 To maxCol
            If mangDL(i, j) > 400 Then
                KQ(i, j) = mangDL(i, j)
            End If
        Next j
    Next i
    Sheets("19").Range("B9").Resize(maxRow, maxCol) = KQ
End With

End Sub
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
PHP:
Sub hochoi2()
Dim mangDL(), i As Integer, j As Integer, k As Integer
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 = 1 To maxRow
        For j = 1 To maxCol
            If mangDL(i, j) > 400 Then
                KQ(i, j) = mangDL(i, j)
            End If
        Next j
    Next i

If k Then

    Sheets("19").Range("A9").Resize(22, 31) = KQ

End If

End With

End Sub

Bởi vì không đặt biến k cho nên kết quả chỉ loại bỏ giá trị ở các cột không thỏa mãn, mình muốn bỏ hẳn các STT không đạt yêu cầu thì không cho vào mảng :).
 
Upvote 0
PHP:
Sub hochoi2()
Dim mangDL(), i As Integer, j As Integer, k As Integer
Dim maxRow As Long, maxCol As Long

With Sheets("Check")
    mangDL = .Range("B2").Resize(21, 31).Value
    maxRow = UBound(mangDL, 1): maxCol = UBound(mangDL, 2)
ReDim KQ(1 To maxRow, 1 To maxCol)
    For i = 1 To maxRow
        For j = 1 To maxCol
            If mangDL(i, j) > 400 Then
                KQ(i, j) = mangDL(i, j)
            End If
        Next j
    Next i
    Sheets("19").Range("B9").Resize(maxRow, maxCol) = KQ
End With

End Sub

Bạn tiến hành duyệt 1 lần nữa, xóa các dòng trống đi, nữa là xong.
 
Upvote 0
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:
With Sheets("Check")
mangDL = .Range("A1").Resize(22, 31).Value
Có một lần dùng tới thì viết luôn mangDL = Sheets("Check").Range("A1").Resize(22, 31).Value (bỏ with/ end with)

PHP:
Sheets("19").Range("A9").Resize(k, j)
Khi thoát khỏi vòng lặp thì j=j+1, trường hợp này thì j=maxCol+1
 
Upvote 0
PHP:
Sub hochoi2()
Dim mangDL(), i As Integer, j As Integer, k As Integer, l As Long
Dim maxRow As Long, maxCol As Long

mangDL = Sheets("Check").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
                j = maxCol + 1
                KQ(k, 1) = mangDL(i, 1)
                KQ(k, j) = mangDL(i, j)
            End If
        Next j
        Exit For
    Next i
MsgBox k

If k Then
Sheets("19").Range("A9").Resize(k, j) = KQ
End If

End Sub

Không biết mình làm sai ở bước nào mà kết quả báo k = 0 befaint ạ. Và cái Exit For tác dụng để nếu không tìm thấy giá trị thỏa mãn thì thoát vòng lặp để tránh lỗi đúng không nhỉ?
 
Upvote 0
Không biết mình làm sai ở bước nào mà kết quả báo k = 0 befaint ạ. Và cái Exit For tác dụng để nếu không tìm thấy giá trị thỏa mãn thì thoát vòng lặp để tránh lỗi đúng không nhỉ?
Bài trên chỉ 2 chỗ cần sửa và có trích dẫn rõ/ cụ thể chỗ nào cần sửa.

Sao lại cho j = maxCol + 1 vào vòng lặp làm gì vậy? :(
 
Upvote 0
Bài trên chỉ 2 chỗ cần sửa và có trích dẫn rõ/ cụ thể chỗ nào cần sửa.

Sao lại cho j = maxCol + 1 vào vòng lặp làm gì vậy? :(
Chỗ 1 mình sửa chắc không có vấn đề gì rồi. Nhưng còn chỗ 2 thật sự là chưa hiểu j=j+1. Xét lần lượt cột nếu cột nào thỏa mãn thì lấy số thứ tự cột đó chứ nhỉ.
 
Lần chỉnh sửa cuối:
Upvote 0
Mình chịu rồi befaint ơi, sửa các kiểu không được. Bấm F8 chạy thử thì thấy đã duyệt hết các vòng lặp i và j báo lỗi gán mảng:
KQ(k, 1) = mangDL(i, 1)
KQ(k, j) = mangDL(i, j)
PHP:
Sub hochoi2()
Dim mangDL()
Dim maxRow As Integer, maxCol As Integer, i As Integer, j As Integer, k As Integer, l As Integer

mangDL = Sheets("Check").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 Sub
 
Upvote 0
Học bài thì cố nhớ 2 điểm này:
1. Báo lỗi gì? chép lai (hoặc snipping tool lại)
2. Tránh viết tiết kiệm dòng như thế này
maxRow = UBound(mangDL, 1): maxCol = UBound(mangDL, 2)
nó làm cho đọc code lại cực bỏ bố. Lúc debug, muón biết một biến được khởi ở chỗ nào, ngừoi ta lướt ngược từ dưới (chỗ được sử dụng) lên cho đến chỗ thấy được gán. Lướt lẹ thì chỉ đọc bên trái. Tìm maxCol đỏ con mắt.
(sau khi code chạy êm rồi người ta mới dồn dòng để tiết kiệm.

Tho code trên, chiều thứ nhất của mảng KQ chỉ đến maxRow trong khi khả năng của k lên đến maxRow*maxCol
 
Upvote 0
Học bài thì cố nhớ 2 điểm này:
1. Báo lỗi gì? chép lai (hoặc snipping tool lại)
2. Tránh viết tiết kiệm dòng như thế này
maxRow = UBound(mangDL, 1): maxCol = UBound(mangDL, 2)
nó làm cho đọc code lại cực bỏ bố. Lúc debug, muón biết một biến được khởi ở chỗ nào, ngừoi ta lướt ngược từ dưới (chỗ được sử dụng) lên cho đến chỗ thấy được gán. Lướt lẹ thì chỉ đọc bên trái. Tìm maxCol đỏ con mắt.
(sau khi code chạy êm rồi người ta mới dồn dòng để tiết kiệm.

Tho code trên, chiều thứ nhất của mảng KQ chỉ đến maxRow trong khi khả năng của k lên đến maxRow*maxCol

Đúng thật là mảng khai báo thiếu phần tử, code đã ra kết quả tuy nhiên phần dồn dòng mình vẫn chưa nghĩ ra cách, bạn chỉ giúp mình nhé.
 

File đính kèm

Upvote 0
Code của bạn không có chú thích giải thuật. Tôi có biết bạn muốn làm cái gì đâu mà hỏi cách "dồn dòng".
 
Upvote 0
Code của bạn không có chú thích giải thuật. Tôi có biết bạn muốn làm cái gì đâu mà hỏi cách "dồn dòng".

Bạn ơi trong file mình có ghi mà.

Tại sheets 19 Từ A8 đến AE8 mình muốn điền giá trị tương ứng của sheet Check nếu các giá trị trong vùng A2:AF22 > 400 thì sẽ lấy và gán STT của sheet Check vào STT của sheet 19. Giá trị của cột thỏa mãn gán vào cột tương ứng của sheet 19.

Hiện tại của mình ra kết quả nhưng nó trải dài mà không thành một dòng. Mình muốn kết quả của trường hợp B như sau. Các trường hợp khác tương tự.

Trình độ sư phạm của mình kém nên giải thích có phần dài dòng mà không chắc dễ hiểu không, có gì bạn góp ý nhé!

upload_2017-7-24_13-15-45.png
 
Upvote 0
Có ai hiểu vấn đề giúp mình với, loay hoay mấy hôm mà không nghĩ ra cách nào. Như ảnh đính kèm ở #899 ví dụ B trong cột STT có các giá trị thỏa mãn >400 cho nên sẽ liệt kê ra các giá trị đó thẳng cùng một hàng. Code của mình mới chỉ làm được việc là nếu giá trị B có bao nhiêu cột thỏa mãn thì sẽ có bấy nhiêu dòng thể hiện B có giá trị thỏa mãn đó. Mình muốn nó thể hiện trên cùng 1 dòng thôi.
 
Upvote 0
Có ai hiểu vấn đề giúp mình với, loay hoay mấy hôm mà không nghĩ ra cách nào. Như ảnh đính kèm ở #899 ví dụ B trong cột STT có các giá trị thỏa mãn >400 cho nên sẽ liệt kê ra các giá trị đó thẳng cùng một hàng. Code của mình mới chỉ làm được việc là nếu giá trị B có bao nhiêu cột thỏa mãn thì sẽ có bấy nhiêu dòng thể hiện B có giá trị thỏa mãn đó. Mình muốn nó thể hiện trên cùng 1 dòng thôi.
 

File đính kèm

Upvote 0
Cảm ơn Befaint, code vượt sự mong đợi của mình. Cảm ơn rất nhiều!
 
Lần chỉnh sửa cuối:
Upvote 0
Em có một thắc mắc
PHP:
For H = 3 To 128 Step 4
    If sArr(1, H) = "Sunday" Then
        sArr(1, H).Offset(-2, H - 1).Resize(, 4).ThemeColor = xlThemeColorAccent6
    End If
Next H

Offeset hình như không dùng được cho mảng phải không ạ. Em muốn code duyệt theo cột H, nếu phát hiện có giá trị Sunday thì từ vị trí đó di dời lên trên hai dòng và lùi xuống 1 cột sau đó Resize sang 4 cột và đổ màu cho nó.
 
Upvote 0
Em có một thắc mắc
PHP:
For H = 3 To 128 Step 4
    If sArr(1, H) = "Sunday" Then
        sArr(1, H).Offset(-2, H - 1).Resize(, 4).ThemeColor = xlThemeColorAccent6
    End If
Next H

Offeset hình như không dùng được cho mảng phải không ạ. Em muốn code duyệt theo cột H, nếu phát hiện có giá trị Sunday thì từ vị trí đó di dời lên trên hai dòng và lùi xuống 1 cột sau đó Resize sang 4 cột và đổ màu cho nó.
Offset là thuộc tính của range/cells
So sánh chuỗi trong VBA dùng Like (đã nói từ mấy bài trước).
 
Upvote 0
Offset là thuộc tính của range/cells
So sánh chuỗi trong VBA dùng Like (đã nói từ mấy bài trước).

Ừm, đã sửa rồi mà vẫn quen tay dùng toán tử "=" :). Vậy mảng thì có thuộc tính nào tương tự như vậy không befaint?

Mình thử Cell thì báo lỗi mà cái cell này mình chưa tìm hiểu được nhiều
PHP:
For H = 3 To 128 Step 4
    If .Cells(6, H).Value Like "Sunday" Then
        .Cells(4, H - 1).Resize(, 4).ThemeColor = xlThemeColorAccent6
    End If
Next H

Mình nhầm H, không phải "H"
 
Lần chỉnh sửa cuối:
Upvote 0
Ừm, đã sửa rồi mà vẫn quen tay dùng toán tử "=" :). Vậy mảng thì có thuộc tính nào tương tự như vậy không befaint?

Mình thử Cell thì báo lỗi mà cái cell này mình chưa tìm hiểu được nhiều
PHP:
For H = 3 To 128 Step 4
    If .Cells(6, "H").Value Like "Sunday" Then
        .Cells(4, "H" - 1).Resize(, 4).ThemeColor = xlThemeColorAccent6
    End If
Next H
Bạn sử dụng gì thì nên đọc tài liệu trước...
"H" là chuỗi, không đúng với cú pháp của .Cells(), không tính toán được "H"-1
01.jpg
02.jpg

------------
Chắc phải học khóa nào đó cho nhanh thôi!!!
 
Lần chỉnh sửa cuối:
Upvote 0
Mình nhầm Befaint ơi, nhưng sửa thành vậy vẫn không được. Code không báo lỗi nữa nhưng chẳng thấy có tác dụng gì cả.

PHP:
For H = 3 To 128 Step 4
    If Sheets("BCC").Cells(6, H).Value Like "Sunday" Then
        Sheets("BCC").Cells(4, H - 1).Resize(, 4).ThemeColor = xlThemeColorAccent6
    End If
Next H
 
Lần chỉnh sửa cuối:
Upvote 0
Mình nhầm Befaint ơi, nhưng sửa thành vậy vẫn không được

PHP:
For H = 3 To 128 Step 4
    If Sheets("BCC").Cells(6, H).Value Like "Sunday" Then
        Sheets("BCC").Cells(4, H - 1).Resize(, 4).ThemeColor = xlThemeColorAccent6
    End If
Next H

Được rồi Befaint nhé :). Cảm ơn bạn!
Không được chỗ nào? :(
.Resize(, 4) viết chính tắc để rõ ràng, dễ hiểu. Chứ có biết trước cái dấu phẩy đó là gì đâu.

"từ vị trí đó di dời lên trên hai dòng và lùi xuống 1 cột sau đó Resize sang 4 cột"
=cell đó.offset(0,-1).resize(1,4)
Hay?
=cell đó.offset(-2,-1).resize(1,4)
 
Upvote 0
Không được chỗ nào? :(
.Resize(, 4) viết chính tắc để rõ ràng, dễ hiểu. Chứ có biết trước cái dấu phẩy đó là gì đâu.

"từ vị trí đó di dời lên trên hai dòng và lùi xuống 1 cột sau đó Resize sang 4 cột"
=cell đó.offset(0,-1).resize(1,4)
Hay?
=cell đó.offset(-2,-1).resize(1,4)

Ý mình là nếu tìm được giá trị Sunday ở dòng 6 cột H thì: Tại dòng 4, cột H-1 và resize sang 4 cột kế bên sẽ đổ màu theo ý mình. Mình thử Msgbox thì đã tìm thấy Sunday rồi mà đến đoạn đổ màu thì báo lỗi Run time erro

Hoặc theo gợi ý của bạn mình viết lại đoạn code đổ màu như sau:

.Cells(6, H).Offset(-2, -1).Resize(1, 4).ThemeColor = xlThemeColorAccent6 cũng báo lỗi trên :(

Sửa thành như vậy .Cells(6, H).Offset(-2, -1).Resize(1, 4) = 1 thì không báo lỗi nhưng vùng cũng không thấy đổ giá trị 1
 
Upvote 0
Ý mình là nếu tìm được giá trị Sunday ở dòng 6 cột H thì: Tại dòng 4, cột H-1 và resize sang 4 cột kế bên sẽ đổ màu theo ý mình. Mình thử Msgbox thì đã tìm thấy Sunday rồi mà đến đoạn đổ màu thì báo lỗi Run time erro

Hoặc theo gợi ý của bạn mình viết lại đoạn code đổ màu như sau:

.Cells(6, H).Offset(-2, -1).Resize(1, 4).ThemeColor = xlThemeColorAccent6 cũng báo lỗi trên :(

Sửa thành như vậy .Cells(6, H).Offset(-2, -1).Resize(1, 4) = 1 thì không báo lỗi nhưng vùng cũng không thấy đổ giá trị 1
Cái "Sunday" ở trên là kết quả của định dạng Date thì phải dùng Cell.Text
 
Upvote 0
Cái "Sunday" ở trên là kết quả của định dạng Date thì phải dùng Cell.Text

Befaint ơi Sunday là dạng text do mình dùng if
=+IF(WEEKDAY(K6)=1,"Sunday","").
Và thực tế thì đã tìm ra đúng 4 ngày chủ nhật trong vòng lặp For, tuy nhiên tìm xong rồi không thấy nó làm gì cả.
 
Upvote 0
Befaint ơi Sunday là dạng text do mình dùng if
=+IF(WEEKDAY(K6)=1,"Sunday","").
Và thực tế thì đã tìm ra đúng 4 ngày chủ nhật trong vòng lặp For, tuy nhiên tìm xong rồi không thấy nó làm gì cả.
- Bài này không liên quan gì tới chủ đề của thớt: Mảng trong VBA
Nếu có tiếp tục thì vào thớt gỡ rối, giải thích.
- Loằng ngoằng thế sao không gửi cái file, hoặc xét luôn cái cell chứa date ấy
Trong VBA thì:
PHP:
Ngayxet=cells(6,H).value2
If Weekday(Ngayxet, vbSunday)=1 then
- Lập thớt mới!!!!
 
Upvote 0
Cảm ơn Befaint, mình làm được rồi. Ban đầu là mình có ý định xem dùng mảng mà lên mới post trong thread này, hề hề.
 
Upvote 0
Em có viết giùm cho bạn em một file sổ cái có thể truy vấn theo đối tượng, tuy nhiên em thấy code của em vẫn còn rối và tốc độ vẫn còn khá chậm, vì dữ liệu trong file lớn lắm, maximum của TK ps là trên 13k dòng. Nên em muốn nhờ mọi người xem giúp em đoạn code của em có thể nào gọn và nhanh hơn nữa được không, em xin cám ơn cả nhà.
Sub test()
On Error Resume Next
Application.ScreenUpdating = False
Application.EnableEvents = False
Sheet5.Activate
Sheet5.ShowAllData
Sheet5.Range(Sheet5.Range("A9"), Sheet5.Range("A1048576")).EntireRow.ClearContents
Dim arr
Dim i, j
Dim sArray
Dim DK_1, DK_2
j = 9
DK_1 = Sheet5.Range("D1").Value
DK_2 = Sheet5.Range("D2").Value
arr = Sheet1.Range(Sheet1.Range("A4"), Sheet1.Range("A1048576").End(xlUp).Offset(0, 10)).Value
If DK_2 = 0 Then
For i = LBound(arr, 1) To UBound(arr, 1)
If arr(i, 4) = DK_1 And arr(i, 5) = DK_1 Then
Sheet5.Range("A" & j & ":D" & j).Value = Sheet1.Range("A" & i + 3 & ":D" & i + 3).Value
Sheet5.Cells(j, 5).Value = arr(i, 6)
Sheet5.Cells(j, 6).Value = arr(i, 6)
Sheet5.Range("G" & j & ":K" & j).Value = Sheet1.Range("G" & i + 3 & ":K" & i + 3).Value
j = j + 1
ElseIf arr(i, 4) = DK_1 Then
Sheet5.Range("A" & j & ":C" & j).Value = Sheet1.Range("A" & i + 3 & ":C" & i + 3).Value
Sheet5.Cells(j, 4).Value = arr(i, 5)
Sheet5.Cells(j, 5).Value = arr(i, 6)
Sheet5.Range("G" & j & ":K" & j).Value = Sheet1.Range("G" & i + 3 & ":K" & i + 3).Value
j = j + 1
ElseIf arr(i, 5) = DK_1 Then
Sheet5.Range("A" & j & ":C" & j).Value = Sheet1.Range("A" & i + 3 & ":C" & i + 3).Value
Sheet5.Cells(j, 4).Value = arr(i, 4)
Sheet5.Cells(j, 6).Value = arr(i, 6)
Sheet5.Range("G" & j & ":K" & j).Value = Sheet1.Range("G" & i + 3 & ":K" & i + 3).Value
j = j + 1

End If
Next i
End If
If DK_2 <> 0 Then
For i = LBound(arr, 1) To UBound(arr, 1)
If arr(i, 4) = DK_1 And arr(i, 5) = DK_1 And (DK_2 = arr(i, 8) Or DK_2 = arr(i, 9)) Then
Sheet5.Range("A" & j & ":D" & j).Value = Sheet1.Range("A" & i + 3 & ":D" & i + 3).Value
Sheet5.Cells(j, 5).Value = arr(i, 6)
Sheet5.Cells(j, 6).Value = arr(i, 6)
j = j + 1
ElseIf arr(i, 4) = DK_1 And (arr(i, 8) = DK_2 Or arr(i, 9) = DK_2) Then
Sheet5.Range("A" & j & ":C" & j).Value = Sheet1.Range("A" & i + 3 & ":C" & i + 3).Value
Sheet5.Cells(j, 4).Value = arr(i, 5)
Sheet5.Cells(j, 5).Value = arr(i, 6)
Sheet5.Range("G" & j & ":K" & j).Value = Sheet1.Range("G" & i + 3 & ":K" & i + 3).Value
j = j + 1
ElseIf arr(i, 5) = DK_1 And (arr(i, 8) = DK_2 Or arr(i, 9) = DK_2) Then
Sheet5.Range("A" & j & ":C" & j).Value = Sheet1.Range("A" & i + 3 & ":C" & i + 3).Value
Sheet5.Cells(j, 4).Value = arr(i, 4)
Sheet5.Cells(j, 6).Value = arr(i, 6)
Sheet5.Range("G" & j & ":K" & j).Value = Sheet1.Range("G" & i + 3 & ":K" & i + 3).Value
j = j + 1
End If
Next i
End If
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
 
Upvote 0
Cho em hỏi trong vba thì làm sao để tạo được mảng có kích thước là 0 như trong hình, tất nhiên là sẽ không dùng listbox. ( trong hình là mảng 0 x 10).
Untitled.png
 
Upvote 0
Dim Arr As Variant
ReDim Arr(0 To 10)

Dim Arr(0 To 10) As Variant

Dim Arr(1 to 10, 1 to 5) As Variant
 
Upvote 0
Upvote 0
Upvote 0
Anh chị cho minh hỏi có cách nào lấy dữ liệu 1 cột hoặc 1 hàng của mảng 2 chiều ra để gán vào mảng 1 chiều khác không ạ?(không dùng vòng lặp(for, do while,..)) Thanks
 
Upvote 0
Anh chị cho minh hỏi có cách nào lấy dữ liệu 1 cột hoặc 1 hàng của mảng 2 chiều ra để gán vào mảng 1 chiều khác không ạ?(không dùng vòng lặp(for, do while,..)) Thanks
Mục đích để nối chuỗi?
Cách:
# Lấy cột:
- Gán mảng 2 chiều xuống bảng tính.
- Mảng 1 chiều = Application.Transpose(cột cần lấy trên bảng tính)

# Lấy hàng:
- Transpose mảng 2 chiều, rồi gán xuống bảng tính.
- Mảng 1 chiều = Application.Transpose(cột cần lấy trên bảng tính ). Cột cần lấy trên bảng tính = hàng cần lấy của mảng 2 chiều.
 
Upvote 0
Mục đích để nối chuỗi?
Cách:
# Lấy cột:
- Gán mảng 2 chiều xuống bảng tính.
- Mảng 1 chiều = Application.Transpose(cột cần lấy trên bảng tính)

# Lấy hàng:
- Transpose mảng 2 chiều, rồi gán xuống bảng tính.
- Mảng 1 chiều = Application.Transpose(cột cần lấy trên bảng tính ). Cột cần lấy trên bảng tính = hàng cần lấy của mảng 2 chiều.

Thanks bạn nhiều, mình cần làm trên chạy code tren VBA thôi, không đụng tới các Worksheet
 
Upvote 0

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

Back
Top Bottom