Giúp sửa code tìm kiếm tên khách hàng để code chạy nhanh hơn

Liên hệ QC

NHG

Thành viên hoạt động
Tham gia
15/1/07
Bài viết
147
Được thích
125
Mình có một bảng chọn khách hàng nhưng với dữ liệu khoảng 6000 dòng thì nó chạy quá chậm, các bạn xem rôi cải tiến giúp mình cho nó chạy nhanh hơn nhé
 

File đính kèm

  • Chon khach hang.rar
    35.5 KB · Đọc: 230
NHG đã viết:
Mình có một bảng chọn khách hàng nhưng với dữ liệu khoảng 6000 dòng thì nó chạy quá chậm, các bạn xem rôi cải tiến giúp mình cho nó chạy nhanh hơn nhé
Hình như dùng VBA kết hợp công thức như thế là nhanh nhất rồi. Nên chuyển qua tìm theo mã chắc nhanh hơn 1 chút.
 
Upvote 0
File của mình hoàn toàn bằng VBA đấy chứ, mình cũng đã làm theo kiểu VBA kết hợp với công thức thì File chạy rất nhanh, nhưng nó có một hạn chế là phải thêm cột phụ, mà cái này mình lại làm cho người khác dùng, họ không biết mà xóa béng của mình cái cột phụ đi thế là xong, khỏi tìm kiếm gì hết. Nên mình nghĩ nếu cải tiến đc tốc độ thì mình dùng hoàn toàn bằng VBA thì tốt hơn
 
Upvote 0
NHG đã viết:
Mình có một bảng chọn khách hàng nhưng với dữ liệu khoảng 6000 dòng thì nó chạy quá chậm, các bạn xem rôi cải tiến giúp mình cho nó chạy nhanh hơn nhé

Mình chỉ có ý kiến xíu (có thể chẳng liên quan đến câu hỏi) :
  1. Dùng Instr là đúng rồi, tuy nhiên thay vì Listbox, ta nên dùng Listview thì đẹp hơn nhiều
  2. Không nên dùng sự kiện TB_change mà nên dùng AfterUpdate, vì cứ thay đổi là . . . chạy trong khi nhập chưa xong
  3. Nên có 2 cột là MÃ và TÊN, từ đó sẽ có 2 hướng là tìm theo MÃ và theo TÊN. Vừa đẹp lại vừa chuyên nghiệp
  4. Sao lại cứ phải kết thúc từ hàng 2000 ?? Nên dùng Sheet3.Range("B65000").End(xlUp).Row để xác định dòng cuối cùng
  5. Danh mục không nên có cột STT, chẳng để làm gì mà lại gây nặng máy
  6. Sử dụng hàm TRIM trước khi tìm kiếm vừa có lợi lại vừa chẳng lợi, không có nó thì tốt hơn.
  7. ...................................
Mấy lời góp ý!
Thân!
 
Upvote 0
Mr Okebab đã viết:
nh chỉ có ý kiến xíu (có thể chẳng liên quan đến câu hỏi) :
  1. Dùng Instr là đúng rồi, tuy nhiên thay vì Listbox, ta nên dùng Listview thì đẹp hơn nhiều
  2. Không nên dùng sự kiện TB_change mà nên dùng AfterUpdate, vì cứ thay đổi là . . . chạy trong khi nhập chưa xong
  3. Nên có 2 cột là MÃ và TÊN, từ đó sẽ có 2 hướng là tìm theo MÃ và theo TÊN. Vừa đẹp lại vừa chuyên nghiệp
  4. Sao lại cứ phải kết thúc từ hàng 2000 ?? Nên dùng Sheet3.Range("B65000").End(xlUp).Row để xác định dòng cuối cùng
  5. Danh mục không nên có cột STT, chẳng để làm gì mà lại gây nặng máy
  6. Sử dụng hàm TRIM trước khi tìm kiếm vừa có lợi lại vừa chẳng lợi, không có nó thì tốt hơn.
  7. ...................................
Mấy lời góp ý!
Thân!
Góp ý thêm với NHG và Mr Okebab

Dùng Instr để so sánh chuỗi trong For Next buộc For Net phải phải duyệt toàn bộ cac dòng dù tìm không có. Nên thay bằng Find trong Do ... Loop, nó sẽ chỉ ngay đến ô có chuỗi cần tìm nếu có. Tìm không có thì kết thúc. Nếu có 3 ô có chuỗi cần tìm, nó chỉ lặp 3 lần.

Sự kiện TB_change làm chậm quá trình nhập, nhưng có cái ưu là người nhập không nhớ chính xác vẫn có thể tìm được nhờ xem vào list gõ tiếp ký tự kế. Còn AfterUpdate mà không nhớ chính xác thì chịu thua vì nó không hiện lên dòng nào gợi nhớ lại tên.

Không cần tách 2 ô MÃ, TÊN. TextBox MÃTÊN cho phép nhập mã hoặc tên (nhớ cái nào nhập cái đó), viết code cho nó tìm cả 2 cột mã và tên.
 
Upvote 0
phamduylong đã viết:
Góp ý thêm với NHG và Mr Okebab

Dùng Instr để so sánh chuỗi trong For Next buộc For Net phải phải duyệt toàn bộ cac dòng dù tìm không có. Nên thay bằng Find trong Do ... Loop, nó sẽ chỉ ngay đến ô có chuỗi cần tìm nếu có. Tìm không có thì kết thúc. Nếu có 3 ô có chuỗi cần tìm, nó chỉ lặp 3 lần.
Xin cảm ơn bác về sự chia sẻ này, để em thử xem sao. Tuy nhiên nếu có thể thì bác thử cho mấy dòng code VD được không ạ !!

phamduylong đã viết:
Sự kiện TB_change làm chậm quá trình nhập, nhưng có cái ưu là người nhập không nhớ chính xác vẫn có thể tìm được nhờ xem vào list gõ tiếp ký tự kế. Còn AfterUpdate mà không nhớ chính xác thì chịu thua vì nó không hiện lên dòng nào gợi nhớ lại tên.

Không nên dùng TextBox_Change vì sẽ làm chậm quá trình tìm kiếm
Việc dùng TextBox_AfterUpdate không cần phải chính xác, nó giống như TextBox_Change thôi, chỉ có điều khác là nó ra lệnh tìm kiếm khi ta chuyển Tab sang Ojb khác.

VD : Khi ta muốn tìm kiếm phamduylong, tuy nhiên ta không nhớ chính xác, chỉ nhớ chữ "duy", vậy ta nhập "duy" vào và Enter, thế là tất cả các khách hàng có ký tự "duy" đều hiện ra.

Nhưng nếu ta dùng TextBox_Change thì cứ mỗi lần ta nhập thêm 1 ký tự là nó lại tìm kiếm, ta muốn nhập chữ "duy" xong thì mới tìm kiếm nhưng lại không được.

phamduylong đã viết:
Không cần tách 2 ô MÃ, TÊN. TextBox MÃTÊN cho phép nhập mã hoặc tên (nhớ cái nào nhập cái đó), viết code cho nó tìm cả 2 cột mã và tên.
Không nên để cho nó tìm cả cột mã và tên, như vậy sẽ lâu hơn (em chưa hình dung hết cái lệnh Find của bác), ta có thể tạo ra 2 Textbox để làm việc này hoặc tạo 1 textbox và 1 Group Option Button gồm 2 nút để tìm theo mã hoặc theo tên.

Cảm ơn bác nhiều!
Thân!
 
Upvote 0
Mr Okebab đã viết:
Xin cảm ơn bác về sự chia sẻ này, để em thử xem sao. Tuy nhiên nếu có thể thì bác thử cho mấy dòng code VD được không ạ !!
Bắt Find tìm cả 2 cột B,C. Tìm thấy đưa vào list. Nhập ký tự đầu tìm rất nhiều, từ ký tự 2, 3 số dòng trong list giảm đáng kể. Có thể thấy được tên cty hoặc mã muốn tìm.

Mã:
Private Sub TB_change()
Dim rng As String, rng1 As String, rng2 As String, strFind As String
Dim r As Integer, i As Integer
Sheets("DM.KH").Select
Chon.Default = True
Thoat.Cancel = True
LB.Clear
strFind = LCase(Trim(TB.Text))
rng1 = "$B$5"
rng = ""
On Error Resume Next
i = 0
Do
  rng2 = Columns("B:C").Find(What:=strFind, After:=Range(rng1)).Address
  If Err.Number > 0 Or rng2 = rng Then
    Exit Do
  End If
  rng1 = rng2
  If rng = "" Then rng = rng2
  If r <> Range(rng2).Row Then
    r = Range(rng2).Row
    LB.AddItem Cells(r, 2)
    LB.List(i, 1) = Cells(r, 3)
    i = i + 1
  End If
Loop
End Sub
 

File đính kèm

  • Chon khach hang_Find.zip
    65.7 KB · Đọc: 408
Upvote 0
phamduylong đã viết:
Bắt Find tìm cả 2 cột B,C. Tìm thấy đưa vào list. Nhập ký tự đầu tìm rất nhiều, từ ký tự 2, 3 số dòng trong list giảm đáng kể. Có thể thấy được tên cty hoặc mã muốn tìm.

Mã:
Private Sub TB_change()
Dim rng As String, rng1 As String, rng2 As String, strFind As String
Dim r As Integer, i As Integer
Sheets("DM.KH").Select
Chon.Default = True
Thoat.Cancel = True
LB.Clear
strFind = LCase(Trim(TB.Text))
rng1 = "$B$5"
rng = ""
On Error Resume Next
i = 0
Do
  rng2 = Columns("B:C").Find(What:=strFind, After:=Range(rng1)).Address
  If Err.Number > 0 Or rng2 = rng Then
    Exit Do
  End If
  rng1 = rng2
  If rng = "" Then rng = rng2
  If r <> Range(rng2).Row Then
    r = Range(rng2).Row
    LB.AddItem Cells(r, 2)
    LB.List(i, 1) = Cells(r, 3)
    i = i + 1
  End If
Loop
End Sub

Vâng, quả thực là tuyệt vời!!. Cảm ơn bác nhiều!

Lại học thêm được 1 chiêu nữa rồi!

Thân!
 
Upvote 0
Cũng với bài toán như trên, nhưng trong lần này các bạn nghiên cứu trong trường hợp File dùng Font TCVN3 nhé, mình nhận thấy hầu hết các ký tự đều tìm đc nhưng riêng tên khách hàng nào có chứa vần “ả” thì sẽ không tìm đc (các bạn thử gõ tên Hải vào texbox mà xem, trong Listbox sẽ không hiện ra khách hàng đấy đâu), mới lại texbox không phân biệt đc “đ”“Đ”
 

File đính kèm

  • Chon khach hang_Find_TCVN3.rar
    33.6 KB · Đọc: 106
Upvote 0
NHG đã viết:
Cũng với bài toán như trên, nhưng trong lần này các bạn nghiên cứu trong trường hợp File dùng Font TCVN3 nhé, mình nhận thấy hầu hết các ký tự đều tìm đc nhưng riêng tên khách hàng nào có chứa vần “ả” thì sẽ không tìm đc (các bạn thử gõ tên Hải vào texbox mà xem, trong Listbox sẽ không hiện ra khách hàng đấy đâu), mới lại texbox không phân biệt đc “đ”“Đ”
Đúng là khổ vì bảng mã. Từ 2005 nhà nước đã quy định font chuẩn nhưng không biết bao giờ mới chấm dứt nhiều bảng mã. Trường hợp này phải ngâm cứu tìm giải pháp.
Có thể phải giải quyết bằng cách: vẫn để Text Box là font Tahoma để đánh tiếng Việt Unicode, nhưng khi tìm phải chuyển chuỗi sang TCVN3 tìm.
Các bạn viết theo hướng này thử xem
 
Upvote 0
Không đc, mình muốn dùng bộ gõ TCVN3 cơ, vì tất cả các File + PM kế toán của mình đều dùng bộ gõ đấy, các bạn thử nghiên cứu xem có cách nào khác không?
 
Upvote 0
Đúng là dùng công cụ Find nhanh hơn rất nhiều, tuy nhiên với khoảng 60.000 dòng mà ta dùng Textbox_Change thì thật là khổ sở.
Vì vậy vẫn nên dùng Textbox_AfterUpdate bác ạ
Bác thử xem File thì biết!

Không đc, mình muốn dùng bộ gõ TCVN3 cơ, vì tất cả các File + PM kế toán của mình đều dùng bộ gõ đấy, các bạn thử nghiên cứu xem có cách nào khác không?

Bạn nên convert mã cần tìm tiếm (textbox.Value) -->> TCVN3 trước khi tìm kiếm. Trên GPE có rất nhiều code về cái này đấy.

Thân!
 

File đính kèm

  • Chon khach hang_Find1.7z
    108 KB · Đọc: 199
Upvote 0
Texbox cũng là TCVN3, Listbox cũng là TCVN3 cơ mà các bạn, có liên quan gì đến Unicode đâu
 
Upvote 0
NHG đã viết:
Texbox cũng là TCVN3, Listbox cũng là TCVN3 cơ mà các bạn, có liên quan gì đến Unicode đâu
Nếu vậy bạn không nên dùng Ucase nữa, vì Font TCVN là loại Font 1 byte, vì vậy dùng hàm này sẽ không chính xác.
Ucase("ả") <> "Ả"
Có 2 cách :
- Tìm chính xác (phân biệt hoa và thường) : Bỏ hàm này đi sẽ tìm được chính xác ngay

- Tìm không phân biệt hoa và thường : Dùng hàm Ucase, tuy nhiên cần convert giá trị tìm kiếm và chuỗi thông tin (tên, mã khách hàng) sang Unicode trước khi so sánh.

Thân!
 
Upvote 0
NHG đã viết:
Texbox cũng là TCVN3, Listbox cũng là TCVN3 cơ mà các bạn, có liên quan gì đến Unicode đâu
Đúng là không liên quan, nhưng Unicode hiển thị đúng, còn TCVN3 có một số ký tự không hiện được. Ví dụ được >đợc. Không biết mìinh gõ đúng hay sai !
 
Upvote 0
Bài viết bổ ích thật, cảm ơn các bạn, theo mình nếu ngại vấn đề Textbox_Change hay Textbox_AfterUpdate , ta có thể đưa thêm tùy chọn ở bảng chọn dữ liệu là update luôn khi thay đổi ở textbox hay ko?
 
Upvote 0
Cảm ơn file rất hay của các anh chị!
cũng như ý trên em muốn trong list box nó hiện thêm hai cột nữa được không ví dụ như ngày tạo, mã số thuế và người liên hệ, mong các anh chị chỉ giúp
 

File đính kèm

  • Chon khach hang_Find.rar
    39.8 KB · Đọc: 54
Upvote 0
1/Bạn thêm 1 sub sau

Mã:
Private Sub UserForm_Initialize()
LB.ColumnCount = 4
LB.ColumnWidths = "80 pt;229.95 pt;120 pt;70 pt"
End Sub
2/Bạn sửa code sau:

Mã:
Private Sub TB_change()
...........................................
  If r <> Range(rng2).Row Then
    r = Range(rng2).Row
    LB.AddItem Cells(r, 2)
    LB.List(i, 1) = Cells(r, 3)
    LB.List(i, 2) = Cells(r, 4)
    LB.List(i, 3) = Cells(r, 5)
  ........................................
End Sub

Tôi chả hiểu bạn lấy ngày tạo mã ở đâu nên chỉ thêm 2 cột, bạn theo đó điều chỉnh nha
 
Upvote 0
Web KT
Back
Top Bottom