ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[讨论] 万能取有数据最后行号自定义函数(VBA专用)

[复制链接]

TA的精华主题

TA的得分主题

发表于 2019-1-27 12:18 | 显示全部楼层 |阅读模式
本帖最后由 小花鹿 于 2019-2-21 07:38 编辑

自己平时给别人写代码时,经常要取某列(如:A)或某个列范围(如:A:Z)最后有数据的行号,以便于进行后续的代码编写,但是,有时要考虑隐藏行或筛选等情况,所以,写一个自定义函数,能够在任何情况下,不对工作表作任何变动而能正确的得到行号。
会存在错误或效率问题,请有兴趣的帮忙优化。
Sub test1()
MsgBox endrow("a:b","sheet1")
End Sub
Function endrow(Optional myc As String, Optional mysht As String)
    '得到有数据的最后行号,两个参数均可选
    '参数形式如:myc是列范围,如"A:B",如果忽略则为整个工作表
    '            mysht是指工作表,如"sheet1",如果忽略则为活动工作表
    Dim sht, ar, r&, i&, j&, s
    If mysht = "" Then
        Set sht = ActiveSheet
    Else
        Set sht = Sheets(mysht)
    End If
    ar = sht.UsedRange
    r = sht.UsedRange.Range("a1").Row
    If IsArray(ar) Then
        For i = UBound(ar) To 1 Step -1
            For j = 1 To UBound(ar, 2)
                If ar(i, j) <> "" Then
                    r = i + r - 1
                    s = ar(i, j)
                    GoTo label1
                End If
            Next j
        Next i
label1:
    Else
        s = ar
    End If
    If s = "" Then r = 0
    If myc = "" Or r = 0 Then
        endrow = r
        Exit Function
    End If
    s = ""
    Dim c
    c = Split(myc, ":")
    ar = sht.Range(c(0) & "1:" & c(1) & r)
    If IsArray(ar) Then
        For i = UBound(ar) To 1 Step -1
            For j = 1 To UBound(ar, 2)
                If ar(i, j) <> "" Then
                    r = i
                    s = ar(i, j)
                    GoTo label2
                End If
            Next j
        Next i
label2:
    Else
        s = ar
    End If
    If s = "" Then r = 0
    endrow = r
End Function

====================================================================
学习9楼老师的代码,修改成自定义函数,方便使用:
Sub test2()
MsgBox EndRow("a:b", "sheet2")
End Sub
Function EndRow(Optional myc As String, Optional mysht As String)
    '得到有数据的最后行号,两个参数均可选
    '参数形式如:myc是列范围,如"A:B",如果忽略则为整个工作表
    '            mysht是指工作表,如"sheet1",如果忽略则为活动工作表
    Dim rng As Range, sht As Worksheet, ar, i&, j&
    If mysht <> "" Then
        Set sht = Sheets(mysht)
    Else
        Set sht = ActiveSheet
    End If
    If myc = "" Then
        Set rng = sht.UsedRange
    Else
        Set rng = Intersect(sht.UsedRange, sht.Range(myc))
    End If
    If rng Is Nothing Then
        EndRow = 0
        Exit Function
    End If
    ar = rng.Value
    If Not IsArray(ar) Then
        If Len(ar) = 0 Then
            EndRow = 0
            Exit Function
        Else
            EndRow = rng.Row
            Exit Function
        End If
    Else
        For i = UBound(ar) To 1 Step -1
            For j = 1 To UBound(ar, 2)
                If Len(ar(i, j)) Then
                    EndRow = i - 1 + rng.Row
                    Exit Function
                End If
            Next j
        Next i
    End If
    EndRow = 0
End Function
=============================================================
修改一下,可以求行号和列号,有兴趣的帮忙测试一下:
Sub test2()
Dim s1$, s2$, s
s1 = [m1]
s2 = [m2]
s = EndRC(s1, s2)
MsgBox s(1) & "," & s(2)
End Sub
Function EndRC(Optional MyRange As String, Optional MySht As String)
    '函数返回结果为两个元素的一维数组,EndRC(1)代表最后行号,EndRC(2)代表最后列号
    '得到指定范围的有数据的最后行列号,两个参数均可选
    '参数形式如:MyRange是指定范围,形如,整列"A:B"、整行"6:26"、矩形区域"a6:h26",如果忽略则为UsedRange
    '            MySht是指工作表,如"sheet1",如果忽略则为活动工作表
    Dim rng As Range, sht As Worksheet, ar, i&, j&, RC(1 To 2) As Long
    If MySht <> "" Then
        Set sht = Sheets(MySht)
    Else
        Set sht = ActiveSheet
    End If
    If MyRange = "" Then
        Set rng = sht.UsedRange
    Else
        Set rng = Intersect(sht.UsedRange, sht.Range(MyRange))
    End If
    If rng Is Nothing Then
        GoTo label1
    End If
    ar = rng.Value
    If Not IsArray(ar) Then
        If Len(ar) = 0 Then
            GoTo label1
        Else
            RC(1) = rng.Row
            RC(2) = rng.Column
            GoTo label1
        End If
    Else
        For i = UBound(ar, 2) To 1 Step -1
            For j = 1 To UBound(ar)
                If Len(ar(j, i)) Then
                    RC(2) = i - 1 + rng.Column
                    GoTo label2
                End If
            Next j
        Next i
label2:
        For i = UBound(ar) To 1 Step -1
            For j = 1 To UBound(ar, 2)
                If Len(ar(i, j)) Then
                    RC(1) = i - 1 + rng.Row
                    GoTo label1
                End If
            Next j
        Next i
    End If
label1:
    EndRC = RC
End Function

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2019-1-29 19:57 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2019-1-29 23:09 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2019-1-30 11:32 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2019-1-30 16:45 | 显示全部楼层
  1. Sub test()
  2. Dim rng As Range
  3. Set rng = Worksheets("sheet1").Columns("a:c")

  4. Dim rnga As Range
  5. Set rnga = rng.Find(what:="*")
  6. Set rnga = rng.FindPrevious(after:=rnga)

  7. MsgBox rnga.Row
  8. End Sub
复制代码


评分

1

查看全部评分

TA的精华主题

TA的得分主题

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

TA的精华主题

TA的得分主题

发表于 2019-1-31 14:32 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-1-31 19:55 | 显示全部楼层
zopey 发表于 2019-1-31 14:32
隐藏单元格内容 ,find 不适用。

我的意思是要在任何情况下都能正确得到有数据的最后行号,而且不对单元格做任何操作,你有没有更简单的方法

TA的精华主题

TA的得分主题

发表于 2019-1-31 23:10 | 显示全部楼层
小花鹿 发表于 2019-1-31 19:55
我的意思是要在任何情况下都能正确得到有数据的最后行号,而且不对单元格做任何操作,你有没有更简单的方 ...
  1. Sub test()
  2. Dim rng As Range
  3. With Worksheets("sheet1")
  4.     Set rng = Intersect(.UsedRange, .Columns("a:d"))
  5. End With

  6. Dim arr
  7. arr = rng

  8. For i = UBound(arr) To 1 Step -1
  9. For j = 1 To UBound(arr, 2)
  10.    If Len(arr(i, j)) > 0 Then MsgBox i - 1 + rng.Row: Exit Sub
  11. Next
  12. Next

  13. End Sub
复制代码
赋值给数组,应该可以

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2019-2-1 08:58 | 显示全部楼层
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-4-17 06:02 , Processed in 0.046146 second(s), 16 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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