Lọc dữ liệu-chứa nhiều điều kiện lọc?

Liên hệ QC
Sẽ có khi dư, khi mà tất cả các dòng dữ liệu đều thoả. Thí dụ bỏ trống customer name, bỏ trống category, date from = 1/1/1950, date to = 31/12/2021, Profit > 1 tỷ. Dư 1 dòng và dòng đó lỗi VALUES
Cái này hình như chưa đúng lắm thầy ạ (bỏ qua vấn đề code em còn đang lỗi ở một số ô profit="" không so sánh được nhé). Nếu theo code, tất cả đều thỏa là cứ bỏ trống toàn bộ. Vậy khi resize tăng thêm 1 dòng để gán darr thì dòng cuối là dòng trống chứ sao lại báo lỗi value thầy? ví dụ như darr=1000 dòng 10 cột, mình resize(1001,10) =darr vẫn được mà thầy
 
Vậy khi resize tăng thêm 1 dòng để gán darr thì dòng cuối là dòng trống chứ sao lại báo lỗi value thầy? ví dụ như darr=1000 dòng 10 cột, mình resize(1001,10) =darr vẫn được mà thầy
Nói thì không chịu tin. Tôi nhớ nhầm, lỗi NA chứ không phải lỗi VALUE

1609567004922.png
 
Vậy thầy kiểm tra lại giúp em, sao code em để k+1 vậy (điều kiện trên để trống hết), dữ liệu trả về đủ cả mà dòng cuối cùng không bị #N/A vậy ạ? Trường hợp này có đặc biệt gì không thầy
Sau khi thoát vòng lặp thì k chứa số dòng dữ liệu, nếu k=ubound(sarr) thì vùng k+1 sẽ lớn hơn số dòng của mảng dẫn đến lỗi. Cách khắc phục là bạn không nên tìm cách thu gọn code lại dẫn tới khó hiểu, dễ sai, cứ xét if k>0 then resize(k) là được.
 
Vậy thầy kiểm tra lại giúp em, sao code em để k+1 vậy (điều kiện trên để trống hết), dữ liệu trả về đủ cả mà dòng cuối cùng không bị #N/A vậy ạ? Trường hợp này có đặc biệt gì không thầy
Do bạn lấy dữ liệu sArr luôn cả tiêu đề nên số dòng của sArr nhiều hơn dữ liệu 1 dòng. Sau đó dArr lại Redim bằng với sArr
PHP:
With Sheets("Orders")
    sArr = .Range("A1:J" & .Cells(.Rows.Count, "A").End(xlUp).Rows).Value
    ReDim dArr(1 To UBound(sArr), 1 To UBound(sArr, 2))
 
Do bạn lấy dữ liệu sArr luôn cả tiêu đề nên số dòng của sArr nhiều hơn dữ liệu 1 dòng. Sau đó dArr lại Redim bằng với sArr
PHP:
With Sheets("Orders")
    sArr = .Range("A1:J" & .Cells(.Rows.Count, "A").End(xlUp).Rows).Value
    ReDim dArr(1 To UBound(sArr), 1 To UBound(sArr, 2))
Lúc nãy em hỏi là em đã kiểm tra theo code bài #53 thầy ạ, còn từ A1 thì K+1 là vừa đủ thì em biết. Nhưng cuối cùng kiểm tra kỹ lại nó là ở chỗ này (nhiều khi nhanh nhẩu quá khổ):
Rich (BB code):
sArr = .Range("A1:J" & .Cells(.Rows.Count, "A").End(xlUp).Rows).Value
Gửi lại bạn @NHN_Phương code cuối cùng của mình nhé : (mà mình thấy bạn cũng học code, cũng biết nhiều lắm mà, tự sửa nếu chưa ưng ý nhé)
Mã:
Option Explicit
Sub NTKTNN()
Dim sArr(), dArr(), CusName, ProCat, fDate As Long, tDate As Long, Profit As String, Bo As Boolean
Dim i As Long, J As Long, K As Long
Application.ScreenUpdating = False
With Sheets("Orders")
    sArr = .Range("A2:J" & .Cells(.Rows.Count, "A").End(xlUp).Row).Value
End With
With Sheets("Filter")
    CusName = Split(";" & .Range("B1").Value, ";")
    ProCat = Split(";" & .Range("B2").Value, ";")
    fDate = .Range("D1").Value
    tDate = .Range("D2").Value
    Profit = .Range("E2").Value
    ReDim dArr(1 To UBound(sArr), 1 To UBound(sArr, 2))
    For i = 1 To UBound(sArr, 1)
        For J = 1 To UBound(CusName)
            If InStr(1, sArr(i, 8), CusName(J), 1) > 0 Then Bo = True: Exit For
        Next
        If Bo = False Then GoTo Next_I Else Bo = False
        For J = 1 To UBound(ProCat)
            If InStr(1, sArr(i, 10), ProCat(J), 1) > 0 Then Bo = True: Exit For
        Next
        If Bo = False Then GoTo Next_I Else Bo = False
        If fDate > 0 And tDate > 0 Then
            If sArr(i, 2) >= fDate And sArr(i, 2) <= tDate Then Bo = True
            If Bo = False Then GoTo Next_I Else Bo = False
        End If
        If Profit <> "" Then
            If Evaluate(sArr(i, 6) * 1 & Profit) Then Bo = True
            If Bo = False Then GoTo Next_I Else Bo = False
        End If
        K = K + 1
        For J = 1 To UBound(sArr, 2)
            dArr(K, J) = sArr(i, J)
        Next
Next_I:
    Next
    If K Then
        .Range("A4:J10000").ClearContents
        .Range("A4").Resize(K, UBound(sArr, 2)) = dArr
    End If
End With
Application.ScreenUpdating = True
End Sub
 
Lúc nãy em hỏi là em đã kiểm tra theo code bài #53 thầy ạ, còn từ A1 thì K+1 là vừa đủ thì em biết. Nhưng cuối cùng kiểm tra kỹ lại nó là ở chỗ này (nhiều khi nhanh nhẩu quá khổ):
Rich (BB code):
sArr = .Range("A1:J" & .Cells(.Rows.Count, "A").End(xlUp).Rows).Value
Kể cả .Row (không s) nhưng lấy từ A1:J mà làm sao không dư
 
Con chào Bác @HieuCD ,
Cảm ơn Bác đã quan tâm vấn đề của con ạ.
Bác mà tham gia, nhờ Bác xử lý giúp con thêm 2 điều kiện nữa lọc trong ô D1,D2,E2 theo cột "Order Date" & "Profit" với ạ:
Bắt lỗi điều kiện nếu có điều kiện trong ô D1 & D2 thì phải đủ cả 2 điều kiện từ ngày đến ngày và ngày trong ô D2 lớn hơn ngày trong ô D1thì mới code mới chạy ạ .

View attachment 252181
ô E2 giá trị Profit format cell là "Text"
Chạy thử code
Mã:
Sub XYZ()
  Dim sArr(), Res()
  Dim i&, n&, k&, j&, sRow&, sCol&
  Dim Customer, Product, fDate, eDate, Profit, tmp
 
  With Sheets("Orders")
    sArr = .Range("A2:J" & .Range("H" & Rows.Count).End(xlUp).Row).Value
  End With
  sRow = UBound(sArr): sCol = UBound(sArr, 2)
  ReDim Res(1 To sRow, 1 To 10)
  With Sheets("Filter")
    i = .Range("A" & Rows.Count).End(xlUp).Row
    If i > 3 Then .Range("A4:J" & i).ClearContents 'Xoa du lieu
   
    Customer = Split(";" & .Range("B1").Value, ";")
    If Customer(1) = "*" Then Customer(1) = ""
   
    Product = Split(";" & .Range("B2").Value, ";")
    If Product(1) = "*" Then Product(1) = ""
   
    fDate = .Range("D1").Value:    eDate = .Range("D2").Value
    If Not (IsDate(fDate) And IsDate(eDate)) Or fDate > eDate Then
      MsgBox ("Nhap lai dieu kien ngay thang"): Exit Sub
    End If
   
    Profit = .Range("E2").Value
    If IsNumeric(Profit) And Profit <> Empty Then Profit = "=" & Profit
  End With
  For i = 1 To sRow
    tmp = sArr(i, 8)
    For n = 1 To UBound(Customer)
      If InStr(1, tmp, Customer(n), vbTextCompare) > 0 Then Exit For
    Next n
    If n = UBound(Customer) + 1 Then GoTo KhongThoaDieuKien
   
    tmp = sArr(i, 10)
    For n = 1 To UBound(Product)
      If InStr(1, tmp, Product(n), vbTextCompare) > 0 Then Exit For
    Next n
    If n = UBound(Product) + 1 Then GoTo KhongThoaDieuKien
   
    If sArr(i, 2) < fDate Or sArr(i, 2) > eDate Then GoTo KhongThoaDieuKien
   
    If Evaluate(Val(sArr(i, 6)) & Profit) Or Profit = Empty Then
      k = k + 1
      For j = 1 To 10
        Res(k, j) = sArr(i, j)
      Next j
    End If
KhongThoaDieuKien:
  Next i
  If k Then Sheets("Filter").Range("A4:J4").Resize(k).Value = Res
End Sub
 

File đính kèm

  • Orders-With Nulls v2.xlsb
    62.8 KB · Đọc: 15
Cảm ơn Bạn @Hau151978 nhiều ạ, kết quả đúng ý OT rồi ạ. Sử dụng câu lệnh truy vấn luôn ngắn gọn và cho kết chính xác thật.
@Nhattanktnn , code bài 30 sau khi OT bỏ trống B2 thì lấy thêm 2 dòng dữ liệu màu đỏ, nhờ bạn xem giúp ạ.
Hoặc trong trường hợp B1 không nhập gì thì code bị lỗi "Type mismatch" tại dòng: If Evaluate(sArr(i, 6) & Profit) Then

View attachment 252292
Điều kiện B1 và B2 là chuỗi đầy đủ hay là sao em?
 
Lúc nãy em hỏi là em đã kiểm tra theo code bài #53 thầy ạ, còn từ A1 thì K+1 là vừa đủ thì em biết. Nhưng cuối cùng kiểm tra kỹ lại nó là ở chỗ này (nhiều khi nhanh nhẩu quá khổ):
Rich (BB code):
sArr = .Range("A1:J" & .Cells(.Rows.Count, "A").End(xlUp).Rows).Value
Gửi lại bạn @NHN_Phương code cuối cùng của mình nhé : (mà mình thấy bạn cũng học code, cũng biết nhiều lắm mà, tự sửa nếu chưa ưng ý nhé)
Mã:
Option Explicit
Sub NTKTNN()
Dim sArr(), dArr(), CusName, ProCat, fDate As Long, tDate As Long, Profit As String, Bo As Boolean
Dim i As Long, J As Long, K As Long
Application.ScreenUpdating = False
With Sheets("Orders")
    sArr = .Range("A2:J" & .Cells(.Rows.Count, "A").End(xlUp).Row).Value
End With
With Sheets("Filter")
    CusName = Split(";" & .Range("B1").Value, ";")
    ProCat = Split(";" & .Range("B2").Value, ";")
    fDate = .Range("D1").Value
    tDate = .Range("D2").Value
    Profit = .Range("E2").Value
    ReDim dArr(1 To UBound(sArr), 1 To UBound(sArr, 2))
    For i = 1 To UBound(sArr, 1)
        For J = 1 To UBound(CusName)
            If InStr(1, sArr(i, 8), CusName(J), 1) > 0 Then Bo = True: Exit For
        Next
        If Bo = False Then GoTo Next_I Else Bo = False
        For J = 1 To UBound(ProCat)
            If InStr(1, sArr(i, 10), ProCat(J), 1) > 0 Then Bo = True: Exit For
        Next
        If Bo = False Then GoTo Next_I Else Bo = False
        If fDate > 0 And tDate > 0 Then
            If sArr(i, 2) >= fDate And sArr(i, 2) <= tDate Then Bo = True
            If Bo = False Then GoTo Next_I Else Bo = False
        End If
        If Profit <> "" Then
            If Evaluate(sArr(i, 6) * 1 & Profit) Then Bo = True
            If Bo = False Then GoTo Next_I Else Bo = False
        End If
        K = K + 1
        For J = 1 To UBound(sArr, 2)
            dArr(K, J) = sArr(i, J)
        Next
Next_I:
    Next
    If K Then
        .Range("A4:J10000").ClearContents
        .Range("A4").Resize(K, UBound(sArr, 2)) = dArr
    End If
End With
Application.ScreenUpdating = True
End Sub
ô E2 giá trị Profit format cell là "Text"
Chạy thử code
Mã:
Sub XYZ()
  Dim sArr(), Res()
  Dim i&, n&, k&, j&, sRow&, sCol&
  Dim Customer, Product, fDate, eDate, Profit, tmp

  With Sheets("Orders")
    sArr = .Range("A2:J" & .Range("H" & Rows.Count).End(xlUp).Row).Value
  End With
  sRow = UBound(sArr): sCol = UBound(sArr, 2)
  ReDim Res(1 To sRow, 1 To 10)
  With Sheets("Filter")
    i = .Range("A" & Rows.Count).End(xlUp).Row
    If i > 3 Then .Range("A4:J" & i).ClearContents 'Xoa du lieu
  
    Customer = Split(";" & .Range("B1").Value, ";")
    If Customer(1) = "*" Then Customer(1) = ""
  
    Product = Split(";" & .Range("B2").Value, ";")
    If Product(1) = "*" Then Product(1) = ""
  
    fDate = .Range("D1").Value:    eDate = .Range("D2").Value
    If Not (IsDate(fDate) And IsDate(eDate)) Or fDate > eDate Then
      MsgBox ("Nhap lai dieu kien ngay thang"): Exit Sub
    End If
  
    Profit = .Range("E2").Value
    If IsNumeric(Profit) And Profit <> Empty Then Profit = "=" & Profit
  End With
  For i = 1 To sRow
    tmp = sArr(i, 8)
    For n = 1 To UBound(Customer)
      If InStr(1, tmp, Customer(n), vbTextCompare) > 0 Then Exit For
    Next n
    If n = UBound(Customer) + 1 Then GoTo KhongThoaDieuKien
  
    tmp = sArr(i, 10)
    For n = 1 To UBound(Product)
      If InStr(1, tmp, Product(n), vbTextCompare) > 0 Then Exit For
    Next n
    If n = UBound(Product) + 1 Then GoTo KhongThoaDieuKien
  
    If sArr(i, 2) < fDate Or sArr(i, 2) > eDate Then GoTo KhongThoaDieuKien
  
    If Evaluate(Val(sArr(i, 6)) & Profit) Or Profit = Empty Then
      k = k + 1
      For j = 1 To 10
        Res(k, j) = sArr(i, j)
      Next j
    End If
KhongThoaDieuKien:
  Next i
  If k Then Sheets("Filter").Range("A4:J4").Resize(k).Value = Res
End Sub
Xin cảm ơn Bác @HieuCD và Bạn @Nhattanktnn đã luôn quan tâm & giúp đỡ OT, cả 2 code chạy khá nhanh ra kết quả chính xác rồi ạ.

Điều kiện B1 và B2 là chuỗi đầy đủ hay là sao em?

Xin chào anh @Hai Lúa Miền Tây ,
Cảm ơn anh đã quan tâm đến vấn đề của OT ạ.
Dạ B1 và B2 có thể là chuỗi đầy đủ và cũng có thể là chuỗi không đầy đủ anh ạ, hihi.
Kính chúc anh năm mới sức khỏe & thành công ạ.
 
Dạ vầng đúng rồi anh: PQ,VBA,ADO đều đủ cả rồi anh ạ. :heart:
Nếu anh Hai Lúa có thêm cách gì độc đáo & và có hứng thì ... tiếp tục đi anh. :fish:
Nạp hết vào Recordset rồi lọc dữ liệu. Tuy nhiên nếu lọc 1 lần trên dữ liệu thì em có thể dùng kết quả những bài trên. Còn nếu cứ dùng Recordset đó để lọc nhiều lần thì nên dùng cách anh đề nghị.
 
Nạp hết vào Recordset rồi lọc dữ liệu. Tuy nhiên nếu lọc 1 lần trên dữ liệu thì em có thể dùng kết quả những bài trên. Còn nếu cứ dùng Recordset đó để lọc nhiều lần thì nên dùng cách anh đề nghị.
Hic anh Hai Lúa nói vậy OT tiếp thu không khác gì đàn gảy tai trâu anh ơi.
"Còn nếu cứ dùng Recordset đó để lọc nhiều lần thì nên dùng cách anh đề nghị." nếu có hứng thú anh chỉ dẫn thêm cách này nhé anh. :"'
 
Web KT
Back
Top Bottom