nguyenmanhnam
Thành viên tiêu biểu

- Tham gia
- 24/7/10
- Bài viết
- 434
- Được thích
- 266
Nhờ các anh, chị; các thày giúp em bài toán lọc duy nhất theo điều kiện tại file đính kèm. Xin trân trọng cảm ơn!
Thêm 1 cách nữa để tham khảo nhé, k được hay lắm, hiiiiiiiiiiiiNhờ các anh, chị; các thày giúp em bài toán lọc duy nhất theo điều kiện tại file đính kèm. Xin trân trọng cảm ơn!
Sub HMT()
Dim i As Long, k As Long
Dim sArr(), dArr()
Dim DIc As Object
Set DIc = CreateObject("Scripting.dictionary")
sArr() = Range("List").Value
ReDim dArr(1 To UBound(sArr), 1 To 1)
For i = 1 To UBound(sArr)
If Not DIc.exists(sArr(i, 1)) Then
DIc.Add sArr(i, 1), k
k = k + 1
dArr(k, 1) = sArr(i, 1)
End If
Next
[E3:E100].ClearContents
If k Then [E3].Resize(k) = dArr
Set DIc = Nothing
End Sub
Sub loc()
Dim c
[E3:E1000].Clear
c = Switch([E2] = "XN1", 1, [E2] = "XN2", 2, [E2] = "XN3", 3)
Range(Cells(2, c), Cells(65536, c).End(3)).AdvancedFilter 2, , [E2], 1
End Sub
Bạn xem thử file đính kèm có đúng ý đồ của bạn không -> nếu đúng ta tiếp tục edit![]()
Bạn xem thử file đính kèm có đúng ý đồ của bạn không -> nếu đúng ta tiếp tục edit![]()
Sub Macro1()
Dim valXN As String
[E3:E1000].Clear
valXN = [E2].Value
Select Case valXN
Case Is = "XN1"
Range("A3", [A65536].End(3)) _
.AdvancedFilter Action:=xlFilterCopy, CopyToRange:=Range("E3"), Unique:=True
Case Is = "XN2"
Range("B3", [B65536].End(3)) _
.AdvancedFilter Action:=xlFilterCopy, CopyToRange:=Range("E3"), Unique:=True
Case Is = "XN3"
Range("C3", [C65536].End(3)) _
.AdvancedFilter Action:=xlFilterCopy, CopyToRange:=Range("E3"), Unique:=True
End Select
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next
If Not Intersect(Target, [E2]) Is Nothing Then Call Module1.Macro1
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rng As Range
Dim lC As Long
If Target.Address = "$E$2" Then
Set rng = Range("A2:C1000")
Select Case Target.Value
Case Is = "XN1": lC = 0
Case Is = "XN2": lC = 1
Case Is = "XN3": lC = 2
End Select
rng.Resize(, 1).Offset(, lC).AdvancedFilter 2, , Target, True
End If
End Sub
Dám cá dù viết bất cứ hàm gì cũng không thể nhanh bằng Advanced Filter <---- TIN KHÔNG?Nhưng với bài này, tôi sẽ không dùng phương thức, mà tôi sẽ tặng hàm lọc duy nhất cho tác giả!
Switch statement thay cho Case và IF trông ngắn hơn nhỉ^^, cái này thú vị à nha, hum nay em mới biết cái thằng Switch này đó, he he he.Thêm cách này nữa xem sao
PHP:Sub loc() Dim c [E3:E1000].Clear c = Switch([E2] = "XN1", 1, [E2] = "XN2", 2, [E2] = "XN3", 3) Range(Cells(2, c), Cells(65536, c).End(3)).AdvancedFilter 2, , [E2], 1 End Sub
Dám cá dù viết bất cứ hàm gì cũng không thể nhanh bằng Advanced Filter <---- TIN KHÔNG?
Set FindRange = Range("A2:C2").Find(Target, LookIn:=xlValues, LookAt:=xlWhole)
Select Case Target.Value
Case [COLOR=#ff0000][B]Is =[/B][/COLOR] "XN1": lC = 0
Case [COLOR=#ff0000][B]Is =[/B][/COLOR] "XN2": lC = 1
Case [COLOR=#ff0000][B]Is =[/B][/COLOR] "XN3": lC = 2
End Select
Select Case Target.Value
Case "XN1": lC = 0
Case "XN2": lC = 1
Case "XN3": lC = 2
End Select
Cái thuật toán quan trọng là cái này nè Thầy:
Mã:Set FindRange = Range("A2:C2").Find(Target, LookIn:=xlValues, LookAt:=xlWhole)
Chứ ở đó mà Select Case cho hàng trăm cột chắc gì làm nổi!
Rồi từ đó, muốn làm gì thì làm! Nhiều người đã dùng Advanced Filter rồi, em không dùng em chỉ dùng Hàm cho có nhiều lựa chọn thôi.
Spam tẹo :Code của bạn là:
Select Case chủ yếu tìm chỉ số cột, sau đó ta định vị vùng dữ liệu dựa vào chỉ số cột đã tìm được ---> Gọn gàng hơn chăng?Mã:Sub Macro1() Dim valXN As String ....... Nhận xét: Câu lệnh Select Case chưa đẹp lắm Tôi thì làm vầy: [code] Private Sub Worksheet_Change(ByVal Target As Range) Dim rng As Range Dim lC As Long If Target.Address = "$E$2" Then Set rng = Range("A2:C1000") Select Case Target.Value Case Is = "XN1": lC = 0 Case Is = "XN2": lC = 1 Case Is = "XN3": lC = 2 End Select rng.Resize(, 1).Offset(, lC).AdvancedFilter 2, , Target, True End If End Sub
Ngoài ra, với Advanced Filter cũng chả cần End(xlUp) hay End(xlDown) gì ráo, cứ cho vùng dữ liệu dư 1 chút, đằng nào thì đúng điều kiện nó mới lọc
------------------------
Dám cá dù viết bất cứ hàm gì cũng không thể nhanh bằng Advanced Filter <---- TIN KHÔNG?
Em thấy FIND hay Select Case đều hay mà, nói chung với mấy đứa đang tập tành như em thì cái gì cũng khoái, biết càng nhiều càng ít, cảm ơn anh Nghĩa và sư phụ ndu, cho em hoàn thiện và sửa đổi cái code trên cho đẹp nhé, ^^Tôi đâu có nói đến vụ Select Case hay Find (cái đó tùy trường hợp mà dùng)
Quan trọng là thằng nào lọc nhanh hơn thôi!
Sub HMT()
Dim i As Long, k As Long
Dim sArr(), dArr()
Dim DIc As Object
Dim startCell As Range
Set DIc = CreateObject("Scripting.dictionary")
Set startCell = Range("A2:C2").Find([E2], LookIn:=xlValues, LookAt:=xlWhole) '''em ngu nhat cho nay...
sArr() = startCell.Offset(1).Resize(1000).Value
ReDim dArr(1 To UBound(sArr), 1 To 1)
For i = 1 To UBound(sArr)
If Not DIc.exists(sArr(i, 1)) Then
DIc.Add sArr(i, 1), k
k = k + 1
dArr(k, 1) = sArr(i, 1)
End If
Next
[E3:E1000].ClearContents
If k Then [E3].Resize(k) = dArr
Set DIc = Nothing
End Sub
Tôi đâu có nói đến vụ Select Case hay Find (cái đó tùy trường hợp mà dùng)
Quan trọng là thằng nào lọc nhanh hơn thôi!
Chẳng hiểu sao bài này đơn giản mà mọi người chơi đao to búa lớn khiếp quá
Vầy cũng lọc được mà
PHP:Sub loc2() [E3:E1000].Clear [A2:C10000].AdvancedFilter 2, [E2:E3], [E2], 1 End Sub
Trời ơi, đồng chí này không hiểu ý mình gì cả:Thầy thấy rồi đó, nếu em làm AdvancedFilter, thì chỉ như vầy thôi:
[GPECODE=vb]Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$E$2" Then
Dim FindRange As Range
Set FindRange = Range("A2:C2").Find(Target, LookIn:=xlValues, LookAt:=xlWhole)
If Not FindRange Is Nothing Then
Range("E3:E65536").ClearContents
Range(FindRange.Offset(1), FindRange.End(xlDown)).AdvancedFilter 2, , Target.Offset(1), True
End If
Set FindRange = Nothing
End If
End Sub
[/GPECODE]
Nhưng em muốn nhiều lựa chọn cho bạn ấy dùng, biết đâu bạn ấy không muốn dùng trên sheet, mà dùng trên form để làm nguồn cho combobox hay listbox gì đó thì lại phải tốn thêm 1 cột trong sheet nữa để nạp lên thì sao.
Gọn hơn chưa chắc đã nhanh hơn, vì Hải phải tốn công Clear dữ liệu (code đầu tiên tôi dùng AdF chẳng có Clear gì cả)Chẳng hiểu sao bài này đơn giản mà mọi người chơi đao to búa lớn khiếp quá
Vầy cũng lọc được mà
PHP:Sub loc2() [E3:E1000].Clear [A2:C10000].AdvancedFilter 2, [E2:E3], [E2], 1 End Sub
Trời ơi, đồng chí này không hiểu ý mình gì cả:
- Vấn đề không nằm ở chổ code ngắn hay dài
- Vấn đề không phải nằm ở cách viết code
- Mình chỉ muốn nói rằng: Advanced Filter (là công cụ có sẵn) luôn tỏ ra ưu việt hơn so với việc ta viết 1 hàm tự tạo ---> Chỉ vậy thôi! Còn như cùng 1 giải thuật, ai thích viết sao thì tùy ý, tôi đâu có bắt bẻ vụ này (chỉ là sửa cái Select Case của người ta viết sẵn cho gọn hơn)
------------------------
Gọn hơn chưa chắc đã nhanh hơn, vì Hải phải tốn công Clear dữ liệu (code đầu tiên tôi dùng AdF chẳng có Clear gì cả)
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rng As Range
Dim lC As Long
If Target.Address = "$E$2" Then
Set rng = Range("A2:C65536")
Select Case Target.Value
Case Is = "XN1": lC = 0
Case Is = "XN2": lC = 1
Case Is = "XN3": lC = 2
End Select
[COLOR=#ff0000][B]rng.Resize(, 1).Offset(, lC).AdvancedFilter 2, , Target, True[/B][/COLOR]
End If
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$E$2" Then
Dim FindRange As Range
Set FindRange = Range("A2:C2").Find(Target, LookIn:=xlValues, LookAt:=xlWhole)
If Not FindRange Is Nothing Then
Range("E3:E65536").ClearContents
Dim UniqueArr As Variant
[COLOR=#ff0000][B]UniqueArr = NewUnique(Range(FindRange(2), FindRange(65535)))[/B][/COLOR]
Target.Offset(1).Resize(UBound(UniqueArr)) = UniqueArr
End If
Set FindRange = Nothing
End If
End Sub
- Mình chỉ muốn nói rằng: Advanced Filter (là công cụ có sẵn) luôn tỏ ra ưu việt hơn so với việc ta viết 1 hàm tự tạo
Em bắt đầu hứng thú với cái màu đỏ rồi đây. Nếu cá về thời gian cũng như tính chính xác thì xin mời với file này!
Giả sử số liệu là một series, nhưng vì lý do nào đó lại có vài trường hợp bị trùng, thế thì phải lọc không trùng!
Với dữ liệu là 65536 dòng, hãy thử với cột B tức điều kiện là XN2 với code của Thầy hay bất cứ của ai lọc bằng Advanced Filter
Kết quả đúng sẽ là không trùng và lọc đến 65517 dòng!
Private Sub Worksheet_Change(ByVal Target As Range) 'Bo so 1 o Change1 de thu.
Dim rng As Range
Dim lC As Long
Dim t As Double
If Target.Address = "$E$2" Then
t = Timer
Set rng = Range("A3:A65536")
Select Case Target.Value
Case Is = "XN1": lC = 0
Case Is = "XN2": lC = 1
Case Is = "XN3": lC = 2
End Select
Set rng = rng.Offset(, lC)
With Target.Offset(1).Resize(rng.Rows.Count)
.Value = rng.Value
.RemoveDuplicates 1, xlNo
End With
MsgBox Format(Timer - t, "0.000")
End If
End Sub
Mình nghĩ với chiêu RemoveDuplicates thì có lẽ vô địch rồi, không cần bàn cãi gì ráo.Cũng nhanh đấy nhưng mà chưa có nhanh hơn công cụ Excel đâu
Tôi dùng con dao bén hơn chút:
Thi đấu với điều kiện lọc ="XN2", code tôi nhanh hơn của Nghĩa 3 lầnMã:Private Sub Worksheet_Change(ByVal Target As Range) 'Bo so 1 o Change1 de thu. Dim rng As Range Dim lC As Long Dim t As Double If Target.Address = "$E$2" Then t = Timer Set rng = Range("A3:A65536") Select Case Target.Value Case Is = "XN1": lC = 0 Case Is = "XN2": lC = 1 Case Is = "XN3": lC = 2 End Select Set rng = rng.Offset(, lC) With Target.Offset(1).Resize(rng.Rows.Count) .Value = rng.Value .RemoveDuplicates 1, xlNo End With MsgBox Format(Timer - t, "0.000") End If End Sub
Ẹc... Ẹc...
---------------
Tuy nhiên, như thế cũng chưa có sướng, làm vầy cho nó sung:
- Hãy SaveAs file thành xlsm rồi copy dữ liệu ra 400,000 dòng, xong thử code nhé
- Riêng cột XN2, hãy chọn cell B3 rồi fill xuống "mút chỉ" đến cuối ---> Mục đích không cho em nào trùng
- Giờ dùng code lọc theo điều kiện "XN2"
Mình nghĩ với chiêu RemoveDuplicates thì có lẽ vô địch rồi, không cần bàn cãi gì ráo.
SELECT DISTINCT FieldName FROM [DataBase]
Cũng nhanh đấy nhưng mà chưa có nhanh hơn công cụ Excel đâu
Tôi dùng con dao bén hơn chút:
Thi đấu với điều kiện lọc ="XN2", code tôi nhanh hơn của Nghĩa 3 lầnMã:Private Sub Worksheet_Change(ByVal Target As Range) 'Bo so 1 o Change1 de thu. Dim rng As Range Dim lC As Long Dim t As Double If Target.Address = "$E$2" Then t = Timer Set rng = Range("A3:A65536") Select Case Target.Value Case Is = "XN1": lC = 0 Case Is = "XN2": lC = 1 Case Is = "XN3": lC = 2 End Select Set rng = rng.Offset(, lC) With Target.Offset(1).Resize(rng.Rows.Count) .Value = rng.Value .RemoveDuplicates 1, xlNo End With MsgBox Format(Timer - t, "0.000") End If End Sub
Ẹc... Ẹc...
---------------
Tuy nhiên, như thế cũng chưa có sướng, làm vầy cho nó sung:
- Hãy SaveAs file thành xlsm rồi copy dữ liệu ra 400,000 dòng, xong thử code nhé
- Riêng cột XN2, hãy chọn cell B3 rồi fill xuống "mút chỉ" đến cuối ---> Mục đích không cho em nào trùng
- Giờ dùng code lọc theo điều kiện "XN2"
Tuy nhiên, để dung hòa về thời gian, phiên bản, tính chính xác thì dùng HÀM để lọc thì tôi cho là hợp lý nhất.
Ấy! Có hợp lý hay không thì phải xem NGƯỜI DÙNG: Nếu họ xài cái của mình thì kết luận cái của mình hợp lý, ngược lại thì... Ẹc... Ẹc...
==> Tùy "phương tiện" của mình đang có là gì, tùy vào trường hợp trên sheet hay mảng... ta có 1 phương thức thực hiện cái này hay cái khác hoặc kết hợp nhiều phương thức lại để thực hiện.
Tôi nói đúng chứ? Tôi nói câu này là nói chung cho bất kỳ ai viết phần mềm, không riêng gì hàm của Nghĩa đâu!
(Nay là năm 2013 rồi, ai còn xài Office 2003 thì ráng chịu thôi, trách ai?)
Tôi nghĩ vấn đề cập nhật mới không phải liên quan đến tiền mà là thói quen (xài quen thì không muốn thay đổi)Theo thống kê tại Việt Nam thì cho tới hiện nay có tới hơn 85% người dùng đang xài WinXP và Excel 2003 đó Thầy, liệu 85% người dùng Việt Nam có chịu đổi tất cả qua phiên bản mới hay không? Liệu có thay đổi hết máy tính hay không vì nếu thay phiên bản Win mới thì phải thay đổi luôn cả máy tính lỗi thời, chưa kể giá bản quyền của mỗi loại Win và Office nó có thể lên tới chục triệu! Thử hỏi có nên thay đổi hay không nếu người ta không cần đến những cái xa xỉ trong những phiên bản mới?
Đồng ý rằng chúng ta cập nhật cái mới, nhưng chắc cũng để đó, cho đến khi "dân giàu, nước mạnh" thì cũng sẽ dùng tới thôi!
Khi nào sếp bạn nhận được file xlsx từ đối tác nước ngoài gửi đến, ổng đọc không được thì tự nhiên ổng sẽ.. hết ngay chứ gìmấy xếp cứ hỏi mày nâng cấp để làm gì? nhiều đó xài đủ rồi.....
chắn lẻ nói với xếp để em cập nhật cho kịp GPE.....hì hì.....ẻ
Khi nào sếp bạn nhận được file xlsx từ đối tác nước ngoài gửi đến, ổng đọc không được thì tự nhiên ổng sẽ.. hết ngay chứ gì
Chuyện thường!
Có khi ông ta đề nghị đối tác Convert xuống 2003 trước khi gửi nữa chứ! Gửi mail lẹ hơn đổi toàn bộ máy tính mà Thầy!
Có mà điên mới dám đưa ra đề nghị này!
Hic...