Lọc danh sách duy nhất người lao động có điều kiện (1 người xem)

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

minhcong.tckt

Thành viên thường trực
Tham gia
13/4/11
Bài viết
385
Được thích
36
Giới tính
Nam
Em gửi file đính kèm, mong các anh chị trong diễn đàn giúp đỡ
Cột nhập dữ liệu: D, E
Đáp án mẫu tại cột J và K
 

File đính kèm

Upvote 0
Em chưa biết sử dụng "advanced filter" lắm, mong anh giúp đỡ thêm
 
Upvote 0
Bạn tham khảo một đoạn Code VBA này nhé. Dạng Function, bạn chọn 1 vùng rồi gõ công thức như File rồi bấm tổ hợp phím Ctrl + Shift + Enter.
Mã:
Function GPE(Rng As Range, DK As Long)
Dim Arr, Res, i As Long, k As Long
Arr = Rng.Value
ReDim Res(1 To UBound(Arr, 1), 1 To 1)
With CreateObject("Scripting.Dictionary")
    For i = 1 To UBound(Arr, 1)
        If Arr(i, 2) = DK Then
            If Not .Exists(Arr(i, 1)) Then
                k = k + 1
                .Add Arr(i, 1), k
                Res(k, 1) = Arr(i, 1)
            End If
        End If
    Next
End With
GPE = Res
End Function
 

File đính kèm

Upvote 0
Công thức mảng như vậy, em sử dụng khoảng 3000 - 5000 dòng có chậm không ạ
 
Upvote 0
Công thức mảng như vậy, em sử dụng khoảng 3000 - 5000 dòng có chậm không ạ
Bạn cứ thử đi rồi biết, muốn tiếp cân VBA thì cái đầu tiên đó là phải "dám thử, dám làm, làm sai thì sửa" cứ đoán rồi nghĩ trong khi có đủ công cụ thì ...Ẹc ẹc
 
Upvote 0
Công thức mảng như vậy, em sử dụng khoảng 3000 - 5000 dòng có chậm không ạ

Đương nhiên sẽ chậm... dữ liệu càng nhiều càng chậm
Nói chung với dữ liệu lớn, chẳng ai dùng công thức (cho dù công thức được viết từ VBA) mà người ta sẽ dùng công cụ có sẵn (như Advanced Filter, PivotTable..) hoặc dùng Sub
 
Upvote 0
nhưng hình như dữ liệu nhiều dòng quá mà dùng advanced filter cho kết quả không chính xác hay sao ấy anh ndu à.
 
Upvote 0
Thêm 1 cái cho bạn dùng = ado.
[GPECODE=sql]Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$I$4" Then
Dim adoConn As Object, adoRs As Object
Set adoConn = CreateObject("ADODB.Connection")
Set adoRs = CreateObject("ADODB.Recordset")
With adoConn
.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & ThisWorkbook.FullName & _
";Extended Properties=""Excel 8.0;HDR=No;IMEX=1"";"
.Open
End With
With adoRs
.ActiveConnection = adoConn
.Open "select distinct f1 from [Sheet1$D5:E5000] where f2=" & Target.Value
End With
[H6:H65000].ClearContents
[H6].CopyFromRecordset adoRs
adoRs.Close: Set adoRs = Nothing
adoConn.Close: Set adoConn = Nothing
End If
End Sub

[/GPECODE]
 

File đính kèm

Upvote 0
em thử cái file này nó bị vậy đây. Bác thử xem thế nào

Bác Bill khó lòng mà sai được lắm, chỉ có ta áp dụng sai thôi
Nguyên tắc của Advanced Filter là DỮ LIỆU PHẢI CÓ TIÊU ĐỀ
Trường hợp dữ liệu của bạn không có tiêu đề thì bác Bill sẽ lấy cell đầu tiên làm tiêu đề ---> Dẫn đến sau khi lọc ta thấy dư 1 giá trị (chính là cái giá trị đã bị lấy làm tiêu đề ấy)
 
Upvote 0
em thử cái file này nó bị vậy đây. Bác thử xem thế nào

Đó là cột tiêu đề mà bạn, file bạn không có cột tiêu đề thì mặc định nó sẽ lấy dòng dầu tiên làm tiêu đề, mà tiêu đề thì sẽ không nằm trong điều kiện lọc.
 
Upvote 0
trời ạ. thế mà em tưởng bị sai mới chết chứ. lại học thêm được một món mới rồi. thanks các bác.
 
Upvote 0
Thêm 1 cái cho bạn dùng = ado.
[GPECODE=sql]Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$I$4" Then
Dim adoConn As Object, adoRs As Object
Set adoConn = CreateObject("ADODB.Connection")
Set adoRs = CreateObject("ADODB.Recordset")
With adoConn
.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & ThisWorkbook.FullName & _
";Extended Properties=""Excel 8.0;HDR=No;IMEX=1"";"
.Open
End With
With adoRs
.ActiveConnection = adoConn
.Open "select distinct f1 from [Sheet1$D5:E5000] where f2=" & Target.Value
End With
[H6:H65000].ClearContents
[H6].CopyFromRecordset adoRs
adoRs.Close: Set adoRs = Nothing
adoConn.Close: Set adoConn = Nothing
End If
End Sub

[/GPECODE]
anh cho em hỏi đoạn code này có nghĩa là gì vậy:
.Open "select distinct f1 from [Sheet1$D5:E5000] where f2=" & Target.Value

đặc biệt chổ f1 và f2 đó.
và thêm 1 điều nữa là nếu cột E điều kiện hiện tại giời qua cột f nữa thì nó có được hay không vậy.
 
Lần chỉnh sửa cuối:
Upvote 0
anh cho em hỏi đoạn code này có nghĩa là gì vậy:
.Open "select distinct f1 from [Sheet1$D5:E5000] where f2=" & Target.Value

đặc biệt chổ f1 và f2 đó.
và thêm 1 điều nữa là nếu cột E điều kiện hiện tại giời qua cột f nữa thì nó có được hay không vậy.

Đầu tiên bạn xem đoạn chuổi kết nối có HDR=No thì điều kiện để chọn dữ liệu là không cần lấy dòng đầu tiên để làm tiêu đề cột. Nếu là Yes thì ngược lại. Tôi tạm gỉai thích 2 trường hợp này như sau:
  1. HDR=No: Vùng dữ liệu [Sheet1$D5:E5000]: Màu đỏ là tên sheet, màu xanh là vùng dữ liệu. Bạn thấy trong vùng dữ liệu có 2 cột D và E, thì ngầm định cột D là F1, E là F2. Nếu vùng dữ liệu có n cột thì sẽ có Fn tương ứng. Lưu ý là Fn<=255. Sau này truy vấn sẽ lấy tên cột là F1, F2...Fn
  2. HDR=Yes: Vùng dữ liệu [Sheet1$D4:E5000]: Màu đỏ là tên sheet, màu xanh là vùng dữ liệu. Bạn thấy trong vùng dữ liệu có 2 cột D và E, thì ngầm định cell D4 là tên cột thứ nhất ([Danh Sách Mẫu]), E4 là tên cột thứ 2 ([Điều Kiện]). Nếu vùng dữ liệu có n cột thì sẽ có Tên Cột n tương ứng. Lưu ý là Tên Cột n<=255. Sau này truy vấn sẽ lấy tên cột là ([Danh Sách Mẫu]), ([Điều Kiện])...
Còn điều kiện lọc như thế nào thì bạn nên đưa file lên để dễ hình dung nhé.
 
Upvote 0
Đầu tiên bạn xem đoạn chuổi kết nối có HDR=No thì điều kiện để chọn dữ liệu là không cần lấy dòng đầu tiên để làm tiêu đề cột. Nếu là Yes thì ngược lại. Tôi tạm gỉai thích 2 trường hợp này như sau:
  1. HDR=No: Vùng dữ liệu [Sheet1$D5:E5000]: Màu đỏ là tên sheet, màu xanh là vùng dữ liệu. Bạn thấy trong vùng dữ liệu có 2 cột D và E, thì ngầm định cột D là F1, E là F2. Nếu vùng dữ liệu có n cột thì sẽ có Fn tương ứng. Lưu ý là Fn<=255. Sau này truy vấn sẽ lấy tên cột là F1, F2...Fn
  2. HDR=Yes: Vùng dữ liệu [Sheet1$D4:E5000]: Màu đỏ là tên sheet, màu xanh là vùng dữ liệu. Bạn thấy trong vùng dữ liệu có 2 cột D và E, thì ngầm định cell D4 là tên cột thứ nhất ([Danh Sách Mẫu]), E4 là tên cột thứ 2 ([Điều Kiện]). Nếu vùng dữ liệu có n cột thì sẽ có Tên Cột n tương ứng. Lưu ý là Tên Cột n<=255. Sau này truy vấn sẽ lấy tên cột là ([Danh Sách Mẫu]), ([Điều Kiện])...
Còn điều kiện lọc như thế nào thì bạn nên đưa file lên để dễ hình dung nhé.
cám ơn anh em, post file lên nhờ anh xem nhé
 

File đính kèm

Upvote 0
cám ơn anh em, post file lên nhờ anh xem nhé

PHP:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$K$4" Then
    Dim adoConn As Object, adoRs As Object
    Set adoConn = CreateObject("ADODB.Connection")
    Set adoRs = CreateObject("ADODB.Recordset")
    With adoConn
        .ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
                            "Data Source=" & ThisWorkbook.FullName & _
                            ";Extended Properties=""Excel 8.0;HDR=No;IMEX=1"";"
        .Open
    End With
    With adoRs
        .ActiveConnection = adoConn
        .Open "select distinct f1 from [Sheet1$D5:G5000] where f4=" & Target.Value
    End With
    [J6:H65000].ClearContents
    [J6].CopyFromRecordset adoRs
    adoRs.Close: Set adoRs = Nothing
    adoConn.Close: Set adoConn = Nothing
End If
End Sub
 
Upvote 0
PHP:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$K$4" Then
    Dim adoConn As Object, adoRs As Object
    Set adoConn = CreateObject("ADODB.Connection")
    Set adoRs = CreateObject("ADODB.Recordset")
    With adoConn
        .ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
                            "Data Source=" & ThisWorkbook.FullName & _
                            ";Extended Properties=""Excel 8.0;HDR=No;IMEX=1"";"
        .Open
    End With
    With adoRs
        .ActiveConnection = adoConn
        .Open "select distinct f1 from [Sheet1$D5:G5000] where f4=" & Target.Value
    End With
    [J6:H65000].ClearContents
    [J6].CopyFromRecordset adoRs
    adoRs.Close: Set adoRs = Nothing
    adoConn.Close: Set adoConn = Nothing
End If
End Sub
Code này có thể viết gọn hơn đó.
 
Upvote 0
PHP:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$K$4" Then
    Dim adoConn As Object, adoRs As Object
    Set adoConn = CreateObject("ADODB.Connection")
    Set adoRs = CreateObject("ADODB.Recordset")
    With adoConn
        .ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
                            "Data Source=" & ThisWorkbook.FullName & _
                            ";Extended Properties=""Excel 8.0;HDR=No;IMEX=1"";"
        .Open
    End With
    With adoRs
        .ActiveConnection = adoConn
        .Open "select distinct f1 from [Sheet1$D5:G5000] where f4=" & Target.Value
    End With
    [J6:H65000].ClearContents
    [J6].CopyFromRecordset adoRs
    adoRs.Close: Set adoRs = Nothing
    adoConn.Close: Set adoConn = Nothing
End If
End Sub
anh hải ơi, code của anh ok , nhưng có 1 điều nhờ anh sửa lại giúp vì nếu cột điều kiện là số thì đúng còn nếu dạng text thi code báo lỗi
Open "select distinct f1 from [Sheet1$D5:G5000] where f4=" & Target.Value
nhờ anh giúp em nhé
cám ơn anh
 
Upvote 0
anh hải ơi, code của anh ok , nhưng có 1 điều nhờ anh sửa lại giúp vì nếu cột điều kiện là số thì đúng còn nếu dạng text thi code báo lỗi
Open "select distinct f1 from [Sheet1$D5:G5000] where f4=" & Target.Value
nhờ anh giúp em nhé
cám ơn anh

Chứ mắc gì không xài VBA cho khỏe thân, bày đặt lọc bằng ADO cho khổ vậy? ADO kén dữ liệu lắm. Chỉ cần 1 cái khoảng trắng cũng chết.
Thay vì dùng ADO thì mình dùng VBA phổ thông cho nhẹ nhàng
Cũng nên biết người biết ta thì đở cực thân. Thậm chí chữ K phải viết hoa trong khi bắt sự kiện change bạn còn không biết mà muốn vọc ADO thì làm ăn gì nổi. Cho xin đi.
PHP:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$K$4" Then
   Dim arr(), dk, i
   dk = Target.Value
   arr = Range("D5", [G65536].End(3)).Value
   With CreateObject("scripting.dictionary")
      For i = 1 To UBound(arr)
         If arr(i, 4) = dk Then
            If Not .exists(arr(i, 1)) Then
               .Add (arr(i, 1)), ""
            End If
         End If
      Next
      [J6:J1000].ClearContents
      If .Count = 0 Then End
      [J6].Resize(.Count) = Application.Transpose(.keys)
   End With
End If
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Chứ mắc gì không xài VBA cho khỏe thân, bày đặt lọc bằng ADO cho khổ vậy? ADO kén dữ liệu lắm. Chỉ cần 1 cái khoảng trắng cũng chết.
Thay vì dùng ADO thì mình dùng VBA phổ thông cho nhẹ nhàng
Cũng nên biết người biết ta thì đở cực thân. Thậm chí chữ K phải viết hoa trong khi bắt sự kiện change bạn còn không biết mà muốn vọc ADO thì làm ăn gì nổi. Cho xin đi.
PHP:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$K$4" Then
   Dim arr(), dk, i
   dk = Target.Value
   arr = Range("D5", [G65536].End(3)).Value
   With CreateObject("scripting.dictionary")
      For i = 1 To UBound(arr)
         If arr(i, 4) = dk Then
            If Not .exists(arr(i, 1)) Then
               .Add (arr(i, 1)), ""
            End If
         End If
      Next
      [J6:J1000].ClearContents
      If .Count = 0 Then End
      [J6].Resize(.Count) = Application.Transpose(.keys)
   End With
End If
End Sub
dạ tại em còn gà anh ơi, e không nghĩ đến được vậy. bớt nóng anh nhé. cám ơn anh nhiều
 
Upvote 0
anh hải ơi, code của anh ok , nhưng có 1 điều nhờ anh sửa lại giúp vì nếu cột điều kiện là số thì đúng còn nếu dạng text thi code báo lỗi
Open "select distinct f1 from [Sheet1$D5:G5000] where f4=" & Target.Value
nhờ anh giúp em nhé
cám ơn anh
Text thì cho nó dấu nháy đơn bao quanh là ok thôi.

Open "select distinct f1 from [Sheet1$D5:G5000] where f4='" & Target.Value & "'"
 
Upvote 0
em cũng làm đúng như anh nhung vẫn lỗi anh à
Với dữ liệu đơn giản thì có thể tham khảo code này rồi tuỳ biến
PHP:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$K$4" Then
   [J6:J1000].ClearContents
   With Range("G5", [G65536].End(3))
      .AutoFilter 1, Target
      .Offset(, -3).SpecialCells(12).Copy [J6]
      .AutoFilter
   End With
   Range("J6", [J65536].End(3)).RemoveDuplicates 1
End If
End Sub
 
Upvote 0
Với dữ liệu đơn giản thì có thể tham khảo code này rồi tuỳ biến
PHP:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$K$4" Then
   [J6:J1000].ClearContents
   With Range("G5", [G65536].End(3))
      .AutoFilter 1, Target
      .Offset(, -3).SpecialCells(12).Copy [J6]
      .AutoFilter
   End With
   Range("J6", [J65536].End(3)).RemoveDuplicates 1
End If
End Sub
cám ơn anh quang hải
 
Upvote 0
Với dữ liệu đơn giản thì có thể tham khảo code này rồi tuỳ biến
PHP:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$K$4" Then
   [J6:J1000].ClearContents
   With Range("G5", [G65536].End(3))
      .AutoFilter 1, Target
      .Offset(, -3).SpecialCells(12).Copy [J6]
      .AutoFilter
   End With
   Range("J6", [J65536].End(3)).RemoveDuplicates 1
End If
End Sub
Nếu phải FILTER thì mình thích Advanced Filter hơn:
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
  If Target.Address = "$K$4" Then
    [IV1] = [G4]: [IV2] = Target.Value: [J5] = [D4]
    [D4:G1000].AdvancedFilter 2, [IV1:IV2], [J5], True
    [IV1:IV2].ClearContents
  End If
End Sub
 
Upvote 0
Nếu phải FILTER thì mình thích Advanced Filter hơn:
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
  If Target.Address = "$K$4" Then
    [IV1] = [G4]: [IV2] = Target.Value: [J5] = [D4]
    [D4:G1000].AdvancedFilter 2, [IV1:IV2], [J5], True
    [IV1:IV2].ClearContents
  End If
End Sub
anh ơi code của anh thì ok nhưng vẫn còn lỗi này anh ah. ví dụ trong bảng điều kiện có chữ a, và a1 thi luc chọn a thì nó cho ra cả a1 luôn vậy nhờ anh xem lại đoạn này giúp em nhé
 
Upvote 0
anh ơi code của anh thì ok nhưng vẫn còn lỗi này anh ah. ví dụ trong bảng điều kiện có chữ a, và a1 thi luc chọn a thì nó cho ra cả a1 luôn vậy nhờ anh xem lại đoạn này giúp em nhé

Bạn cho file có dữ liệu tổng quát lên đi. Ai mà biết dữ liệu thật còn có trường hợp nào nữa chứ
-----------------
Tạm thời thì sửa thành vầy:
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
  If Target.Address = "$K$4" Then
    [IV1] = [G4]: [COLOR=#ff0000][IV2] = "'=" & Target.Value[/COLOR]: [J5] = [D4]
    [D4:G1000].AdvancedFilter 2, [IV1:IV2], [J5], True
    [IV1:IV2].ClearContents
  End If
End Sub
Chỗ màu đỏ là chỗ sửa lại
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn cho file có dữ liệu tổng quát lên đi. Ai mà biết dữ liệu thật còn có trường hợp nào nữa chứ
-----------------
Tạm thời thì sửa thành vầy:
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
  If Target.Address = "$K$4" Then
    [IV1] = [G4]: [COLOR=#ff0000][IV2] = "'=" & Target.Value[/COLOR]: [J5] = [D4]
    [D4:G1000].AdvancedFilter 2, [IV1:IV2], [J5], True
    [IV1:IV2].ClearContents
  End If
End Sub
Chỗ màu đỏ là chỗ sửa lại
đúng rồi đó anh, cám ơn anh nhìu nhìu
 
Upvote 0

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

Back
Top Bottom