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,906
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ị
 
Em viết như vầy:
PHP:
Option Explicit
Sub dic2()
Dim dic, i, j, k, mang()
Set dic = CreateObject("Scripting.Dictionary")
For i = 2 To 21
If Not dic.exists(Cells(i, 2).Value) Then
   j = j + 1
   dic.Add Cells(i, 2).Value, ""
   ReDim mang(1 To dic.Count, 1 To 6)
   mang(j, 1) = j
   For k = 2 To 6
      mang(j, k) = Cells(i, k).Value
   Next k
End If
Next i
    Range("J9").Resize(dic.Count, 6) = mang()
End Sub

Thì nó chỉ ra kết quả hàng cuối cùng, khi em thêm từ khóa Preserve vào sau Redim thì lại bị bắt lỗi. Mọi người giúp em thêm lần nữa với ạ. :.,:.,

1/ Bạn khai báo mang(), nghĩa là khai báo mảng 2 chiều
2/ Mảng 2 chiều khi Redim thì nó tạo lại 1 mảng "trống trơn".
3/ Mảng 2 chiều không thể Preserve.
4/ Bạn muốn thử dùng mảng thì chơi luôn mảng, sao xài Cells() cho "nửa nạc nửa mỡ"?
5/ Mới bước vào "con đường đau khổ" thì phải tập khai báo tường minh các biến, đừng "làm biếng" thành thói quen, dù là code vẫn chạy.
6/ Trường hợp của bạn, dữ liệu có lẽ từ B2 đến F21? Xác định được mảng Data thì dựa vào chiều dọc ngang của mảng Data mà khai báo mang(), dùng mảng thì dù bạn khai bào "dư chút đỉnh" cũng chẳng "bựa" chút nào khi chạy code đâu mà sợ.
6/ Đọc code của bạn có thể xài cái này:
PHP:
Sub dic2()
Dim Dic As Object, i As Long, j As Long, k As Long, sArr(), Mang()
Set Dic = CreateObject("Scripting.Dictionary")
sArr = Range("B2:F21").Value               '<-----------Bằng cách nào đó bạn phải xác định được Range() này'
ReDim Mang(1 To UBound(sArr, 1), 1 To UBound(sArr, 2) + 1)
For i = 1 To UBound(sArr, 1)
    If Not Dic.Exists(sArr(i, 1)) Then
        k = k + 1
        Dic.Add sArr(i, 1), ""
        Mang(k, 1) = k
        For j = 1 To UBound(sArr, 2)
            Mang(k, j + 1) = sArr(i, j)
        Next j
    End If
Next i
Range("J9").Resize(k, UBound(Mang, 2)) = Mang
Set Dic=Nothing
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
...
Thì nó chỉ ra kết quả hàng cuối cùng, khi em thêm từ khóa Preserve vào sau Redim thì lại bị bắt lỗi. Mọi người giúp em thêm lần nữa với ạ

Khi Redim, dữ liệu trong mảng sẽ bị xóa. Vì vậy các dòng trước đó sẽ trống trơn.
Khi bạn biết thêm từ khóa Preserve vào thì có lẽ bạn đã biết tại sao nó chỉ cho ra dòng cuối cùng.

Tuy nhiên, cái bạn quên để ý là Redim Preserve chỉ cho phép đổi chiều cuối cùng. Mảng của bạn 2 chiều cho nên nó chỉ cho đổi chiều thứ 2. Điều này đã có nhiều bài bàn cãi qua, và tôi cũng có từng giải thích tại sao VBA lại đặt ta luật như vậy.

Trong bài trước đó, tôi có đề nghị là bạn Redim trước khi bắt đầu vòng lặp. Không phải là không có lý do.

Theo lô gic bài toán, vòng lặp của bạn biết trước là nó sẽ chạy 21 lần, không có lý do gì mảng của bạn không thể redim trước là 21 dòng. Nếu bạn thay đổi số cuối vòng lặp bằng bất cứ cái gì thì cũng có thể thay redim mảng của bạn bằng cái ấy.
 
Upvote 0
quote_icon.png
Nguyên văn bởi Ba Tê

3/ Mảng 2 chiều không thể Preserve.

mình xin phép nghi ngờ điều này

Bạn kia chỉ nói vắn tắt thôi. Bắt bẻ làm gì.
Cần bổ xung thì nói thẳng ra. Úp mở chỉ mất công tranh cãi.
 
Upvote 0
Hình như vẫn Preserve được nhưng chỉ có tác dụng với chiều thứ nhất thì phải

mảng một chiều thì có thể preverse tăng thêm dòng
mảng 2 chiều chỉ có thể preverse tăng thêm cột
(tôi xài từ "dòng", "cột", không biết chính xác trong mảng người ta gọi nó là cái gi.....hihiih)
 
Upvote 0
Đầu xuân, năm mới. Tôi xin được kính chúc các anh chị biên tập viên và các thầy giáo của diễn đàn GPE lời chúc sức khỏe hạnh phúc và thành công. Tôi có một vấn đề này mong các anh chị giúp đỡ viết cho code của nút NHAP. Các yêu cầu đã ghi rõ trong file đính kèm.
Xin trân trọng cảm ơn!

Tôi không biết đăng ở đâu. Nếu có gì sai xin được sự cảm thông của Anh chị em và các thầy nhé!
 

File đính kèm

  • NHAP PHIEU Nhap.xlsx
    19.1 KB · Đọc: 18
Upvote 0
Đầu xuân, năm mới. Tôi xin được kính chúc các anh chị biên tập viên và các thầy giáo của diễn đàn GPE lời chúc sức khỏe hạnh phúc và thành công. Tôi có một vấn đề này mong các anh chị giúp đỡ viết cho code của nút NHAP. Các yêu cầu đã ghi rõ trong file đính kèm.
Xin trân trọng cảm ơn!

Tôi không biết đăng ở đâu. Nếu có gì sai xin được sự cảm thông của Anh chị em và các thầy nhé!

Thứ nhất: Bài của bạn thuộc diện xen ngang; Nó có thể bị xóa cùng với bài này của mình.

Bài này iêu cầu làm bằng macro; Nên nó fải ở trong mục "lập trình"

Điều nữa: Thiết kế trang tính CSDL của bạn sẽ có vấn đề không tốt khi vận hành sau này;
Nếu là mình thì mình tách ra làm 2 bảng dữ liệu như sau:
Trang chính có tên là "Chung" gồm các trường/cột sau:
[STT] Dùng để ghi STT các fiếu
[Mã khóa] - Mã này để liên hệ với trang tính "chi tiết"
[Số fiếu] - Là số fiếu nhập của bạn
[Người giao]
[Người nhận]
[Ghi chú]

Trang thứ hai là có tên là "Chi tiết", gồm các trường
[STT] như trên
[Mã khóa] - Như trên
[Mã hàng]
[Tên hàng]
[Đơn vị tính]
[Đơn giá]
[Số lượng]
[Thành tiền]
Ở trang chi tiết này ta ghi mỗi loại hàng của từng hóa đơn 1 dòng;
Như vậy 2 trang tính này có mối quan hệ 1 - nhiều với nhau
 
Upvote 0
Cảm ơn bác SA_DQ nhiều!. về cấu trúc dữ liệu thị đây chỉ là file ví dụ. Tôi đã làm file có cả mã hàng, tên hàng hóa...
Mong các bác viết hộ phần code để nhập vào sheet tổng hợp.
Cảm ơn!
 
Upvote 0
Tôi dự định chỉ phân quyền cho những user có tên trong danh sách và tại các máy được chỉ định (việc này sẽ được kiểm tra khi file được mở) tôi nghĩ nên dùng mảng và for để tìm trong mảng (nếu tìm không thấy thì đóng file lại), nhưng không biết phải khai báo như thế nào và tìm ra làm sao... Mong các anh chị chỉ giáo.
 

File đính kèm

  • Book1.xlsx
    8.8 KB · Đọc: 11
Upvote 0
Nhờ mọi người xem giúp em File này. Mục đích của em là loại bỏ các giá trị trùng nhau đồng thời sắp xếp lại các phần tử của cột theo thứ tự tăng dần. Em không hiểu sao lại bị báo lỗi ở câu lệnh Redim Preserve ...

Cảm ơn mọi người !
 

File đính kèm

  • sắp xếp.xls
    36 KB · Đọc: 21
Upvote 0
Nhờ mọi người xem giúp em File này. Mục đích của em là loại bỏ các giá trị trùng nhau đồng thời sắp xếp lại các phần tử của cột theo thứ tự tăng dần. Em không hiểu sao lại bị báo lỗi ở câu lệnh Redim Preserve ...

Cảm ơn mọi người !

Nghe đồn là muốn Redim Preserve thì lúc khai báo phải là
Dim mang
Redim mang(.....)

Rồi mới
Redim Preserve được...--=0--=0--=0
 
Upvote 0
Nhờ mọi người xem giúp em File này. Mục đích của em là loại bỏ các giá trị trùng nhau đồng thời sắp xếp lại các phần tử của cột theo thứ tự tăng dần. Em không hiểu sao lại bị báo lỗi ở câu lệnh Redim Preserve ...

Cảm ơn mọi người !
Hiểu nôm na là thế này bạn:

Code của bạn
Mã:
ReDim Preserve mang(1 To k, 1 To 1)
Tức là tăng số "Hàng"

Nhưng

Redim Preserve chỉ cho phép tăng số "Cột"

Gpe nói nhiều về cái này, bạn tìm hiểu thêm nhé
 
Upvote 0
Hiểu nôm na là thế này bạn:

Code của bạn
Mã:
ReDim Preserve mang(1 To k, 1 To 1)
Tức là tăng số "Hàng"

Nhưng

Redim Preserve chỉ cho phép tăng số "Cột"


Gpe nói nhiều về cái này, bạn tìm hiểu thêm nhé
Em đã đổi lại thành Redim theo chiều cột rồi mà vẫn báo lỗi vậy ah
 
Upvote 0
Em sửa như anh nói mà nó lại báo lỗi: Subscript out of range :=\+:=\+

Thì đọc lại í bạn gì cmt ở trên đó, nó chỉ cho Redim Preserve cột cơ mà...--=0--=0--=0
-----------

Nhưng với bài toán của chàng thì làm gì mà phức tạp vậy

1. Viết 1 Dic lọc duy nhất bình thường, dán kết quả xuống sheet
2. Sau đó dùng excel mà Sort từ bé tới lớn là được kết quả như ý...

Đừng si nghĩ chi cho mệt óc nha em!
 
Upvote 0
Nhưng với bài toán của chàng thì làm gì mà phức tạp vậy

1. Viết 1 Dic lọc duy nhất bình thường, dán kết quả xuống sheet
2. Sau đó dùng excel mà Sort từ bé tới lớn là được kết quả như ý...

Đừng si nghĩ chi cho mệt óc nha em!

Vâng anh, tại em đang thử cách này để làm 1 bài toán khác í mà ...
 
Upvote 0
Vâng anh, tại em đang thử cách này để làm 1 bài toán khác í mà ...

Thử không xài "muối" mà xài "mắm" xem sao.
PHP:
Public Sub GPE()
Dim Arr, Tmp, dArr(), I As Long, Rws As Long, K As Long
Arr = Range("A1", Range("A1").End(xlDown)).Value
Rws = UBound(Arr)
ReDim Tmp(Rws)
For I = 1 To UBound(Arr)
    If Arr(I, 1) > Rws Then
        Rws = Arr(I, 1)
        ReDim Preserve Tmp(Rws)
    End If
        Tmp(Arr(I, 1)) = Arr(I, 1)
Next I
ReDim dArr(1 To Rws + 1, 1 To 1)
For I = 0 To Rws
    If Tmp(I) <> "" Then
        K = K + 1
        dArr(K, 1) = Tmp(I)
    End If
Next I
[R2].Resize(K) = dArr
End Sub
 
Upvote 0
Web KT
Back
Top Bottom