Nhờ giúp chuyển từ sub lọc dữ liệu thành function (1 người xem)

Liên hệ QC

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

ngocleasing

Thành viên hoạt động
Tham gia
17/10/08
Bài viết
102
Được thích
5
Bác nào chuyển giúp cái thủ tục sau thành hàm đươc không ạ

Public Sub MyFilter()
Dim lngStart As Long, lngEnd As Long
lngStart = Range("E1").Value 'assume this is the start date
lngEnd = Range("E2").Value 'assume this is the end date
Range("C1:C13").AutoFilter field:=1, _
Criteria1:=">=" & lngStart, _
Operator:=xlAnd, _
Criteria2:="<=" & lngEnd
End Sub
 
Bác nào chuyển giúp cái thủ tục sau thành hàm đươc không ạ

Public Sub MyFilter()
Dim lngStart As Long, lngEnd As Long
lngStart = Range("E1").Value 'assume this is the start date
lngEnd = Range("E2").Value 'assume this is the end date
Range("C1:C13").AutoFilter field:=1, _
Criteria1:=">=" & lngStart, _
Operator:=xlAnd, _
Criteria2:="<=" & lngEnd
End Sub
đổi mỗi chữ "Sub" thành chữ "Function" là OK
 
Upvote 0
Upvote 0
Hàm filter chỉ có trong excel 360 mà bác, em dùng excel 2019 ạ
Nếu không có hàm Filter và đang xài 2019
Mã:
Function MyFilter(DataRng As Range, StartD As Date, EndD As Date, DCol As Long)
Dim DataArr(), ResultArr(), RwsCount As Long, ColCount As Long
DataArr = DataRng.Value
RwsCount = UBound(DataArr, 1)
ColCount = UBound(DataArr, 2)
For i = 1 To RwsCount
    If DataArr(i, DCol) >= StartD And DataArr(i, DCol) <= EndD Then
        k = k + 1
        ReDim Preserve ResultArr(1 To ColCount, 1 To k)
        For j = 1 To ColCount
            ResultArr(j, k) = DataArr(i, j)
        Next
    End If
Next
MyFilter = Application.Transpose(ResultArr)
End Function

Dcol là thứ tự của cột chứa ngày.
H2 =myfilter(A2:C16,F1,F2,3)

1676384898345.png
 
Upvote 0
Nếu không có hàm Filter và đang xài 2019
Mã:
Function MyFilter(DataRng As Range, StartD As Date, EndD As Date, DCol As Long)
Dim DataArr(), ResultArr(), RwsCount As Long, ColCount As Long
DataArr = DataRng.Value
RwsCount = UBound(DataArr, 1)
ColCount = UBound(DataArr, 2)
For i = 1 To RwsCount
    If DataArr(i, DCol) >= StartD And DataArr(i, DCol) <= EndD Then
        k = k + 1
        ReDim Preserve ResultArr(1 To ColCount, 1 To k)
        For j = 1 To ColCount
            ResultArr(j, k) = DataArr(i, j)
        Next
    End If
Next
MyFilter = Application.Transpose(ResultArr)
End Function

Dcol là thứ tự của cột chứa ngày.
H2 =myfilter(A2:C16,F1,F2,3)

View attachment 286495
Cảm ơn bác nhiều, nhưng nếu em dùng dấu Phẩy (,) để cách giữa các tham số hàm thì máy báo lỗi
1676423973775.png

Còn nếu em thay dấu Phẩy (,) bằng dấu Chấm phẩy (;) thì kết quả chỉ ra không đúng bác ah
1676424077847.png
 
Upvote 0
Còn nếu em thay dấu Phẩy (,) bằng dấu Chấm phẩy (;) thì kết quả chỉ ra không đúng bác ah
Chả lẽ 2019 không ra được kết quả mảng?
Thử: tô khối H2:J12 gõ công thức rồi Ctrl shift Enter
Xài: H2 =Index(MyFilter($A$2:$C$12,$F$1,$F$2,3),Row(B1),Column(B1)), fill ngang và fill dọc đến khi lỗi thì ngưng
 
Upvote 0
Chả lẽ 2019 không ra được kết quả mảng?
Thử: tô khối H2:J12 gõ công thức rồi Ctrl shift Enter
Xài: H2 =Index(MyFilter($A$2:$C$12,$F$1,$F$2,3),Row(B1),Column(B1)), fill ngang và fill dọc đến khi lỗi thì ngưng

Nếu gõ vào dấu phẩu thì báo lỗi như sau bác ah
1676425066524.png

Còn nếu thay dấu phẩy bằng dấu chấm phẩy trong công thức và gõ xong ấn enter ctr shift, xong kéo ngang, kéo dọc thì có kết quả như sau bác ah
1676425358594.png
 
Upvote 0
Nếu gõ vào dấu phẩu thì báo lỗi như sau bác ah
Còn nếu thay dấu phẩy bằng dấu chấm phẩy trong công thức và gõ xong ấn enter ctr shift, xong kéo ngang, kéo dọc thì có kết quả như sau bác ah
Bạn đừng bao giờ thử dấu phảy trên máy bạn nữa, ai đưa công thức cho bạn dấu phảy thì phải tự biết mà đổi, khỏi kêu ca.
Bạn đọc kỹ khi nào tôi nói Ctrl shift enter, khi nào không bảo. Và đọc cả chỗ "khi nào lỗi thì ngưng"
---
Sửa lại chút xíu:

H2 =Index(MyFilter($A$2:$C$12,$F$1,$F$2,3),Row(A1),Column(A1))
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn đừng bao giờ thử dấu phảy trên máy bạn nữa, ai đưa công thức cho bạn dấu phảy thì phải tự biết mà đổi, khỏi kêu ca.
Bạn đọc kỹ khi nào tôi nói Ctrl shift enter, khi nào không bảo. Và đọc cả chỗ "khi nào lỗi thì ngưng"
Vâng có thể em chưa hiểu rõ ý bác lắm, nhưng em đang làm là bôi khối H2:J12, xong gõ công thức, tiếp đó là nhấn tổ hợp phím ctr shift enter, xong đặt chuột vào góc cuối của khối kéo ngang kéo dọc thì ra kết quả sau ạ
 

File đính kèm

  • 1676426870581.png
    1676426870581.png
    164 KB · Đọc: 7
Upvote 0
Vâng có thể em chưa hiểu rõ ý bác lắm, nhưng em đang làm là bôi khối H2:J12, xong gõ công thức, tiếp đó là nhấn tổ hợp phím ctr shift enter, xong đặt chuột vào góc cuối của khối kéo ngang kéo dọc thì ra kết quả sau ạ
Bạn đọc lại thật kỹ lần nữa. Phải làm 2 lần, 1 lần thử và 1 lần xài. Hai cái riêng rẽ xóa đi làm lại.
Sửa lại chút xíu:

Xài: H2 =Index(MyFilter($A$2:$C$12,$F$1,$F$2,3),Row(A1),Column(A1))
 
Upvote 0
Bạn đừng bao giờ thử dấu phảy trên máy bạn nữa, ai đưa công thức cho bạn dấu phảy thì phải tự biết mà đổi, khỏi kêu ca.
Bạn đọc kỹ khi nào tôi nói Ctrl shift enter, khi nào không bảo. Và đọc cả chỗ "khi nào lỗi thì ngưng"
---
Sửa lại chút xíu:

H2 =Index(MyFilter($A$2:$C$12,$F$1,$F$2,3),Row(A1),Column(A1))
Kết quả như sau bác ạ
1676427323873.png
 
Upvote 0
Kết quả như sau bác ạ
Nhìn hình thì thấy bạn không chịu đọc lại. Bác ấy viết rõ rằng: Làm 2 lần xóa đi làm lại chứ không phải làm 1 lần 2 bước.
Lần 1: tô khối, gõ công thức, ctrl shift enter. Xem kết quả.
Lần 2: tốt nhất là làm chỗ khác. Nếu làm tại H2 thì phải xóa kết quả lần 1 đi. Gõ công thức 1 ô, enter, không ctrl shift gì sất. Rồi mới fill ngang fill dọc.
Bác ấy viết đến 3 lần là quá kiên nhẫn rồi đó.
 
Upvote 0
Bạn đọc lại thật kỹ lần nữa. Phải làm 2 lần, 1 lần thử và 1 lần xài. Hai cái riêng rẽ xóa đi làm lại.
Sửa lại chút xíu:

Xài: H2 =Index(MyFilter($A$2:$C$12,$F$1,$F$2,3),Row(A1),Column(A1))
Kết quả lần thử:
1676427683098.png
Kết quả lần xài
1676427814101.png
Thế là cả hai lần đều ngon bác ạ. Cảm ơn bác nhiều, em muốn chút nữa giả sử em cần lọc ra cột D không phải là SG thì sửa cái code VBA trên như thế
nào bác nhỉ
1676428092947.png
 

File đính kèm

  • 1676427606900.png
    1676427606900.png
    140.2 KB · Đọc: 0
Upvote 0
Thế là cả hai lần đều ngon bác ạ. Cảm ơn bác nhiều, em muốn chút nữa giả sử em cần lọc ra cột D không phải là SG thì sửa cái code VBA trên như thế
nào bác nhỉ
Không ai viết hàm chung được đâu. Lúc thì khác SG, lúc thì bằng HCM, lúc thì trong khoảng giữa 2 ngày, lúc thì trước ngày A, lúc thì sau ngày B. Mỗi trường hợp phải viết 1 hàm á hả?
Các trường hợp lung tung này mà không có hàm Filter của 365 thì phải dùng Advanced filter, VBA thì viết Sub, không dùng function.
 
Upvote 0
Không ai viết hàm chung được đâu. Lúc thì khác SG, lúc thì bằng HCM, lúc thì trong khoảng giữa 2 ngày, lúc thì trước ngày A, lúc thì sau ngày B. Mỗi trường hợp phải viết 1 hàm á hả?
Các trường hợp lung tung này mà không có hàm Filter của 365 thì phải dùng Advanced filter, VBA thì viết Sub, không dùng function.
Ý em là thêm 1 cột để loại 1 yếu tố, như trên thì cần loại yếu tố là SG chẳng hạn, còn yếu tố khác thế nào thì em sẽ tự sửa vào trong VBA mà. Còn không cần thay đổi gì thêm ạ
 
Upvote 0
Ý em là thêm 1 cột để loại 1 yếu tố, như trên thì cần loại yếu tố là SG chẳng hạn, còn yếu tố khác thế nào thì em sẽ tự sửa vào trong VBA mà. Còn không cần thay đổi gì thêm ạ
Tôi không tin bạn tự sửa trong VBA được. Xài trên sheet còn lúng ta lúng túng, chuyển từ sub sang function thì không biết gì.
 
Upvote 0
Tôi không tin bạn tự sửa trong VBA được. Xài trên sheet còn lúng ta lúng túng, chuyển từ sub sang function thì không biết gì.
hehe, em tưởng chỉ cần sửa chữ SG thành HCM thui ạ, hay là bác cho cái chuẩn men luôn là vẫn cái hàm trên nhưng thêm 1 tham số loại 1 yếu tố trong cột D chẳng hạn!
 
Upvote 0
Ý em là thêm 1 cột để loại 1 yếu tố, như trên thì cần loại yếu tố là SG chẳng hạn, còn yếu tố khác thế nào thì em sẽ tự sửa vào trong VBA mà. Còn không cần thay đổi gì thêm ạ
Sub thì đơn giản thế này:
Mã:
Sub AdvFilter()
    Range("A1:D16").AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=Range( _
        "M1:O2"), CopyToRange:=Range("Q1:T1"), Unique:=False
End Sub
Công thức M2 =">="&F1
N2 ="<="&F2
O2 gõ tay

1676429697497.png
 
Upvote 0
Cảm
Sub thì đơn giản thế này:
Mã:
Sub AdvFilter()
    Range("A1:D16").AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=Range( _
        "M1:O2"), CopyToRange:=Range("Q1:T1"), Unique:=False
End Sub
Công thức M2 =">="&F1
N2 ="<="&F2
O2 gõ tay

View attachment 286519
Cảm ơn bác nhiều, tuy nhiên em muốn hàm ạ. Vì bảng tính em có nhiều vùng cần lọc theo kiểu như cái hàm, nên làm thành thủ tục không tiện ạ!!
 
Upvote 0
Cảm ơn bác nhiều, tuy nhiên em muốn hàm ạ. Vì bảng tính em có nhiều vùng cần lọc theo kiểu như cái hàm, nên làm thành thủ tục không tiện ạ!!
Này thì hàm.
Đòi thêm nữa là không có đâu nhá. Tự sửa.
Mã:
Function MyFilter(DataRng As Range, StartD As Date, EndD As Date, DCol As Long, Place As String, PlCol As Long)
Dim DataArr(), ResultArr(), RwsCount As Long, ColCount As Long
DataArr = DataRng.Value
RwsCount = UBound(DataArr, 1)
ColCount = UBound(DataArr, 2)
For i = 1 To RwsCount
    If DataArr(i, DCol) >= StartD And DataArr(i, DCol) <= EndD _
    And DataArr(i, PlCol) <> Place Then
        k = k + 1
        ReDim Preserve ResultArr(1 To ColCount, 1 To k)
        For j = 1 To ColCount
            ResultArr(j, k) = DataArr(i, j)
        Next
    End If
Next
MyFilter = Application.Transpose(ResultArr)
End Function

1676431220126.png
 
Upvote 0
Này thì hàm.
Đòi thêm nữa là không có đâu nhá. Tự sửa.
Mã:
Function MyFilter(DataRng As Range, StartD As Date, EndD As Date, DCol As Long, Place As String, PlCol As Long)
Dim DataArr(), ResultArr(), RwsCount As Long, ColCount As Long
DataArr = DataRng.Value
RwsCount = UBound(DataArr, 1)
ColCount = UBound(DataArr, 2)
For i = 1 To RwsCount
    If DataArr(i, DCol) >= StartD And DataArr(i, DCol) <= EndD _
    And DataArr(i, PlCol) <> Place Then
        k = k + 1
        ReDim Preserve ResultArr(1 To ColCount, 1 To k)
        For j = 1 To ColCount
            ResultArr(j, k) = DataArr(i, j)
        Next
    End If
Next
MyFilter = Application.Transpose(ResultArr)
End Function

View attachment 286521
Cảm ơn bác nhiều, phiền bác quá a!
 
Upvote 0
Lâu quá rồi mới thấy sư phụ và sư nương ở chung 1 phòng.
:))
 
Upvote 0
Này thì hàm.
Đòi thêm nữa là không có đâu nhá. Tự sửa.
Mã:
Function MyFilter(DataRng As Range, StartD As Date, EndD As Date, DCol As Long, Place As String, PlCol As Long)
Dim DataArr(), ResultArr(), RwsCount As Long, ColCount As Long
DataArr = DataRng.Value
RwsCount = UBound(DataArr, 1)
ColCount = UBound(DataArr, 2)
For i = 1 To RwsCount
    If DataArr(i, DCol) >= StartD And DataArr(i, DCol) <= EndD _
    And DataArr(i, PlCol) <> Place Then
        k = k + 1
        ReDim Preserve ResultArr(1 To ColCount, 1 To k)
        For j = 1 To ColCount
            ResultArr(j, k) = DataArr(i, j)
        Next
    End If
Next
MyFilter = Application.Transpose(ResultArr)
End Function

View attachment 286521
Bác ui, cai này khi xóa data cũ đi, paste data mới vào thì kết quả trả về bị lõi luôn ạ!
 
Upvote 0
Bác ui, cai này khi xóa data cũ đi, paste data mới vào thì kết quả trả về bị lõi luôn ạ!
Các trường hợp có thể gây ra lỗi khi copy paste data mới:
- Dữ liệu mới không đúng thứ tự cột: Ngày không phải C, Place không phải D, khi viết công thức không biết truyền tham số
- Dữ liệu ngày không đúng chuẩn
Theo quy ước thì:
Lỗi do sử dụng công thức sai: ráng chịu,
Lỗi do dữ liệu sai: rang chịu,
Lỗi do hàm chưa tổng quát (nếu có): tự sửa.
Lỗi hàm sai: tôi sửa. Nhưng chắc chắn không sai vì tôi đã test kỹ.
 
Upvote 0
Các trường hợp có thể gây ra lỗi khi copy paste data mới:
- Dữ liệu mới không đúng thứ tự cột: Ngày không phải C, Place không phải D, khi viết công thức không biết truyền tham số
- Dữ liệu ngày không đúng chuẩn
Theo quy ước thì:
Lỗi do sử dụng công thức sai: ráng chịu,
Lỗi do dữ liệu sai: rang chịu,
Lỗi do hàm chưa tổng quát (nếu có): tự sửa.
Lỗi hàm sai: tôi sửa. Nhưng chắc chắn không sai vì tôi đã test kỹ.
cảm ơn bác nhiều nhé
 
Upvote 0
Tét kỹ mà hổng biết hàm Transpose có tới 2 giới hạn cùi bắp lận.
Dính giới hạn là lăn ra ngỏm củ tỏi chứ chưa kịp chạy sai. :)
 
Upvote 0
@ngocleasing
Bác có thể sử dụng hàm AutoFilter chính của Excel thông qua callback Function dưới đây.

=AutoFilter(C1:C13, 1,">="&E1,afoAnd(),"<="&E2)

Hoặc mảng:
=AutoFilter(C1:C13, 1,{1;5;6;7},afoAnd())

(Sao chép mã vào một Module mới)
JavaScript:
Option Explicit

Private Type TypeArguments
  Action As Long
  Formula As String
  Cells As Excel.Range
  Caller As Range
  field As String
  Criteria1 As Variant
  operator As XlAutoFilterOperator
  Criteria2 As Variant
  VisibleDropDown As Boolean
  SubField As Boolean
  title As String
End Type

#If VBA7 Then
  Private Declare PtrSafe Function SetTimer Lib "USER32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr, ByVal uElapse As LongPtr, ByVal lpTimerFunc As LongPtr) As Long
  Private Declare PtrSafe Function KillTimer Lib "USER32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr) As Long
#Else
  Private Declare Function SetTimer Lib "user32" (ByVal HWnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
  Private Declare Function KillTimer Lib "user32" (ByVal HWnd As Long, ByVal nIDEvent As Long) As Long
#End If
''///////////////////////////////////////////////////////
Private Works() As TypeArguments
Function afoAnd(): afoAnd= xlAnd: End Function
Function afoBottom10Items(): afoBottom10Items = xlBottom10Items: End Function
Function afoBottom10Percent(): afoBottom10Percent = xlBottom10Percent: End Function
Function afoFilterAutomaticFontColor(): afoFilterAutomaticFontColor = xlFilterAutomaticFontColor: End Function
Function afoFilterCellColor(): afoFilterCellColor = xlFilterCellColor: End Function
Function afoFilterDynamic(): afoFilterDynamic = xlFilterDynamic: End Function
Function afoFilterFontColor(): afoFilterFontColor = xlFilterFontColor: End Function
Function afoFilterIcon(): afoFilterIcon = xlFilterIcon: End Function
Function afoFilterNoFill(): afoFilterNoFill = xlFilterNoFill: End Function
Function afoFilterNoicon(): afoFilterNoicon = xlFilterNoIcon: End Function
Function afoFilterValues(): afoFilterValues = xlFilterValues: End Function
Function afoOr(): afoOr = xlOr: End Function
Function afoTop10Items(): afoTop10Items = xlTop10Items: End Function
Function afoTop10Percent(): afoTop10Percent = xlTop10Percent: End Function

Function AutoFilter( _
             ByVal Cells As Range, _
    Optional field As String = vbNullChar, _
    Optional Criteria1 As Variant, _
    Optional operator As XlAutoFilterOperator = 1, _
    Optional Criteria2 As Variant, _
    Optional VisibleDropDown As Boolean = True, _
    Optional SubField As Boolean, _
    Optional title As String = vbNullChar)
 
  On Error Resume Next
  If Cells.Worksheet.ProtectContents = True Then
    AutoFilter = "[SheetProtected]"
    Exit Function
  End If
 
  Dim r As Object, k%, i%, s$, F$
  s = Cells.Address(0, 0)
  Set r = Application.ThisCell
  F = r.Formula
  If title <> vbNullChar Then AutoFilter = title
  k = UBound(Works): k = k + 1
  ReDim Preserve Works(1 To k)
  With Works(k)
    Set .Caller = r
    Set .Cells = Cells
    .Formula = F
n:
    .Action = 0
    .field = field
    .Criteria1 = Criteria1
    .operator = operator
    .Criteria2 = Criteria2
    .SubField = SubField
    .VisibleDropDown = VisibleDropDown
  End With
  Set r = Nothing
  Call SetTimer(Application.hwnd, 1111, 0, AddressOf S_AutoFilter_callback)
  On Error GoTo 0
End Function


#If VBA7 And Win64 Then
Private Sub S_AutoFilter_callback(ByVal hwnd^, ByVal uMsg&, ByVal nIDEvent&, ByVal dwTimer&)
#Else
Private Sub S_AutoFilter_callback(ByVal hwnd&, ByVal uMsg&, ByVal nIDEvent&, ByVal dwTimer&)
#End If
  On Error Resume Next
  Call KillTimer(hwnd, nIDEvent)
  S_AutoFilter_working
End Sub

Private Sub S_AutoFilter_working()
  On Error Resume Next
  Dim ub As Integer, a As Object, b As TypeArguments, i&, k&, su As Boolean, Ac As Boolean, v As Variant, rg As Range, cell
  ub = UBound(Works)
  Dim s$, o, sh
  For i = 1 To ub
    b = Works(i)
    Select Case b.Action
    Case 0
      If b.Caller.Formula = b.Formula Then
'        If a Is Nothing Then
'          Set a = Application
'          su = a.ScreenUpdating: If su Then a.ScreenUpdating = False
'          Ac = a.Calculation = xlCalculationAutomatic: If Ac Then a.Calculation = xlCalculationManual
'        End If
        Set rg = b.Cells: Set sh = rg.Parent
        If Not sh.AutoFilter Is Nothing Then
          sh.AutoFilter.ShowAllData
        End If
        If b.Criteria2 = Empty Then
          If b.SubField = Empty Then
            b.Cells.AutoFilter field:=b.field, Criteria1:=b.Criteria1, operator:=b.operator, VisibleDropDown:=b.VisibleDropDown
          Else
            b.Cells.AutoFilter field:=b.field, Criteria1:=b.Criteria1, operator:=b.operator, Criteria2:=b.Criteria2, VisibleDropDown:=b.VisibleDropDown, SubField:=b.SubField
          End If
        Else
          If b.SubField = Empty Then
            b.Cells.AutoFilter field:=b.field, Criteria1:=b.Criteria1, operator:=b.operator, Criteria2:=b.Criteria2, VisibleDropDown:=b.VisibleDropDown
          Else
            b.Cells.AutoFilter field:=b.field, Criteria1:=b.Criteria1, operator:=b.operator, Criteria2:=b.Criteria2, VisibleDropDown:=b.VisibleDropDown, SubField:=b.SubField
          End If
        End If
        Works(i).Action = 1
      End If
    End Select
    k = k + 1
n:
  Next
  Erase Works
'  If Not a Is Nothing Then
'    If su And a.ScreenUpdating <> su Then a.ScreenUpdating = su
'    If Ac And xlCalculationAutomatic <> a.Calculation Then a.Calculation = Ac
'    Set a = Nothing
'  End If
  On Error GoTo 0
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
@ngocleasing
Bác có thể sử dụng hàm AutoFilter chính của Excel thông qua callback Function dưới đây.

=AutoFilter(C1:C13, 1,">="&E1,afoAnd(),"<="&E2)

Hoặc mảng:
=AutoFilter(C1:C13, 1,{1;5;6;7},afoAnd())

(Sao chép mã vào một Module mới)
JavaScript:
Option Explicit

Private Type TypeArguments
  Action As Long
  Formula As String
  Cells As Excel.Range
  Caller As Range
  field As String
  Criteria1 As Variant
  operator As XlAutoFilterOperator
  Criteria2 As Variant
  VisibleDropDown As Boolean
  SubField As Boolean
  title As String
End Type

#If VBA7 Then
  Private Declare PtrSafe Function SetTimer Lib "USER32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr, ByVal uElapse As LongPtr, ByVal lpTimerFunc As LongPtr) As Long
  Private Declare PtrSafe Function KillTimer Lib "USER32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr) As Long
#Else
  Private Declare Function SetTimer Lib "user32" (ByVal HWnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
  Private Declare Function KillTimer Lib "user32" (ByVal HWnd As Long, ByVal nIDEvent As Long) As Long
#End If
''///////////////////////////////////////////////////////
Private Works() As TypeArguments
Function afoAnd(): afoAnd= xlAnd: End Function
Function afoBottom10Items(): afoBottom10Items = xlBottom10Items: End Function
Function afoBottom10Percent(): afoBottom10Percent = xlBottom10Percent: End Function
Function afoFilterAutomaticFontColor(): afoFilterAutomaticFontColor = xlFilterAutomaticFontColor: End Function
Function afoFilterCellColor(): afoFilterCellColor = xlFilterCellColor: End Function
Function afoFilterDynamic(): afoFilterDynamic = xlFilterDynamic: End Function
Function afoFilterFontColor(): afoFilterFontColor = xlFilterFontColor: End Function
Function afoFilterIcon(): afoFilterIcon = xlFilterIcon: End Function
Function afoFilterNoFill(): afoFilterNoFill = xlFilterNoFill: End Function
Function afoFilterNoicon(): afoFilterNoicon = xlFilterNoIcon: End Function
Function afoFilterValues(): afoFilterValues = xlFilterValues: End Function
Function afoOr(): afoOr = xlOr: End Function
Function afoTop10Items(): afoTop10Items = xlTop10Items: End Function
Function afoTop10Percent(): afoTop10Percent = xlTop10Percent: End Function

Function AutoFilter( _
             ByVal Cells As Range, _
    Optional field As String = vbNullChar, _
    Optional Criteria1 As Variant, _
    Optional operator As XlAutoFilterOperator = 1, _
    Optional Criteria2 As Variant, _
    Optional VisibleDropDown As Boolean = True, _
    Optional SubField As Boolean, _
    Optional title As String = vbNullChar)
 
  On Error Resume Next
  If Cells.Worksheet.ProtectContents = True Then
    AutoFilter = "[SheetProtected]"
    Exit Function
  End If
 
  Dim r As Object, k%, i%, s$, F$
  s = Cells.Address(0, 0)
  Set r = Application.ThisCell
  F = r.Formula
  If title <> vbNullChar Then AutoFilter = title
  k = UBound(Works): k = k + 1
  ReDim Preserve Works(1 To k)
  With Works(k)
    Set .Caller = r
    Set .Cells = Cells
    .Formula = F
n:
    .Action = 0
    .field = field
    .Criteria1 = Criteria1
    .operator = operator
    .Criteria2 = Criteria2
    .SubField = SubField
    .VisibleDropDown = VisibleDropDown
  End With
  Set r = Nothing
  Call SetTimer(Application.hwnd, 1111, 0, AddressOf S_AutoFilter_callback)
  On Error GoTo 0
End Function


#If VBA7 And Win64 Then
Private Sub S_AutoFilter_callback(ByVal hwnd^, ByVal uMsg&, ByVal nIDEvent&, ByVal dwTimer&)
#Else
Private Sub S_AutoFilter_callback(ByVal hwnd&, ByVal uMsg&, ByVal nIDEvent&, ByVal dwTimer&)
#End If
  On Error Resume Next
  Call KillTimer(hwnd, nIDEvent)
  S_AutoFilter_working
End Sub

Private Sub S_AutoFilter_working()
  On Error Resume Next
  Dim ub As Integer, a As Object, b As TypeArguments, i&, k&, su As Boolean, Ac As Boolean, v As Variant, rg As Range, cell
  ub = UBound(Works)
  Dim s$, o
  For i = 1 To ub
    b = Works(i)
    Select Case b.Action
    Case 0
      If b.Caller.Formula = b.Formula Then
'        If a Is Nothing Then
'          Set a = Application
'          su = a.ScreenUpdating: If su Then a.ScreenUpdating = False
'          Ac = a.Calculation = xlCalculationAutomatic: If Ac Then a.Calculation = xlCalculationManual
'        End If
        Set rg = b.Cells: Set sh = rg.Parent
        If Not sh.AutoFilter Is Nothing Then
          sh.AutoFilter.ShowAllData
        End If
        If b.Criteria2 = Empty Then
          If b.SubField = Empty Then
            b.Cells.AutoFilter field:=b.field, Criteria1:=b.Criteria1, operator:=b.operator, VisibleDropDown:=b.VisibleDropDown
          Else
            b.Cells.AutoFilter field:=b.field, Criteria1:=b.Criteria1, operator:=b.operator, Criteria2:=b.Criteria2, VisibleDropDown:=b.VisibleDropDown, SubField:=b.SubField
          End If
        Else
          If b.SubField = Empty Then
            b.Cells.AutoFilter field:=b.field, Criteria1:=b.Criteria1, operator:=b.operator, Criteria2:=b.Criteria2, VisibleDropDown:=b.VisibleDropDown
          Else
            b.Cells.AutoFilter field:=b.field, Criteria1:=b.Criteria1, operator:=b.operator, Criteria2:=b.Criteria2, VisibleDropDown:=b.VisibleDropDown, SubField:=b.SubField
          End If
        End If
        Works(i).Action = 1
      End If
    End Select
    k = k + 1
n:
  Next
  Erase Works
'  If Not a Is Nothing Then
'    If su And a.ScreenUpdating <> su Then a.ScreenUpdating = su
'    If Ac And xlCalculationAutomatic <> a.Calculation Then a.Calculation = Ac
'    Set a = Nothing
'  End If
  On Error GoTo 0
End Sub
Cảm ơn bác, toàn lúc khó nhất thì được gặp bác, nhưng để về em xem lại chưa hiểu dùng như thế nào hehe
 
Upvote 0
@ngocleasing
Bác có thể sử dụng hàm AutoFilter chính của Excel thông qua callback Function dưới đây.

=AutoFilter(C1:C13, 1,">="&E1,afoAnd(),"<="&E2)

Hoặc mảng:
=AutoFilter(C1:C13, 1,{1;5;6;7},afoAnd())

(Sao chép mã vào một Module mới)
JavaScript:
Option Explicit

Private Type TypeArguments
  Action As Long
  Formula As String
  Cells As Excel.Range
  Caller As Range
  field As String
  Criteria1 As Variant
  operator As XlAutoFilterOperator
  Criteria2 As Variant
  VisibleDropDown As Boolean
  SubField As Boolean
  title As String
End Type

#If VBA7 Then
  Private Declare PtrSafe Function SetTimer Lib "USER32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr, ByVal uElapse As LongPtr, ByVal lpTimerFunc As LongPtr) As Long
  Private Declare PtrSafe Function KillTimer Lib "USER32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr) As Long
#Else
  Private Declare Function SetTimer Lib "user32" (ByVal HWnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
  Private Declare Function KillTimer Lib "user32" (ByVal HWnd As Long, ByVal nIDEvent As Long) As Long
#End If
''///////////////////////////////////////////////////////
Private Works() As TypeArguments
Function afoAnd(): afoAnd= xlAnd: End Function
Function afoBottom10Items(): afoBottom10Items = xlBottom10Items: End Function
Function afoBottom10Percent(): afoBottom10Percent = xlBottom10Percent: End Function
Function afoFilterAutomaticFontColor(): afoFilterAutomaticFontColor = xlFilterAutomaticFontColor: End Function
Function afoFilterCellColor(): afoFilterCellColor = xlFilterCellColor: End Function
Function afoFilterDynamic(): afoFilterDynamic = xlFilterDynamic: End Function
Function afoFilterFontColor(): afoFilterFontColor = xlFilterFontColor: End Function
Function afoFilterIcon(): afoFilterIcon = xlFilterIcon: End Function
Function afoFilterNoFill(): afoFilterNoFill = xlFilterNoFill: End Function
Function afoFilterNoicon(): afoFilterNoicon = xlFilterNoIcon: End Function
Function afoFilterValues(): afoFilterValues = xlFilterValues: End Function
Function afoOr(): afoOr = xlOr: End Function
Function afoTop10Items(): afoTop10Items = xlTop10Items: End Function
Function afoTop10Percent(): afoTop10Percent = xlTop10Percent: End Function

Function AutoFilter( _
             ByVal Cells As Range, _
    Optional field As String = vbNullChar, _
    Optional Criteria1 As Variant, _
    Optional operator As XlAutoFilterOperator = 1, _
    Optional Criteria2 As Variant, _
    Optional VisibleDropDown As Boolean = True, _
    Optional SubField As Boolean, _
    Optional title As String = vbNullChar)
 
  On Error Resume Next
  If Cells.Worksheet.ProtectContents = True Then
    AutoFilter = "[SheetProtected]"
    Exit Function
  End If
 
  Dim r As Object, k%, i%, s$, F$
  s = Cells.Address(0, 0)
  Set r = Application.ThisCell
  F = r.Formula
  If title <> vbNullChar Then AutoFilter = title
  k = UBound(Works): k = k + 1
  ReDim Preserve Works(1 To k)
  With Works(k)
    Set .Caller = r
    Set .Cells = Cells
    .Formula = F
n:
    .Action = 0
    .field = field
    .Criteria1 = Criteria1
    .operator = operator
    .Criteria2 = Criteria2
    .SubField = SubField
    .VisibleDropDown = VisibleDropDown
  End With
  Set r = Nothing
  Call SetTimer(Application.hwnd, 1111, 0, AddressOf S_AutoFilter_callback)
  On Error GoTo 0
End Function


#If VBA7 And Win64 Then
Private Sub S_AutoFilter_callback(ByVal hwnd^, ByVal uMsg&, ByVal nIDEvent&, ByVal dwTimer&)
#Else
Private Sub S_AutoFilter_callback(ByVal hwnd&, ByVal uMsg&, ByVal nIDEvent&, ByVal dwTimer&)
#End If
  On Error Resume Next
  Call KillTimer(hwnd, nIDEvent)
  S_AutoFilter_working
End Sub

Private Sub S_AutoFilter_working()
  On Error Resume Next
  Dim ub As Integer, a As Object, b As TypeArguments, i&, k&, su As Boolean, Ac As Boolean, v As Variant, rg As Range, cell
  ub = UBound(Works)
  Dim s$, o
  For i = 1 To ub
    b = Works(i)
    Select Case b.Action
    Case 0
      If b.Caller.Formula = b.Formula Then
'        If a Is Nothing Then
'          Set a = Application
'          su = a.ScreenUpdating: If su Then a.ScreenUpdating = False
'          Ac = a.Calculation = xlCalculationAutomatic: If Ac Then a.Calculation = xlCalculationManual
'        End If
        Set rg = b.Cells: Set sh = rg.Parent
        If Not sh.AutoFilter Is Nothing Then
          sh.AutoFilter.ShowAllData
        End If
        If b.Criteria2 = Empty Then
          If b.SubField = Empty Then
            b.Cells.AutoFilter field:=b.field, Criteria1:=b.Criteria1, operator:=b.operator, VisibleDropDown:=b.VisibleDropDown
          Else
            b.Cells.AutoFilter field:=b.field, Criteria1:=b.Criteria1, operator:=b.operator, Criteria2:=b.Criteria2, VisibleDropDown:=b.VisibleDropDown, SubField:=b.SubField
          End If
        Else
          If b.SubField = Empty Then
            b.Cells.AutoFilter field:=b.field, Criteria1:=b.Criteria1, operator:=b.operator, Criteria2:=b.Criteria2, VisibleDropDown:=b.VisibleDropDown
          Else
            b.Cells.AutoFilter field:=b.field, Criteria1:=b.Criteria1, operator:=b.operator, Criteria2:=b.Criteria2, VisibleDropDown:=b.VisibleDropDown, SubField:=b.SubField
          End If
        End If
        Works(i).Action = 1
      End If
    End Select
    k = k + 1
n:
  Next
  Erase Works
'  If Not a Is Nothing Then
'    If su And a.ScreenUpdating <> su Then a.ScreenUpdating = su
'    If Ac And xlCalculationAutomatic <> a.Calculation Then a.Calculation = Ac
'    Set a = Nothing
'  End If
  On Error GoTo 0
End Sub
Bị báo lỗi sau bác ah
1676541637988.png
 
Upvote 0
Bác ah, em sửa lại không thấy báo lỗi gì nữa nhưng lại không ra kết quả bác ah
Bác muốn kết quả gì, Filter là lọc tự động, trả lại 3 kết quả 3 dòng bác cần tìm là đúng rồi

Có phải bác muốn hàm Filter trả về mảng đã lọc vào nơi gõ hàm?
 
Upvote 0
Bác muốn kết quả gì, Filter là lọc tự động, trả lại 3 kết quả 3 dòng bác cần tìm là đúng rồi

Có phải bác muốn hàm Filter trả về mảng đã lọc vào nơi gõ hàm?
Vâng ạ, em muốn trả kết quả về nơi gõ hàm ạ.
Và nếu em muốn thêm 1 cột D nữa, giá trị trong cột đấy là dạng ký tự. Và khi lọc thỏa mãn điều kiện E1 và E2, nhưng những bản ghi đó là bản ghi khác với giá trị trong cột D thì viết điều kiện lọc thế nào bác nhỉ? Cảm ơn bác ạ. Ví dụ như hình vẽ sau không bao gồm dòng có BB ạ
 

File đính kèm

  • 1676554638219.png
    1676554638219.png
    231.3 KB · Đọc: 6
Lần chỉnh sửa cuối:
Upvote 0
Tét kỹ mà hổng biết hàm Transpose có tới 2 giới hạn cùi bắp lận.
Dính giới hạn là lăn ra ngỏm củ tỏi chứ chưa kịp chạy sai. :)
Transpose là của lão chết tiệt, không phải của mình. Mình chỉ hô biến 1 phát.
Tuy vậy mình biết chắc là bạn ấy đang thử dưới giới hạn, xem hình bài 36 và 38 thì thấy vậy. Còn vụ kêu tự sửa là bạn ấy tự nguyện.
 
Upvote 0
Tét kỹ mà hổng biết hàm Transpose có tới 2 giới hạn cùi bắp lận.
Dính giới hạn là lăn ra ngỏm củ tỏi chứ chưa kịp chạy sai. :)
Ban đầu thấy chỉ có 3 cột, nếu 10 ngàn dòng chưa đến nỗi, Dùng transpose là dùng cho kết quả mảng vừa đủ, chưa biết kết quả cụ thể bao nhiêu dòng. Ai dè 2019 mà không chịu kết quả mảng, phải dùng index.
Nếu dùng Index thì không cần redim preserve và cũng không cần transpose.
TB:
Code bài 29 khủng quá! Tương tự code bài 2 ở đây, nếu là tôi thì viết như bài 10 chỉ 5 câu lệnh.
 
Upvote 0
@ngocleasing
Bác có thể tham khảo bài viết mới của tôi để sử dụng hàm trả giá trị tại ô Viết hàm

 
Upvote 0
@ngocleasing
Bác có thể tham khảo bài viết mới của tôi để sử dụng hàm trả giá trị tại ô Viết hàm

Vâng, cảm ơn bác nhiều ạ
 
Upvote 0

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

Back
Top Bottom