Có thể nạp list box mà không dùng vòng lặp? (1 người xem)

Liên hệ QC

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

Tường_Vi

Thành viên tiêu biểu
Tham gia
19/4/10
Bài viết
482
Được thích
121
Nghề nghiệp
Luôn tìm kiếm một vị trí tốt hơn
Có thể nạp list box (nếu thỏa mãn điều kiện) mà không dùng vòng lặp?

Em vừa thừ dùng code nạp danh sách cho Listbox bằng vòng lặp (có tham khảo bài viết của anh Sealand) nhưng với dữ liêu vài trăm dòng thì ok nhưng test thử 5000 dòng thì code chạy rất lâu

Em xin hỏi có cách nào nạp danh sách vào listbox mà không cần dùng vòng lặp không?

Xin cám ơn
 
Lần chỉnh sửa cuối:
Em vừa thừ dùng code nạp danh sách cho Listbox bằng vòng lặp (có tham khảo bài viết của anh Sealand) nhưng với dữ liêu vài trăm dòng thì ok nhưng test thử 5000 dòng thì code chạy rất lâu

Em xin hỏi có cách nào nạp danh sách vào listbox mà không cần dùng vòng lặp không?

Xin cám ơn
Tùy theo nguồn dữ liệu mới biết có dùng vòng lập hay không. Bạn đưa file cụ thể thử xem
Có nhiều cách ví dụ như ListBox1.Lis()= Range("A1:C1000").Value chẳng hạn
 
Upvote 0
Em vừa thừ dùng code nạp danh sách cho Listbox bằng vòng lặp (có tham khảo bài viết của anh Sealand) nhưng với dữ liêu vài trăm dòng thì ok nhưng test thử 5000 dòng thì code chạy rất lâu

Em xin hỏi có cách nào nạp danh sách vào listbox mà không cần dùng vòng lặp không?

Xin cám ơn

Nạp listbox bằng name cũng được bạn, đặt name rồi gán vào thuộc tính RowSource
 
Upvote 0
Theo mình biết có 2 cách không dùng vòng lặp:

1/Dùng thuộc tính RowSource:

Ví dụ: Me.ListBox1.RowSource = Sheet1.Name & "!" & Sheet1.[A2:D10].Address

(Theo mình không nên dùng Name vì đã Code lại còn lỉnh kỉnh 1 đống Name)

2/Dùng phương thức List():

Ví dụ:

Dim Tm
Tm = Sheet1.[B2:D10]
Me.ListBox1.List() = Tm
 
Upvote 0
Em vừa thừ dùng code nạp danh sách cho Listbox bằng vòng lặp (có tham khảo bài viết của anh Sealand) nhưng với dữ liêu vài trăm dòng thì ok nhưng test thử 5000 dòng thì code chạy rất lâu

Em xin hỏi có cách nào nạp danh sách vào listbox mà không cần dùng vòng lặp không?

Xin cám ơn

Nạp RowSource hay List cho ListBox có rất nhiều cách, hoặc là dùng Name để nạp cho Rowsource hoặc dùng mảng để nạp cho List. Tuy nhiên, nếu ListBox không cần thiết phải nạp toàn bộ số cột mà mảng đang có thì tốt nhất là dùng vòng lặp để duyệt cho mảng rồi gán lên List của ListBox. Tôi thiết nghĩ trong trường hợp dùng vòng lặp này không có vấn đề về tốc độ đâu!

Với Form dưới đây, tốc độ chưa đến 1.5 giây cho 60,001 dòng, 8 cột (nạp từ 17 cột trong sheet)!

Mã:
Private Sub UserForm_Initialize()
[COLOR=#0000cd]    Dim TG As Double
    TG = Timer[/COLOR]
        Dim MyArr, MyArray, iRow As Long, iCol As Long
        MyArr = Sheet1.Range("A1:Q60001").Value
        ReDim MyArray(1 To UBound(MyArr, 1), 1 To 8)
        For iRow = 1 To UBound(MyArr, 1)
            For iCol = 1 To 8
                MyArray(iRow, iCol) = MyArr(iRow, iCol * 2)
            Next
        Next
        ListBox1.ColumnCount = iCol
        ListBox1.List() = MyArray
    [COLOR=#0000cd]MsgBox " With da ta: " & UBound(MyArray, 1) & " records." & Chr(10) & Chr(10) & _
    "Time for run: " & Timer - TG & " seconds"[/COLOR]
End Sub
Bạn xem File sẽ rõ!
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Theo mình biết có 2 cách không dùng vòng lặp:

1/Dùng thuộc tính RowSource:

Ví dụ: Me.ListBox1.RowSource = Sheet1.Name & "!" & Sheet1.[A2:D10].Address

(Theo mình không nên dùng Name vì đã Code lại còn lỉnh kỉnh 1 đống Name)

2/Dùng phương thức List():

Ví dụ:

Dim Tm
Tm = Sheet1.[B2:D10]
Me.ListBox1.List() = Tm

Em đang tham khảo file của Anh Sealand (file Kê khai hoá đơn GTGT...) và thấy đoạn code này dùng vòng lặp.
Lý do: phải thỏa mãn ký tự trong text box mới cho vào list box

PHP:
Private Sub nap()
  Dim j, i As Long
    ListBox1.Clear
i = 2
j = 0
 Do While Sheet3.Cells(i, 1) <> ""
 If IIf(Me.CheckBox1, InStr(1, Sheet3.Cells(i, 1), TextBox1, 1) = 1, InStr(1, _
 Sheet3.Cells(i, 1), TextBox1, 1) > 0) Then
 With ListBox1
 .AddItem (Sheet3.Cells(i, 1))
.List(j, 1) = Sheet3.Cells(i, 2)
.List(j, 2) = Sheet3.Cells(i, 3)
.List(j, 3) = Sheet3.Cells(i, 4)
.ColumnWidths = "250 pt;70 pt;70 pt"
End With
 j = j + 1
End If
i = i + 1
 Loop
If ListBox1.ListCount > 0 Then ListBox1.ListIndex = 0
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn lưu ý:
-Nếu nạp toàn bộ vùng thì mới áp dụng như việc nạp không dùng vòng lặp như bài trước.
-Nếu chọn lọc thì nạp từng Item thoả mãn đièu kiện hoặc lọc ra mảng mới load lên

Cái list trên bài đó là lọc danh sách theo ký tự gõ vào Textbox nên phải như vậy.
 
Upvote 0
Em đang tham khảo file của Anh Sealand (file Kê khai hoá đơn GTGT...) và thấy đoạn code này dùng vòng lặp.
Lý do: phải thỏa mãn ký tự trong text box mới cho vào list box

PHP:
Private Sub nap()
  Dim j, i As Long
    ListBox1.Clear
i = 2
j = 0
 Do While Sheet3.Cells(i, 1) <> ""
 If IIf(Me.CheckBox1, InStr(1, Sheet3.Cells(i, 1), TextBox1, 1) = 1, InStr(1, _
 Sheet3.Cells(i, 1), TextBox1, 1) > 0) Then
 With ListBox1
 .AddItem (Sheet3.Cells(i, 1))
.List(j, 1) = Sheet3.Cells(i, 2)
.List(j, 2) = Sheet3.Cells(i, 3)
.List(j, 3) = Sheet3.Cells(i, 4)
.ColumnWidths = "250 pt;70 pt;70 pt"
End With
 j = j + 1
End If
i = i + 1
 Loop
If ListBox1.ListCount > 0 Then ListBox1.ListIndex = 0
End Sub
Code này làm việc trực tiếp trên cell nên chậm là phải rồi... Lý ra bạn nên làm theo cách:
- Chuyển toàn bộ dữ liệu sang mảng
- Dùng vòng lập quét mảng
- Xét điều kiện rồi nạp vào 1 mảng tạm khác
- Cuối cùng lấy mảng tạm ấy gán vào ListBox
===> Xem cách làm của minhthien ấy
--------------
Nếu làm không được, hãy cho file lên đây
 
Upvote 0
PHP:
Private Sub UserForm_Initialize()     Dim TG As Double     TG = Timer         Dim MyArr, MyArray, iRow As Long, iCol As Long         MyArr = Sheet1.Range("A1:Q60001").Value         ReDim MyArray(1 To UBound(MyArr, 1), 1 To 8)         For iRow = 1 To UBound(MyArr, 1)             For iCol = 1 To 8                 MyArray(iRow, iCol) = MyArr(iRow, iCol * 2)             Next         Next         ListBox1.ColumnCount = iCol         ListBox1.List() = MyArray     MsgBox " With da ta: " & UBound(MyArray, 1) & " records." & Chr(10) & Chr(10) & _     "Time for run: " & Timer - TG & " seconds" End Sub

Em chưa học mảng. Huynh có thể phác thêm điều kiện nếu thỏa mãn giá trị TextBox (là chữ) thì nạp cho list box được không?

Hy vọng qua ví dụ này em sẽ hiểu hơn về mảng
 
Upvote 0
Mình tặng bạn Hàm lọc mảng theo đúng cơ chế lọc của AutoFilter (Bao gồm 12 dạng lọc)

Mã:
Function Filter2D(ByVal Arr As Variant, _
Dk As String, Id As Integer, MyType As Integer)
'=================== SEALAND - GPE - 2011 =========================
'=== Arr la mang can loc ------ Tham so MyType: 1-Bang,2-khac,  ===
'=== 3-Lon hon, 4-Lon hon va bang, 5-Nho hon, 6-Nho hon va bang ===
'=== 7-Bat dau bang, 8-Khong bat dau bang, 9-Ket thuc bang,     ===
'=== 10-Khong ket thuc bang,11-Co chua, 12-Khong chua           ===
'==================================================================
Dim Tm, Kq(), Ts As Boolean
Dim i, j, n
On Error GoTo suly
Tm = Arr
For i = 1 To UBound(Tm, 1)
If TestOk(UCase(Tm(i, Id)), UCase(Dk), MyType) Then
j = j + 1
For n = 1 To UBound(Tm, 2)
Tm(j, n) = Tm(i, n)
Next n
End If
Next i
suly:
If j > 0 Then
ReDim Kq(1 To j, 1 To UBound(Tm, 2))
For i = 1 To UBound(Kq, 1)
For j = 1 To UBound(Kq, 2)
Kq(i, j) = Tm(i, j)
Next
Next
End If
Filter2D = Kq
End Function
'----------------------------------------------
Function TestOk(ByVal Str1 As String, ByVal _
Str2 As String, K As Integer) As Boolean
Select Case K
Case Is = 1
TestOk = Str1 Like Str2
Case Is = 2
TestOk = Not Str1 Like Str2
Case Is = 3
TestOk = Str1 > Str2
Case Is = 4
TestOk = Str1 >= Str2
Case Is = 5
TestOk = Str1 < Str2
Case Is = 6
TestOk = Str1 <= Str2
Case Is = 7
TestOk = Str1 Like Str2 & "*"
Case Is = 8
TestOk = Not Str1 Like Str2 & "*"
Case Is = 9
TestOk = Str1 Like "*" & Str2
Case Is = 10
TestOk = Not Str1 Like "*" & Str2
Case Is = 11
TestOk = Str1 Like "*" & Str2 & "*"
Case Is = 12
TestOk = Not Str1 Like "*" & Str2 & "*"
Case Else
TestOk = False
End Select
End Function

Hàm chính là hàm Filter2D còn hàm TestOK là phụ trợ của hàm chính.

Như vậy từ mảng, lọc mảng, load mảng nhất định tốc độ tốt.
 
Upvote 0
Em chưa hiểu Id (as interger ) là gì?
Anh Sealand có thể upload một file excel để em hiểu hàm trên được không?
 
Upvote 0
Id là chỉ định lọc theo cột nào.
Đây là 1 ví dụ mình đã áp dụng trong thực tế và thấy khá nhanh và không lỗi như Filter

Tại sheet Lọc mình có đoạn code điều khiển lọc:

Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Tm As Variant, cot As Integer, Kieu As Integer, Dk As String
On Error GoTo Thoat
If Not Intersect(Target, Sheet2.[A2:C2]) Is Nothing Then
cot = Sheet2.[B2].Value
Kieu = Sheet2.[A2].Value
Dk = Sheet2.[C2].Value
Sheet2.[A5:K1000].ClearContents
Tm = Filter2D(Sheet1.Range(Sheet1.[A2], Sheet1.[A65536].End(3)).Resize(, 12).Value, Dk, cot, Kieu)
Sheet2.[A5].Resize(UBound(Tm, 1), 12).Value = Tm
End If
Thoat:
End Sub

Sheet Loc là kết quả của hàm này.
 

File đính kèm

Upvote 0
Với hàm Filter 2D trên, làm cách nào em đưa nó vào sự kiện khi Textbox thay đổi để nạp dach sách đã lọc vào Listbox?

Em loay hoay cả buổi chiều nay không được
 
Upvote 0
Vẫn file cũ bạn tham khảo nha, tranh thủ nên chưa chỉnh cho đẹp được, thông cảm nha
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Với hàm Filter 2D trên, làm cách nào em đưa nó vào sự kiện khi Textbox thay đổi để nạp dach sách đã lọc vào Listbox?

Em loay hoay cả buổi chiều nay không được
Tặng bạn cái này xài thử..
Nó có thể lọc bất kỳ mảng nào, Base1 hay Base0 gì cũng chơi tuốt (tức có thể lọc mảng có nguồn từ Range hoặc thậm chí có nguồn từ chính cái ListBox ta đang dùng --> Nói chung là bất kỳ mảng nào, miễn là mảng 2 chiều)
- Khi bạn mở form, bạn gõ gì đó vào TextBox nghĩa là lọc tại cột 1 theo điều kiện lọc của TextBox
- Muốn lọc ở cột khác, chỉ cần bấm vào tiêu đề ListBox (tại cột cần lọc) rồi gõ vào TextBox từ khóa
Ví dụ:
- Bạn gõ chữ A* nghĩa là lọc tất cả các dòng có ký tự bắt đầu bằng A
- Bạn gõ *A nghĩa là lọc tất cả các dòng có ký tự kết thúc là A
- Bạn gõ *A* nghĩa là lọc tất cả các dòng có ký tự ở giửa là A
- Bạn gõ !A* nghĩa là lọc tất cả các dòng có ký tự bắt đầu <> A
- Bạn gõ >10 nghĩa là lọc tất cả các dòng có giá trị >10
- Bạn gõ >=Date(2011, 4, 15) nghĩa là lọc tất cả các dòng có giá trị ngày tháng >= ngày 15/4/2011
vân vân và vân vân... còn nhiều chiêu khác nữa chờ bạn tự khám phá
----------------
Tham khảo thêm tại đây:
http://www.giaiphapexcel.com/forum/showthread.php?53566-Thắc-mắc-về-hàm-UDF-Filter2DArray/page3
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Em làm được rồi
Cám ơn Anh SEALAND, NDU rất nhiều
 
Upvote 0
Cho em hỏi, liệu mình có thể dùng phương thức Find để nạp dữ liệu vào ListBox được không (tìm theo một cột được chỉ định nào đó)? và so với sử dụng vòng lặp liệu nó có nhanh hơn được không (xét trên một kiểu là tìm trên cell hoặc cùng tìm trên mảng)
 
Upvote 0
Cho em hỏi, liệu mình có thể dùng phương thức Find để nạp dữ liệu vào ListBox được không (tìm theo một cột được chỉ định nào đó)? và so với sử dụng vòng lặp liệu nó có nhanh hơn được không (xét trên một kiểu là tìm trên cell hoặc cùng tìm trên mảng)
Dùng phương thức Find để tìm và nạp vào ListBox đương nhiên được nhưng chỉ thích hợp với dữ liệu nhỏ... Nó chắc chắn sẽ chậm hơn so với xử lý mảng
 
Upvote 0

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

Back
Top Bottom