Filter Array 2D theo nhiều điều kiện

Liên hệ QC

Ngô Hải Đăng

Thành viên hoạt động
Tham gia
31/8/17
Bài viết
183
Được thích
247
Giới tính
Nam
Hàm nhận 2 tham số iArray (Mảng hoặc Range) và iFilter as String (điều kiện Filter)
Các điều kiện được nối với nhau bởi OR, AND, ]OR[, ]AND[ theo mức độ ưu tiên từ cao đến thấp như sau: ]AND[ >> ]OR[ >> AND >> OR.
Các toán tử so sánh gồm: LIKE, !LIKE, <, <=, >, >=, =, <>. Trong đó LIKE và !LIKE dùng cho Text và Text phải được đặt trong 2 dấu nháy đơn (Ví dụ: 'Giải pháp Excel')
Chuỗi Filter được viết theo cú pháp như sau: [5] > 100 AND [3] LIKE '*GPE*'
Trong đó[5] và [3] là cột cần Filter, các toán tử so sánh và các phép nối OR AND đều phải cách ra 1 khoảng trắng.
Trường hợp cần so sánh ngày thì ta phải thêm # trước ngày cần so sánh (Ví dụ: [1] > #21/12/2020)
Trường hợp có sử dụng công thức thì phải thêm ? đứng trước (Ví dụ: ?[3]*[4] > 1000000 hoặc là ?Year([1]) = 2020 hoặc là ?Left([2],3) = 'GPE')

Code trong Module
PHP:
Function FilterArray2D(ByVal iArray, ByVal iFilter As String)
  Dim x&, y&, z&, minY&, maxY&, minX&, maxX&, sF$
  Dim yI(), xF(), aX

  ReDim aX(1 To 1, 1 To 1)
  If iFilter = "" Then
    aX(1, 1) = "Không có Filter..."
  Else
    If TypeName(iArray) = "Range" Then iArray = iArray.Value
    MakeFilter iFilter
    minX = LBound(iArray, 2): maxX = UBound(iArray, 2)
    For x = 1 To maxX - minX + 1
      If InStr(1, iFilter, "[" & vbBack & vbBack & x & vbBack & vbBack & "]", vbTextCompare) > 0 Then
        z = z + 1: ReDim Preserve xF(1 To z): xF(z) = x
      End If
    Next x
    If z = 0 Then
      aX(1, 1) = "Filter sai..."
    Else
      z = 0
      minY = LBound(iArray, 1): maxY = UBound(iArray, 1)
      For y = minY To maxY
        sF = iFilter
        For x = 1 To UBound(xF)
          sF = Replace(sF, "[" & vbBack & vbBack & xF(x) & vbBack & vbBack & "]", GetValueArray(iArray(y, xF(x) - 1 + minX)), , , vbTextCompare)
        Next x
        If CheckFilter(sF) Then z = z + 1: ReDim Preserve yI(1 To z): yI(z) = y
      Next y
      If z = 0 Then
        aX(1, 1) = "Không tìm ra..."
      Else
        ReDim aX(1 To z, 1 To maxX - minX + 1)
        For y = 1 To z
          For x = 1 To maxX - minX + 1
            aX(y, x) = iArray(yI(y), x - 1 + minX)
          Next x
        Next y
      End If
    End If
  End If
  FilterArray2D = aX
End Function

Private Sub MakeFilter(iFilter As String)
  Dim xBeginText&, xEndText&, sText$, x&, aCompare

  iFilter = WorksheetFunction.Trim(iFilter)
  iFilter = Replace(iFilter, "[", "[" & vbBack & vbBack)
  iFilter = Replace(iFilter, "]", vbBack & vbBack & "]")
  iFilter = Replace(iFilter, " ", vbBack, , , vbTextCompare)
  iFilter = Replace(iFilter, vbBack & vbBack & vbBack, vbBack)

  xBeginText = InStr(1, iFilter, "'") + 1
  While xBeginText > 1
    xEndText = InStr(xBeginText, iFilter, "'") + 1
    sText = Mid(iFilter, xBeginText, xEndText - xBeginText)
    iFilter = Replace(iFilter, sText, Replace(sText, vbBack & vbBack, ""))
    iFilter = Replace(iFilter, sText, Replace(sText, vbBack, " "))
    xBeginText = InStr(xEndText, iFilter, "'") + 1
  Wend

  aCompare = Array("!like", "<=", ">=", "<>", "like", "<", ">", "=")
  For x = 0 To UBound(aCompare)
    iFilter = Replace(iFilter, vbBack & aCompare(x) & vbBack, vbBack & x & vbBack, , , vbTextCompare)
  Next x
End Sub

Private Function GetValueArray(iValue)
  Select Case TypeName(iValue)
    Case Is = "String", "Null", "Empty", "Error": GetValueArray = "'" & CStr(iValue) & "'"
    Case Else: GetValueArray = CDbl(iValue)
  End Select
End Function

Private Function CheckFilter(ByVal iFilter As String) As Boolean
  Dim aF: aF = Split(iFilter, vbBack & "]AND[" & vbBack, , vbTextCompare)
  Dim x&
  For x = LBound(aF) To UBound(aF)
    If Not CheckFilter1(aF(x)) Then Exit Function
  Next x
  CheckFilter = True
End Function

Private Function CheckFilter1(ByVal iFilter As String) As Boolean
  Dim aF: aF = Split(iFilter, vbBack & "]OR[" & vbBack, , vbTextCompare)
  Dim x&
  For x = LBound(aF) To UBound(aF)
    If CheckFilter2(aF(x)) Then CheckFilter1 = True: Exit Function
  Next x
End Function

Private Function CheckFilter2(ByVal iFilter As String) As Boolean
  Dim aF: aF = Split(iFilter, vbBack & "AND" & vbBack, , vbTextCompare)
  Dim x&
  For x = LBound(aF) To UBound(aF)
    If Not CheckFilter3(aF(x)) Then Exit Function
  Next x
  CheckFilter2 = True
End Function

Private Function CheckFilter3(ByVal iFilter As String) As Boolean
  Dim aF: aF = Split(iFilter, vbBack & "OR" & vbBack, , vbTextCompare)
  Dim x&
  For x = LBound(aF) To UBound(aF)
    If CheckFilter4(aF(x)) Then CheckFilter3 = True: Exit Function
  Next x
End Function

Private Function CheckFilter4(ByVal iFilter As String) As Boolean
  Dim aF: aF = Split(iFilter, vbBack)
  Dim u1, u2
  u1 = GetValueFilter(aF(0)): If IsArray(u1) Then Exit Function
  u2 = GetValueFilter(aF(2)): If IsArray(u2) Then Exit Function
  Select Case aF(1)
    Case Is = 0: CheckFilter4 = Not u1 Like u2
    Case Is = 1: CheckFilter4 = u1 <= u2
    Case Is = 2: CheckFilter4 = u1 >= u2
    Case Is = 3: CheckFilter4 = u1 <> u2
    Case Is = 4: CheckFilter4 = u1 Like u2
    Case Is = 5: CheckFilter4 = u1 < u2
    Case Is = 6: CheckFilter4 = u1 > u2
    Case Is = 7: CheckFilter4 = u1 = u2
  End Select
End Function

Private Function GetValueFilter(ByVal iString As String)
  On Error GoTo HError
  Select Case Left$(iString, 1)
    Case Is = "'": GetValueFilter = Mid(iString, 2, Len(iString) - 2)
    Case Is = "?": GetValueFilter = Evaluate("=" & Mid(iString, 2))
    Case Is = "#": GetValueFilter = CDbl(CDate(Mid(Replace(iString, "'", ""), 2)))
    Case Else: GetValueFilter = Val(iString)
  End Select
  Exit Function
HError:
GetValueFilter = Array(1)
End Function

Code Test
PHP:
Sub TestFilterArray2D()
  Dim sFilter$, rData As Range, rResult As Range, aX, xTimer!
  xTimer = Timer
  'Dieu kien Filter
  sFilter = "[2] like 'KH*' and [5] like 'Kg' and [8] > 0"
  'Chon vung Du lieu can Filter
  Set rData = Sheet3.[A3:N9601]
  'Chon Cell de gan ket qua
  Set rResult = Sheet3.[P3]
  aX = FilterArray2D(rData.Value, sFilter)
  Application.ScreenUpdating = False
  rResult.Resize(rData.Rows.Count, rData.Columns.Count).ClearContents
  rResult.Resize(UBound(aX, 1), UBound(aX, 2)) = aX
  Application.ScreenUpdating = True
  MsgBox "Time is: " & Timer - xTimer
End Sub
 

File đính kèm

  • ViDu.xlsb
    361.6 KB · Đọc: 70
Lần chỉnh sửa cuối:
Code dùng ngon lành. Cảm ơn chủ thớt!
 
Upvote 0
Anh cho em Vân hỏi với là với cách này có thể lựa chọn được cột muốn hiển thị ra kết quả không ạ ??

Em Vân cảm ơn anh ạ !
 
Upvote 0
Anh cho em Vân hỏi với là với cách này có thể lựa chọn được cột muốn hiển thị ra kết quả không ạ ??

Em Vân cảm ơn anh ạ !
Hiện tại thì chưa cho chọn cột hiển thị ra kết quả nhưng nếu muốn thêm tùy chọn này vào thì cũng không khó, hoặc là dữ liệu đầu vào mình loại trước những cột nào ko cần filter cũng được.
 
Upvote 0
Hàm nhận 2 tham số iArray (Mảng hoặc Range) và iFilter as String (điều kiện Filter)
Các điều kiện được nối với nhau bởi OR, AND, ]OR[, ]AND[
Các toán tử so sánh gồm LIKE, !LIKE, <, <=, >, >=, =, <>. Trong đó LIKE và !LIKE dùng cho Text và Text phải được đặt trong 2 dấu nháy đơn (Ví dụ: 'Giải pháp Excel')
Chuỗi Filter được viết theo cú pháp như sau: [5] > 100 AND [3] LIKE '*GPE*'
Trong đó[5] và [3] là cột cần Filter, các toán tử so sánh và các phép nối OR AND đều phải cách ra 1 khoảng trắng.
Trường hợp cần so sánh ngày thì ta phải thêm # trước ngày cần so sánh (Ví dụ: [1] > #21/12/2020)
Trường hợp có sử dụng công thức thì phải thêm ? đứng trước (Ví dụ: ?[3]*[4] > 1000000 hoặc là ?Year([1]) = 2020 hoặc là ?Left([2],3) = 'GPE')

Code trong Module
PHP:
Function FilterArray2D(ByVal iArray, ByVal iFilter As String)
  Dim x&, y&, z&, minY&, maxY&, minX&, maxX&, sF$
  Dim yI(), xF(), aX

  ReDim aX(1 To 1, 1 To 1)
  If iFilter = "" Then
    aX(1, 1) = "Không có Filter..."
  Else
    If TypeName(iArray) = "Range" Then iArray = iArray.Value
    MakeFilter iFilter
    minX = LBound(iArray, 2): maxX = UBound(iArray, 2)
    For x = 1 To maxX - minX + 1
      If InStr(1, iFilter, "[" & vbBack & vbBack & x & vbBack & vbBack & "]", vbTextCompare) > 0 Then
        z = z + 1: ReDim Preserve xF(1 To z): xF(z) = x
      End If
    Next x
    If z = 0 Then
      aX(1, 1) = "Filter sai..."
    Else
      z = 0
      minY = LBound(iArray, 1): maxY = UBound(iArray, 1)
      For y = minY To maxY
        sF = iFilter
        For x = 1 To UBound(xF)
          sF = Replace(sF, "[" & vbBack & vbBack & xF(x) & vbBack & vbBack & "]", GetValueArray(iArray(y, xF(x) - 1 + minX)), , , vbTextCompare)
        Next x
        If CheckFilter(sF) Then z = z + 1: ReDim Preserve yI(1 To z): yI(z) = y
      Next y
      If z = 0 Then
        aX(1, 1) = "Không tìm ra..."
      Else
        ReDim aX(1 To z, 1 To maxX - minX + 1)
        For y = 1 To z
          For x = 1 To maxX - minX + 1
            aX(y, x) = iArray(yI(y), x - 1 + minX)
          Next x
        Next y
      End If
    End If
  End If
  FilterArray2D = aX
End Function

Private Sub MakeFilter(iFilter As String)
  Dim xBeginText&, xEndText&, sText$, x&, aCompare

  iFilter = WorksheetFunction.Trim(iFilter)
  iFilter = Replace(iFilter, "[", "[" & vbBack & vbBack)
  iFilter = Replace(iFilter, "]", vbBack & vbBack & "]")
  iFilter = Replace(iFilter, " ", vbBack, , , vbTextCompare)
  iFilter = Replace(iFilter, vbBack & vbBack & vbBack, vbBack)

  xBeginText = InStr(1, iFilter, "'") + 1
  While xBeginText > 1
    xEndText = InStr(xBeginText, iFilter, "'") + 1
    sText = Mid(iFilter, xBeginText, xEndText - xBeginText)
    iFilter = Replace(iFilter, sText, Replace(sText, vbBack & vbBack, ""))
    iFilter = Replace(iFilter, sText, Replace(sText, vbBack, " "))
    xBeginText = InStr(xEndText, iFilter, "'") + 1
  Wend

  aCompare = Array("!like", "<=", ">=", "<>", "like", "<", ">", "=")
  For x = 0 To UBound(aCompare)
    iFilter = Replace(iFilter, vbBack & aCompare(x) & vbBack, vbBack & x & vbBack, , , vbTextCompare)
  Next x
End Sub

Private Function GetValueArray(iValue)
  Select Case TypeName(iValue)
    Case Is = "String", "Null", "Empty", "Error": GetValueArray = "'" & CStr(iValue) & "'"
    Case Else: GetValueArray = CDbl(iValue)
  End Select
End Function

Private Function CheckFilter(ByVal iFilter As String) As Boolean
  Dim aF: aF = Split(iFilter, vbBack & "]AND[" & vbBack, , vbTextCompare)
  Dim x&
  For x = LBound(aF) To UBound(aF)
    If Not CheckFilter1(aF(x)) Then Exit Function
  Next x
  CheckFilter = True
End Function

Private Function CheckFilter1(ByVal iFilter As String) As Boolean
  Dim aF: aF = Split(iFilter, vbBack & "]OR[" & vbBack, , vbTextCompare)
  Dim x&
  For x = LBound(aF) To UBound(aF)
    If CheckFilter2(aF(x)) Then CheckFilter1 = True: Exit Function
  Next x
End Function

Private Function CheckFilter2(ByVal iFilter As String) As Boolean
  Dim aF: aF = Split(iFilter, vbBack & "AND" & vbBack, , vbTextCompare)
  Dim x&
  For x = LBound(aF) To UBound(aF)
    If Not CheckFilter3(aF(x)) Then Exit Function
  Next x
  CheckFilter2 = True
End Function

Private Function CheckFilter3(ByVal iFilter As String) As Boolean
  Dim aF: aF = Split(iFilter, vbBack & "OR" & vbBack, , vbTextCompare)
  Dim x&
  For x = LBound(aF) To UBound(aF)
    If CheckFilter4(aF(x)) Then CheckFilter3 = True: Exit Function
  Next x
End Function

Private Function CheckFilter4(ByVal iFilter As String) As Boolean
  Dim aF: aF = Split(iFilter, vbBack)
  Dim u1, u2
  u1 = GetValueFilter(aF(0))
  u2 = GetValueFilter(aF(2))
  Select Case aF(1)
    Case Is = 0: CheckFilter4 = Not u1 Like u2
    Case Is = 1: CheckFilter4 = u1 <= u2
    Case Is = 2: CheckFilter4 = u1 >= u2
    Case Is = 3: CheckFilter4 = u1 <> u2
    Case Is = 4: CheckFilter4 = u1 Like u2
    Case Is = 5: CheckFilter4 = u1 < u2
    Case Is = 6: CheckFilter4 = u1 > u2
    Case Is = 7: CheckFilter4 = u1 = u2
  End Select
End Function

Private Function GetValueFilter(ByVal iString As String)
  Select Case Left$(iString, 1)
    Case Is = "'": GetValueFilter = Mid(iString, 2, Len(iString) - 2)
    Case Is = "?": GetValueFilter = Evaluate("=" & Mid(iString, 2))
    Case Is = "#": GetValueFilter = CDbl(CDate(Mid(iString, 2)))
    Case Else: GetValueFilter = Val(iString)
  End Select
End Function

Code Test
PHP:
Sub TestFilterArray2D()
  Dim sFilter$, rData As Range, rResult As Range, aX, xTimer!
  xTimer = Timer
  'Dieu kien Filter
  sFilter = "[2] like 'KH*' and [5] like 'Kg' and [8] > 0"
  'Chon vung Du lieu can Filter
  Set rData = Sheet3.[A3:N9601]
  'Chon Cell de gan ket qua
  Set rResult = Sheet3.[P3]
  aX = FilterArray2D(rData.Value, sFilter)
  Application.ScreenUpdating = False
  rResult.Resize(rData.Rows.Count, rData.Columns.Count).ClearContents
  rResult.Resize(UBound(aX, 1), UBound(aX, 2)) = aX
  Application.ScreenUpdating = True
  MsgBox "Time is: " & Timer - xTimer
End Sub
Sẽ bị lỗi nếu như cột 1 không phải là kiểu ngày tháng, nên xử lý bẫy lỗi trường hợp này
 
Upvote 0
Hình như công cụ AdvanceFilter đã không còn tác dụng sau khi có code tuyệt phẩm này
 
Upvote 0
Sẽ bị lỗi nếu như cột 1 không phải là kiểu ngày tháng, nên xử lý bẫy lỗi trường hợp này

Sửa lại 2 Function này chút xíu
PHP:
Private Function CheckFilter4(ByVal iFilter As String) As Boolean
  Dim aF: aF = Split(iFilter, vbBack)
  Dim u1, u2
  u1 = GetValueFilter(aF(0))
  u2 = GetValueFilter(aF(2))
  Select Case aF(1)
    Case Is = 0: CheckFilter4 = Not u1 Like u2
    Case Is = 1: CheckFilter4 = u1 <= u2
    Case Is = 2: CheckFilter4 = u1 >= u2
    Case Is = 3: CheckFilter4 = u1 <> u2
    Case Is = 4: CheckFilter4 = u1 Like u2
    Case Is = 5: CheckFilter4 = u1 < u2
    Case Is = 6: CheckFilter4 = u1 > u2
    Case Is = 7: CheckFilter4 = u1 = u2
  End Select
End Function

Private Function GetValueFilter(ByVal iString As String)
  Select Case Left$(iString, 1)
    Case Is = "'": GetValueFilter = Mid(iString, 2, Len(iString) - 2)
    Case Is = "?": GetValueFilter = Evaluate("=" & Mid(iString, 2))
    Case Is = "#": GetValueFilter = CDbl(CDate(Mid(iString, 2)))
    Case Else: GetValueFilter = Val(iString)
  End Select
End Function

Sửa thành như vậy
PHP:
Private Function CheckFilter4(ByVal iFilter As String) As Boolean
  Dim aF: aF = Split(iFilter, vbBack)
  Dim u1, u2
  u1 = GetValueFilter(aF(0)): If IsArray(u1) Then Exit Function
  u2 = GetValueFilter(aF(2)): If IsArray(u2) Then Exit Function
  Select Case aF(1)
    Case Is = 0: CheckFilter4 = Not u1 Like u2
    Case Is = 1: CheckFilter4 = u1 <= u2
    Case Is = 2: CheckFilter4 = u1 >= u2
    Case Is = 3: CheckFilter4 = u1 <> u2
    Case Is = 4: CheckFilter4 = u1 Like u2
    Case Is = 5: CheckFilter4 = u1 < u2
    Case Is = 6: CheckFilter4 = u1 > u2
    Case Is = 7: CheckFilter4 = u1 = u2
  End Select
End Function

Private Function GetValueFilter(ByVal iString As String)
  On Error GoTo HError
  Select Case Left$(iString, 1)
    Case Is = "'": GetValueFilter = Mid(iString, 2, Len(iString) - 2)
    Case Is = "?": GetValueFilter = Evaluate("=" & Mid(iString, 2))
    Case Is = "#": GetValueFilter = CDbl(CDate(Mid(Replace(iString, "'", ""), 2)))
    Case Else: GetValueFilter = Val(iString)
  End Select
  Exit Function
HError:
GetValueFilter = Array(1)
End Function
 
Upvote 0
Hình như công cụ AdvanceFilter đã không còn tác dụng sau khi có code tuyệt phẩm này
Đâu có sao, càng nhiều công cụ càng tốt.
Chỉ có điều là cỡ đầu óc bùn như tôi 3 tháng sau quên mất. Mà nhìn code không có chú thích thế này, 3 tháng sau quả là ngại không dám dùng.
Nếu tôi muốn dùng thì phải copy code vào thư viện riêng. Sau đó cóp luôn cái phần chỉ dẫn cách dùng ở đầu bài #1 vào làm chú thích cách sử dụng...
Về thuật toán thì quên đi. Ra đúng biết đúng, ra sai chưa chắc biết sai. Do mình không biết cách dùng, do thuật toán sai, hay do code sai?
 
Upvote 0
ko biết có siêu việt hơn cái AdvanceFilter của bill ko nữa ...
thấy code khủng quá nên làm biếng dòm .. vì có cố dòm cũng ko có hiểu nên làm biếng đó mà -0-0-0-
 
Upvote 0
Mắc mớ gì đòi hỏi nó phải hơn công cụ có sẵn của MS.
Nó chỉ đưa ra công việc mà MS không làm. Chẳng phải đấy là nhiệm vụ của addins hay sao?
Cái nó làm mà MS không làm là parse chuỗi điều kiện.
Cái mà thớt chủ quan không giải thích là luật ưu tiên toán tử: có theo luật chung hay không? tức là and ưu tiên trước or?
Và theo tôi đọc cách chỉ dẫn sử dụng thì không có phần giải thích cách dùng dấu ngoặc (). Parse chuỗi mà không có dấu ngoặc thì là thiếu sót trầm trọng.
 
Upvote 0
Hình như công cụ AdvanceFilter đã không còn tác dụng sau khi có code tuyệt phẩm này
Anh quá khen rồi, em xem đây là động lực để viết thêm được những code có ích khác sau này.
Đâu có sao, càng nhiều công cụ càng tốt.
Chỉ có điều là cỡ đầu óc bùn như tôi 3 tháng sau quên mất. Mà nhìn code không có chú thích thế này, 3 tháng sau quả là ngại không dám dùng.
Nếu tôi muốn dùng thì phải copy code vào thư viện riêng. Sau đó cóp luôn cái phần chỉ dẫn cách dùng ở đầu bài #1 vào làm chú thích cách sử dụng...
Về thuật toán thì quên đi. Ra đúng biết đúng, ra sai chưa chắc biết sai. Do mình không biết cách dùng, do thuật toán sai, hay do code sai?
Cái này sử dụng nhiều nên chưa quên được đâu anh, nhưng chắc cũng phải thêm ghi chú cho chắc ăn.
ko biết có siêu việt hơn cái AdvanceFilter của bill ko nữa ...
thấy code khủng quá nên làm biếng dòm .. vì có cố dòm cũng ko có hiểu nên làm biếng đó mà -0-0-0-
Thêm được cái nhận dữ liệu đầu vào là Array thôi anh, còn chức năng vẫn y chang
Bài đã được tự động gộp:

Mắc mớ gì đòi hỏi nó phải hơn công cụ có sẵn của MS.
Nó chỉ đưa ra công việc mà MS không làm. Chẳng phải đấy là nhiệm vụ của addins hay sao?
Cái nó làm mà MS không làm là parse chuỗi điều kiện.
Cái mà thớt chủ quan không giải thích là luật ưu tiên toán tử: có theo luật chung hay không? tức là and ưu tiên trước or?
Và theo tôi đọc cách chỉ dẫn sử dụng thì không có phần giải thích cách dùng dấu ngoặc (). Parse chuỗi mà không có dấu ngoặc thì là thiếu sót trầm trọng.
Nó sẽ ưu tiên AND trước rồi mới đến OR, nếu muốn ưu tiên OR trước thì phải sử dụng ]OR[. Trong nội dung code này thì em chỉ sử dụng 4 cấp theo mức độ ưu tiên từ cao đến thấp như sau: ]AND[ >> ]OR[ >> AND >> OR. Phần này đúng là có thiếu sót, để em cập nhật lại trong nội dung bài số 1.
 
Lần chỉnh sửa cuối:
Upvote 0
Trời, khó thật.
Tôi cứ ngỡ ][ có nghĩa là NOT
]OR[ nghĩa là NOR, và ]AND[ nghĩa là NAND
 
Upvote 0
Trời, khó thật.
Tôi cứ ngỡ ][ có nghĩa là NOT
]OR[ nghĩa là NOR, và ]AND[ nghĩa là NAND
Lúc đầu em chỉ có AND với OR thôi. Nhưng khi gặp trường hợp (A AND B) OR (C AND D) thì em mới nghĩ đến việc thêm ]OR[ vào. Lý do em để cặp ][ là để ... gõ cho nhanh :D
 
Upvote 0
Bây giờ bạn biện chứng cho biết, tại sao không dùng DAO.Recorset để filter?
Ví dụ tôi vẫn dùng cái giao diện (interface) như bạn tức là nạp môt mảng, và một filter string. Nhưng bên trong code, tôi dùng Advanced Filter hoặc Recordset filter?
 
Upvote 0
Bây giờ bạn biện chứng cho biết, tại sao không dùng DAO.Recorset để filter?
Ví dụ tôi vẫn dùng cái giao diện (interface) như bạn tức là nạp môt mảng, và một filter string. Nhưng bên trong code, tôi dùng Advanced Filter hoặc Recordset filter?
Thứ nhất là vì Recordset đã có nhiều bài hướng dẫn trên diễn đàn, Advanced Filter cũng vậy nên nếu em viết lại thì xem như thừa vì cũng không có gì mới so với các bài viết trước. Thứ hai là giải thuật Filter Array trên diễn đàn cũng có nhưng đã rất lâu và em muốn viết 1 giải thuật khác tốt hơn. Chỉ như vậy thôi.
 
Upvote 0
Web KT

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

Back
Top Bottom