ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[已解决] 按指定条件、指定序号忽略空格提取对应数据的自定义函数

[复制链接]

TA的精华主题

TA的得分主题

发表于 2020-1-20 19:46 | 显示全部楼层
lsdongjh 发表于 2020-1-20 17:13
自己的需求,自己忘了?第四参数,设置为1,最后不满期的会显示!
也就是现在公式中的N2单元格

老师:我把38楼里自定义函数的参数先后输入顺序改成 {=XHCOUNTIF(数据区域,序号区域,总表最大序号,每周期间隔序号,满额与不满额周期选择,指定需要计数的数据)  后显示错误是怎么回事?

TA的精华主题

TA的得分主题

发表于 2020-1-20 21:32 | 显示全部楼层
lsdongjh 发表于 2020-1-20 17:13
自己的需求,自己忘了?第四参数,设置为1,最后不满期的会显示!
也就是现在公式中的N2单元格

什么都没忘,老师:对不起,只得打扰您了。今天下午才发现,我当初设置的参数有问题--最大序号必须是G1指定的总表最大序号才对,而不是通过MAX(E5:E5000)获取,为此,需要专门增加一个最大序号参数,以替代原代码中的Application.WorksheetFunction.Max(crr)。具体事宜,请看41楼。
  41楼主要问题是:当 MOD(ZDXH-4【表头】,ZQ) =0【最大序号恰好能被周期整除】时,代表最后那个周期的序号正好满额,则无论N2指定为0或为1,都应该显示其计数结果才对。但从41楼截图里看出:当N2指定为1时,L664:N664显示了结果;但当N2指定为0时,L664:N664却显示空白。请老师看看错在哪里了?应该怎样修改代码,才能始终显示正确结果?

TA的精华主题

TA的得分主题

发表于 2020-1-21 09:42 | 显示全部楼层
lsdongjh 发表于 2020-1-20 17:13
自己的需求,自己忘了?第四参数,设置为1,最后不满期的会显示!
也就是现在公式中的N2单元格

老师:请给40楼的代码增加一句判断--当(最大序号-表头4行)恰好是每周期间隔序号【N1】的整倍数【正好满额】时,无论N2指定0或者1,都会显示最后那个周期的计算结果。

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-1-24 01:22 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 WYS67 于 2020-1-25 15:41 编辑

1.gif 2.gif

按指定条件、指定序号忽略空格提取对应数据.zip (168.67 KB, 下载次数: 4)

老师:全怪我粗心大意,没有交代清楚,使得您15楼编写的代码,少了一个判断--  公式  =ZDXHTQ(条件区域,指定条件,数据区域,指定序号区域或指定序号),当符合指定条件的数据个数,少于第四参数指定的序号区域或指定序号时,其结果应该显示空白

如上面截图黄色填充区域【工作表《验证》】的A:B列所示,数据源sheet1的数据区域B5:B100000里,符合指定条件3的非空数据只有640个,所以当第四参数指定序号区域或指定序号超出640的,应该全部显示空白!即工作表《验证》的计算结果 E645:E1000,H5:H360,K645:K1000,N5:N360都应该显示空白才对。

麻烦老师修改相关代码,使得:符合指定条件的数据个数,少于第四参数指定的序号区域或指定序号时,其结果应该显示空白! 不胜感谢之至!

需要修改的15楼代码如下:Option Explicit

Function ZDXHTQ(rgFind As Range, varFind As Variant, rgData As Range, varID As Variant) As Variant
    Dim arrFind As Variant, arrData As Variant, arrID As Variant, arrReturn As Variant
    Dim arrTemp As Variant, strTemp As String, strFind As String
    Dim rgTemp As Range, lngRows As Long, lngCols As Long
    Dim lngMaxID As Long, lngRid As Long, lngCid As Long
    Dim lngMin As Long, lngMax As Long, lngTemp As Long


    Dim intFindRowOrCol As Integer '条件区域为行还是列, 0 为列,1为行
    Dim intDataRowOrCol As Integer '数据区域为行还是列, 0 为列,1为行
    Dim intReturnRowOrCol As Integer '返回区域为行还是列, 0 为列,1为行

    '判断公式所在区域的设置
    '-------------------------------------------------------
    Set rgTemp = Application.Caller
    lngRows = rgTemp.Rows.Count
    lngCols = rgTemp.Columns.Count
    ReDim arrReturn(1 To lngRows, 1 To lngCols) As String
    Set rgTemp = Nothing
    If lngRows <> 1 And lngCols <> 1 Then
        arrReturn(1, 1) = "公式区域有误!"
        ZDXHTQ = arrReturn
        Exit Function
    End If
    '列优先
    If lngRows = 1 Then
        intReturnRowOrCol = 1
    End If
    If lngCols = 1 Then
        intReturnRowOrCol = 0
    End If

    '判断条件区域的设置
    '-------------------------------------------------------
    arrFind = rgFind
    lngRows = rgFind.Rows.Count
    lngCols = rgFind.Columns.Count
    If lngRows <> 1 And lngCols <> 1 Then
        arrReturn(1, 1) = "条件区域有误!"
        ZDXHTQ = arrReturn
        Exit Function
    End If
    '列优先
    If lngRows = 1 Then intFindRowOrCol = 1
    If lngCols = 1 Then intFindRowOrCol = 0

    '判断查找值
    '-------------------------------------------------------
    If IsArray(varFind) Then
        arrReturn(1, 1) = "查找值有误!"
        ZDXHTQ = arrReturn
        Exit Function
    End If
    strFind = Trim(varFind)
    If strFind = "" Then
        arrReturn(1, 1) = "查找值有误!"
        ZDXHTQ = arrReturn
        Exit Function
    End If


    '判断数据区域的设置
    '-------------------------------------------------------
    arrData = rgData
    lngRows = rgData.Rows.Count
    lngCols = rgData.Columns.Count
    If lngRows <> 1 And lngCols <> 1 Then
        arrReturn(1, 1) = "数据区域有误!"
        ZDXHTQ = arrReturn
        Exit Function
    End If
    '列优先
    If lngRows = 1 Then intDataRowOrCol = 1
    If lngCols = 1 Then intDataRowOrCol = 0

    '比对条件区域与数据区域,以最小行列数 为循环终止数
    '-------------------------------------------------------
    If intDataRowOrCol = 1 Then
        lngMaxID = UBound(arrData, 2)
    Else
        lngMaxID = UBound(arrData)
    End If
    If intFindRowOrCol = 1 Then
        If lngMaxID > UBound(arrFind, 2) Then lngMaxID = UBound(arrFind, 2)
    Else
        If UBound(arrFind, 2) > UBound(arrFind) Then lngMaxID = UBound(arrFind)
    End If

    '序号处理
    '-------------------------------------------------------
    arrTemp = varID
    If IsArray(varID) Then
        '如果是数组
        On Error Resume Next '出错处理
        lngRows = UBound(arrTemp)
        lngCols = 0: lngCols = UBound(arrTemp, 2)

        Select Case lngCols
            Case 0 '一维
                arrID = arrTemp
            Case 1 '二维一列
                ReDim arrID(1 To lngRows) As String
                For lngRid = 1 To lngRows
                    arrID(lngRid) = arrTemp(lngRid, 1)
                Next
            Case Is > 1
                If lngRows <> 1 Then
                    arrReturn(1, 1) = "序号区域有误!"
                    ZDXHTQ = arrReturn
                    Exit Function
                Else
                    ReDim arrID(1 To lngCols) As String
                    For lngCid = 1 To lngCols
                        arrID(lngCid) = arrTemp(1, lngCid)
                    Next
                End If
        End Select
    Else
        '不是数组,判断是不是有冒号
        If InStr(arrTemp, ":") > 0 Then
            arrTemp = Split(arrTemp, ":")
            lngMin = Val(arrTemp(0))
            lngMax = Val(arrTemp(1))
            lngTemp = Abs(lngMax - lngMin) + 1
            ReDim arrID(1 To lngTemp) As String
            lngTemp = 1
            If lngMin < lngMax Then
                For lngRid = lngMin To lngMax
                    arrID(lngTemp) = lngRid
                    lngTemp = lngTemp + 1
                Next
            Else
                For lngRid = lngMin To lngMax Step -1
                    arrID(lngTemp) = lngRid
                    lngTemp = lngTemp + 1
                Next
            End If
        Else
            '没有,返回唯一值
            ReDim arrID(1 To 1) As String
            arrID(1) = Val(arrTemp)
        End If
    End If


    '判断序号数量与公式所在区域是否匹配
    '-------------------------------------------------------
    If intReturnRowOrCol = 1 Then
        lngCid = UBound(arrReturn, 2)
    Else
        lngCid = UBound(arrReturn)
    End If

    If lngCid < UBound(arrID) Then
        arrReturn(1, 1) = "公式区域小于序列数量!"
        ZDXHTQ = arrReturn
        Exit Function
    End If


    '查找运算
    '-------------------------------------------------------
    ReDim arrTemp(1 To lngMaxID): lngTemp = 1
    Select Case intFindRowOrCol
        Case 1
            For lngCid = LBound(arrFind, 2) To lngMaxID
                If arrFind(1, lngCid) = strFind Then
                    If intDataRowOrCol = 1 Then
                        If arrData(1, lngCid) <> "" Then arrTemp(lngTemp) = arrData(1, lngCid): lngTemp = lngTemp + 1
                    ElseIf intDataRowOrCol = 0 Then
                        If arrData(lngCid, 1) <> "" Then arrTemp(lngTemp) = arrData(lngCid, 1): lngTemp = lngTemp + 1
                    End If
                End If
            Next
            lngMaxID = lngTemp
        Case 0
            For lngRid = LBound(arrFind) To lngMaxID
                If arrFind(lngRid, 1) = strFind Then
                    If intDataRowOrCol = 1 Then
                        If arrData(1, lngRid) <> "" Then arrTemp(lngTemp) = arrData(1, lngRid): lngTemp = lngTemp + 1
                    ElseIf intDataRowOrCol = 0 Then
                        If arrData(lngRid, 1) <> "" Then arrTemp(lngTemp) = arrData(lngRid, 1): lngTemp = lngTemp + 1
                    End If
                End If
            Next
            lngMaxID = lngTemp
    End Select

    '根据序号提取值
    '-------------------------------------------------------
    For lngRid = LBound(arrID) To UBound(arrID)
        lngTemp = (lngMaxID + Val(arrID(lngRid))) Mod lngMaxID
        arrID(lngRid) = arrTemp(lngTemp)
    Next

    '根据公式区域形式返回行或列
    '-------------------------------------------------------
    For lngRid = LBound(arrID) To UBound(arrID)
        If intReturnRowOrCol = 1 Then
            arrReturn(1, lngRid) = arrID(lngRid)
        Else
            arrReturn(lngRid, 1) = arrID(lngRid)
        End If
    Next

    '返回值
    '-------------------------------------------------------
    ZDXHTQ = arrReturn
End Function



TA的精华主题

TA的得分主题

发表于 2020-1-24 08:42 | 显示全部楼层
本帖最后由 玉阳山人 于 2020-1-28 13:34 编辑

敬请老师帮忙解决44楼反映的问题:当符合指定条件的数据个数,少于第四参数指定的序号区域或指定序号个数时,其结果应该显示空白

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-1-25 09:35 | 显示全部楼层
本帖最后由 WYS67 于 2020-1-28 13:35 编辑
WYS67 发表于 2020-1-14 17:31
经反复测试,老师编写的代码都能显示正确的结果,非常感谢老师!!!

祝老师新年快乐!

敬请老师帮忙解决44楼反映的问题:当符合条件的数据个数,少于第四参数指定的序号区域或指定序号个数时,其结果应该显示空白!

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-1-25 18:58 | 显示全部楼层
本帖最后由 WYS67 于 2020-1-28 13:36 编辑

敬请老师帮忙解决44楼反映的问题:给15楼的代码增加判断:当符合条件的数据个数,少于第四参数指定的序号区域或指定序号个数时,则多出的序号区域和指定序号,其结果应该显示空白!

TA的精华主题

TA的得分主题

发表于 2020-1-25 19:39 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
玉阳山人 发表于 2020-1-24 08:42
敬请老师帮忙解决45楼反映的问题:当符合指定条件的数据个数,少于第四参数指定的序号区域或指定序号个数 ...

'根据公式区域形式返回行或列
    '-------------------------------------------------------
    For lngRid = LBound(arrID) To UBound(arrID)
        If intReturnRowOrCol = 1 Then
            arrReturn(1, lngRid) = arrID(lngRid)
        Else
            arrReturn(lngRid, 1) = arrID(lngRid)
        End If
    Next
改为
'根据公式区域形式返回行或列
    '-------------------------------------------------------
   If intReturnRowOrCol = 1 Then
        For lngRid = LBound(arrID) To lngTemp
              arrReturn(1, lngRid) = arrID(lngRid)
        Next
        For lngRid = lngRid To UBound(arrID)
              arrReturn(1, lngRid) = ""
        Next
    Else
        For lngRid = LBound(arrID) To lngTemp
               arrReturn(lngRid, 1) = arrID(lngRid)
        Next
        For lngRid = lngRid To UBound(arrID)
               arrReturn(lngRid, 1) = ""
        Next
    End If
   

评分

2

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-1-25 20:13 | 显示全部楼层
yjh_27 发表于 2020-1-25 19:39
'根据公式区域形式返回行或列
    '-------------------------------------------------------
    For ...

1.gif

老师:改为
'根据公式区域形式返回行或列
    '-------------------------------------------------------
   If intReturnRowOrCol = 1 Then
        For lngRid = LBound(arrID) To lngTemp
              arrReturn(1, lngRid) = arrID(lngRid)
        Next
        For lngRid = lngRid To UBound(arrID)
              arrReturn(1, lngRid) = ""
        Next
    Else
        For lngRid = LBound(arrID) To lngTemp
               arrReturn(lngRid, 1) = arrID(lngRid)
        Next
        For lngRid = lngRid To UBound(arrID)
               arrReturn(lngRid, 1) = ""
        Next
    End If
后,仍然不能显示正确结果,解铃还需系铃人,看来只有等lsdongjh老师解决了。

万分感谢老师!

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-1-28 13:40 | 显示全部楼层

恳请老师给15楼的代码增加判断:当符合指定条件的数据个数,少于第四参数指定的序号区域或指定序号数时,其错误结果应该都显示为空白
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-4-27 07:05 , Processed in 0.051733 second(s), 13 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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