ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 1272|回复: 8

[原创] 二维数组 自定义筛选 通用方法

[复制链接]

TA的精华主题

TA的得分主题

发表于 2021-8-5 17:55 | 显示全部楼层 |阅读模式
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
  1. Sub Test()
  2.     Dim arr As Variant, brr As Variant
  3.     arr = Sheet1.Range("C6:E13")
  4.    
  5.     '从arr中筛选
  6.     '--第 2 列 等于 1100  [2, "=", 1100]
  7.     '--且 [True]
  8.     '--第 3 列 等于 "CASH"[3, "=", "CASH"]
  9.     brr = FilterArr(arr, True, 2, "=", 1100, 3, "=", "CASH")
  10.     Sheet1.Range("L6").Resize(UBound(arr), UBound(arr, 2)) = brr
  11.    
  12.     '从arr中筛选
  13.     '--第 2 列 等于 1100  [2, "=", 1100]
  14.     '--或 [False]
  15.     '--第 3 列 等于 "CASH"[3, "=", "CASH"]
  16.     brr = FilterArr(arr, False, 2, "=", 1100, 3, "=", "CASH")
  17.     Sheet1.Range("Q6").Resize(UBound(arr), UBound(arr, 2)) = brr
  18.    
  19. End Sub


  20. '' 二维数组 通用多条件筛选
  21. ''
  22. ''' arr 要筛选的数组
  23. ''' IsAND  多条件之间的关系,True 为 And ,False 为 OR
  24. ''' Conditions(),条件参数组。
  25. '''     (1)三个为一组,分别为:判断的列索引号,逻辑运算符,条件值
  26. '''     (2)指定逻辑运算符为 Like 时,按 字符型处理,其他的则根据条件值的类型:
  27. '''            ... "1" 为字符型, 1 为数值型
  28. Function FilterArr(arr As Variant, IsAND As Boolean, ParamArray Conditions() As Variant) As Variant
  29.     Dim startID As Long, endID As Long, paraCount As Long
  30.     Dim arrResult As Variant, strMsg As String, lngRow As Long, lngCOl As Long
  31.     Dim lngID As Long, arrConditions As Variant, arrFlag As Variant
  32.     Dim blCHeck As Boolean
  33.     On Error GoTo ErrFun
  34.    
  35.     startID = LBound(Conditions): endID = UBound(Conditions)
  36.     paraCount = endID - startID + 1
  37.    
  38.     If GetArrayRange(arr) <> 2 Then strMsg = "不是二维数组": GoTo ErrFun
  39.     If paraCount = 0 Then strMsg = "没有输入筛选条件": GoTo ErrFun
  40.     If paraCount Mod 3 <> 0 Then strMsg = "筛选条件有误": GoTo ErrFun
  41.    
  42.     paraCount = paraCount / 3
  43.     ReDim arrConditions(1 To paraCount, 1 To 3)
  44.     paraCount = 1
  45.     For lngID = startID To endID Step 3
  46.         arrConditions(paraCount, 1) = CLng(Conditions(lngID))
  47.         If arrConditions(paraCount, 1) < LBound(arr, 2) Or arrConditions(paraCount, 1) > UBound(arr, 2) Then
  48.             strMsg = "筛选条件[列索引值]有误": GoTo ErrFun
  49.         End If
  50.         arrConditions(paraCount, 2) = CStr(Conditions(lngID + 1))
  51.         arrConditions(paraCount, 3) = Conditions(lngID + 2)
  52.         paraCount = paraCount + 1
  53.     Next
  54.    
  55.     ReDim arrFlag(0) As Long: paraCount = 0
  56.     For lngRow = LBound(arr) To UBound(arr)
  57.         blCHeck = IsAND
  58.         For lngID = LBound(arrConditions) To UBound(arrConditions)
  59.             If IsAND Then
  60.                 blCHeck = blCHeck And (Compare(arr(lngRow, arrConditions(lngID, 1)), arrConditions(lngID, 3), CStr(arrConditions(lngID, 2))))
  61.             Else
  62.                 blCHeck = blCHeck Or (Compare(arr(lngRow, arrConditions(lngID, 1)), arrConditions(lngID, 3), CStr(arrConditions(lngID, 2))))
  63.             End If
  64.             If blCHeck = Not IsAND Then Exit For
  65.         Next

  66.         If blCHeck Then
  67.             paraCount = paraCount + 1
  68.             ReDim Preserve arrFlag(1 To paraCount) As Long
  69.             arrFlag(paraCount) = lngRow
  70.         End If
  71.     Next
  72.    
  73.     If paraCount = 0 Then GoTo ErrFun
  74.     ReDim arrResult(1 To paraCount, LBound(arr, 2) To UBound(arr, 2))
  75.    
  76.     For lngRow = LBound(arrFlag) To UBound(arrFlag)
  77.         For lngCOl = LBound(arr, 2) To UBound(arr, 2)
  78.             arrResult(lngRow, lngCOl) = arr(arrFlag(lngRow), lngCOl)
  79.         Next
  80.     Next
  81.    
  82.     FilterArr = arrResult
  83.     Exit Function
  84. ErrFun:
  85.     ReDim arrResult(1 To 1, 1 To 1) As String
  86.     arrResult(1, 1) = strMsg
  87.     FilterArr = arrResult
  88. End Function

  89. '两两比较
  90. Function Compare(ParaValue As Variant, ParaCondition As Variant, Comparator As String) As Boolean
  91.     Dim arrA As Variant, arrB As Variant
  92.     Dim blResult As Boolean
  93.    
  94.     Comparator = UCase(Comparator)
  95.     If Comparator = "LIKE" Then
  96.         arrA = CStr(ParaValue)
  97.         arrB = CStr(ParaCondition)
  98.     Else
  99.         If TypeName(ParaCondition) = "String" Then
  100.             arrA = CStr(ParaValue)
  101.             arrB = CStr(ParaCondition)
  102.         Else
  103.             arrA = Val(ParaValue)
  104.             arrB = Val(ParaCondition)
  105.         End If
  106.     End If
  107.    
  108.     Select Case Comparator
  109.         Case ">"
  110.             blResult = (arrA > arrB)
  111.         Case ">="
  112.             blResult = (arrA >= arrB)
  113.         Case "<"
  114.             blResult = (arrA < arrB)
  115.         Case "<="
  116.             blResult = (arrA <= arrB)
  117.         Case "<>"
  118.             blResult = (arrA <> arrB)
  119.         Case "="
  120.             blResult = (arrA = arrB)
  121.         Case "LIKE"
  122.             blResult = (arrA Like arrB)
  123.         Case Else
  124.             blResult = False
  125.     End Select
  126.    
  127.     Compare = blResult
  128. End Function

  129. '判断数组维数
  130. Public Function GetArrayRange(arr As Variant) As Integer
  131.     Dim intID As Integer, intTmp As Integer
  132.     On Error GoTo ErrFun

  133.     If Not IsArray(arr) Then
  134.         GetArrayRange = -1
  135.         Exit Function
  136.     End If
  137.      
  138.     For intID = 1 To 60
  139.         intTmpt = UBound(arr, intID)
  140.     Next
  141.    
  142.     GetArrayRange = intTmpt
  143.     Exit Function
  144. ErrFun:
  145.     GetArrayRange = intID - 1
  146. End Function

复制代码


评分

3

查看全部评分

TA的精华主题

TA的得分主题

发表于 2021-8-5 18:52 | 显示全部楼层
涵盖了二维数组中的几个典型示例!感谢分享!

TA的精华主题

TA的得分主题

发表于 2024-1-24 23:41 来自手机 | 显示全部楼层
测试了下,条件不能是变量吗?

TA的精华主题

TA的得分主题

发表于 2024-1-25 08:16 | 显示全部楼层
如果这方法有个实例就完美了。

TA的精华主题

TA的得分主题

发表于 2024-1-25 15:38 | 显示全部楼层
数组筛选的函数 :   _二维数组筛选_GetFilterArray.rar (3.79 KB, 下载次数: 29)

  1. Rem *********************************
  2. Rem *******  北极狐工作室出品  ******
  3. Rem *******  QQ:14885553      ******
  4. Rem *********************************
  5. Option Explicit  '//强制声明变量

  6. Function GetFilterArray(ByVal ARX, Optional ByVal ZAC As Object = Nothing, Optional ByVal intBT As Long = 1, Optional ByVal HuLueBlank As Boolean = False _
  7.         , Optional ByVal StrNum As String = "", Optional ByVal NumData As String = "0", Optional ByVal StrExpNum As String = "=" _
  8.         , Optional ByVal StrDate As String = "", Optional ByVal DateData As String = "0", Optional ByVal StrExpDate As String = "=" _
  9.         , Optional ByVal StrText = "", Optional ByVal TextData As String = "", Optional ByVal StrExpTxt As String = "" _
  10.         , Optional ByVal BlPinYin As Boolean = False, Optional ByVal BlCase As Boolean = True, Optional ByVal StrNeedBT As String = "")
  11.    
  12.     Rem  GetFilterArray    对数组进行过滤 留下需要的行
  13.     Rem  ARX             需要筛选的二维数组, 可以有标题  可以无标题, 数组下限=0 或者=1 自动判断
  14.     Rem  ZAC             数组标题的字典, 默认:=nothing 则在函数中指定, IntBT=0 则必须提前制定好
  15.     Rem  IntBT            数组是否有标题  默认:=1 有标题
  16.     Rem  HuLueBlank 是否忽略数组中的空白或Null  默认:=false 不要忽略,直接参与判断 此时空白日期=1901-01-01
  17.    
  18.     Rem  StrNum       数字对比字段, 可以是多个字段, 使用[,]隔开, 默认:=""   则不对比数字字段
  19.     Rem  NumData    数字字段的对比值,, 可以是多个字段, 使用[,]隔开, 个数和数字字段相同, 默认:="0"
  20.     Rem  StrExpNum  对比表达式 默认:= 如果 空白或个数不同 则都是: =  可以是: =,<>,>,>=,<,<=,等于,不等于,大于,大于等于,小于,小于等于
  21.    
  22.     Rem  StrDate       日期对比字段, 可以是多个字段, 使用[,]隔开, 默认:=""   则不对比日期字段
  23.     Rem  DateData    日期字段的对比值,, 可以是多个字段, 使用[,]隔开, 个数和日期字段相同, 默认:="1901-01-01"
  24.     Rem  StrExpDate  对比表达式 默认:= 如果 空白或个数不同 则都是: =  可以是: =,<>,>,>=,<,<=,等于,不等于,大于,大于等于,小于,小于等于
  25.    
  26.     Rem  StrText        文本对比字段, 可以是多个字段, 使用[,]隔开, 默认:=""  则不对比文本字段
  27.     Rem  TextData     文本字段的对比值,, 可以是多个字段, 使用[,]隔开, 个数和文本字段相同, 默认:=""
  28.     Rem  StrExpTxt     对比表达式 默认:= 如果 空白或个数不同 则都是: =  可以是: =,<>,Instr,包含,不包含,等于,不等于,开头,结尾
  29.     Rem  BlPinYin       是否使用拼音首字母查询  仅限文本字段  默认:=false  需要汉字首字母函数  PySZM
  30.     Rem  BlCase         是否区分大写  默认=true  区分大小写
  31.     Rem  StrNeedBT   结果数组需要的标题, 默认=""  就是全部
  32.    
  33.     Rem  北极狐工作室  QQ: 14885553
  34.    
  35.     Rem  DRX = GetFilterArray(ARX:=ARX, ZAC:=ZAC, IntBT:=1, HuLueBlank:=FALSE,StrNum:="金额", NumData:="0", StrExpNum:="大于", StrText:="省,市,区", TextData:="黑龙江,哈尔滨,南岗区", StrExpTxt:="=,=,不等于",BlPinYin=FALSE,BlCase:=false)
  36.     Rem  DRX = GetFilterArray(ARX:=SQLARR, ZAC:=ZSC, IntBT:=1,HuLueBlank:=FALSE,StrNum:="待生产数", NumData:="0", StrExpNum:="大于", StrText:="物料编码,物料编码", TextData:="R,001", StrExpTxt:="包含,包含", StrDate:="要货日期,要货日期", DateData:="2023-10-01,2023-10-22", StrExpDate:="大于等于,小于等于")
  37.    
复制代码

TA的精华主题

TA的得分主题

发表于 2024-1-25 19:11 | 显示全部楼层
opiona 发表于 2024-1-25 15:38
数组筛选的函数 :

挺不错的,要仔细学学。

TA的精华主题

TA的得分主题

发表于 2024-1-25 19:18 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2024-2-5 12:17 | 显示全部楼层
我也来发一个,返回筛选后的索引数组arrIndex,再根据索引数组从原数组取数或数组,一二维数组都适用,主要是看回调函数怎么设计。回调功能可以将CallBackFunctionReturnLong2替换为CallWindowProcA。

Function Array_FilterIndex_(arr, ByVal cmpFun As Long, Optional ByVal l As Long = -1, Optional ByVal r As Long = -1)
'返回筛选后的索引数组arrIndex,LBOUND=0,不存在则返回空
'l,r:范围
'CmpFun:比较回调函数,符合条件返回非0.函数原型为:
'Function cbFun_BinaryCompareVariant(arr, i As Long) As Boolean'i为index或row

If cmpFun = 0 Then MsgBox "cmpFun=0", vbExclamation, "Array_FilterIndex Error": Exit Function

If Array1D_CheckAndSetBoundValid_(arr, l, r) = False Then Exit Function

ReDim arrIndex(0 To r - l)
Dim fast As Long, slow As Long
slow = l
fast = l

Do While (fast <= r)
    If CallBackFunctionReturnLong2(cmpFun, arr, fast) Then
'    If arr(fast) = Condition Then
        arrIndex(slow - l) = fast
        slow = slow + 1
    End If
    fast = fast + 1
Loop

If slow > l Then
    If slow - 1 < r Then ReDim Preserve arrIndex(0 To slow - l - 1)
    Array_FilterIndex_ = arrIndex
End If
End Function

TA的精华主题

TA的得分主题

发表于 2024-3-23 10:04 | 显示全部楼层
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-4-28 06:37 , Processed in 0.051082 second(s), 16 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表