ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[讨论] 如何用VBA定位与某值最接近的数据首次出现的行号?

[复制链接]

TA的精华主题

TA的得分主题

发表于 2014-7-28 09:45 | 显示全部楼层 |阅读模式
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
  给定一个值n,在一列数据中进行查找、判断、定位并返回所在行号,依据是与该值n的差的绝对值最小,且是首次出现……
  要求:1.不用vlookup函数等,用vba代码解决;
     2.尽量减少循环。
  附件: VBA定位行.rar (3.44 KB, 下载次数: 42)
  当然,附件中的值是随机的。图如下:
   1.jpg

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-7-28 09:54 | 显示全部楼层
打字错误:“和等号”应该为“的行号”……不好意思……

TA的精华主题

TA的得分主题

发表于 2014-7-28 10:09 | 显示全部楼层
扫描一遍就可以了。
  1. Sub aa()
  2.     Dim arr, myrow&, mMin&, myval&, i&
  3.     arr = Range("A2").CurrentRegion
  4.     myval = Cells(1, 4)
  5.     mMin = Abs(arr(1, 1) - myval)
  6.     myrow = 1

  7.     For i = 2 To UBound(arr)
  8.         If Abs(arr(i, 1) - myval) < mMin Then mMin = Abs(arr(i, 1) - myval): myrow = i
  9.     Next
  10.     MsgBox "第一次出现最接近的行:" & myrow
  11. End Sub
复制代码

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-7-28 10:14 | 显示全部楼层
wzsy2_mrf 发表于 2014-7-28 10:09
扫描一遍就可以了。

首先将目标值与第一个值做减法(mMin = Abs(arr(1, 1) - myval)),存储其差的绝对值,便于接下来的比较,很是巧妙!

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-7-28 10:16 | 显示全部楼层
wzsy2_mrf 发表于 2014-7-28 10:09
扫描一遍就可以了。

您的这个方法即将在我接下来的帖子中应用,届时烦请围观下……呵呵,对我启发太大了,真是感谢……我考虑到了死角,都感觉要用两三层循环了,您这个够厉害!

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-7-28 11:14 | 显示全部楼层
wzsy2_mrf 发表于 2014-7-28 10:09
扫描一遍就可以了。

您的代码也可以修改为首次与最大值比较,然后来一个完整循环:
  1. Sub aa1() '网友提供,精彩方法
  2.     Dim arr, myrow&, mMin&, myval&, i&
  3.     arr = Range("A2").CurrentRegion
  4.     myval = Cells(1, 4)
  5.     mMin = Abs(WorksheetFunction.Max(arr) - myval)
  6.     myrow = 1

  7.     For i = 1 To UBound(arr)
  8.         If Abs(arr(i, 1) - myval) < mMin Then mMin = Abs(arr(i, 1) - myval): myrow = i
  9.     Next
  10.     MsgBox "第一次出现最接近的行:" & myrow
  11. End Sub
复制代码
这样在特殊情况下是有好处的……

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-7-28 11:32 | 显示全部楼层
本帖最后由 aoe1981 于 2014-7-28 11:35 编辑
wzsy2_mrf 发表于 2014-7-28 10:09
扫描一遍就可以了。

  不好意思,前面的说法有点漏洞,应当与2倍的最大值比较,防止目标数据就是最大值本身!代码修改为(可以减少首次行号预赋值的代码):
  1. Sub aa1() '网友提供,精彩方法
  2.     Dim arr, myrow&, mMin&, myval&, i&
  3.     arr = Range("A2").CurrentRegion
  4.     myval = Cells(1, 4)
  5.     mMin = Abs(WorksheetFunction.Max(arr) * 2 - myval)

  6.     For i = 1 To UBound(arr)
  7.         If Abs(arr(i, 1) - myval) < mMin Then mMin = Abs(arr(i, 1) - myval): myrow = i
  8.     Next
  9.     MsgBox "第一次出现最接近的行:" & myrow
  10. End Sub
复制代码

TA的精华主题

TA的得分主题

发表于 2014-7-28 12:27 | 显示全部楼层
aoe1981 发表于 2014-7-28 11:32
  不好意思,前面的说法有点漏洞,应当与2倍的最大值比较,防止目标数据就是最大值本身!代码修改为(可 ...

说句不客气的话,你以上两个程序都是没有必要的。第一,调用工作表函数也是要花费时间的,而这个工作表函数作用的时候已经扫描过全部数据一遍,而这扫描一遍的时间的早已可把工作做完,而你才刚刚开始,这等于是在做无用功。第二,如果是求最小数的话,那么mMin有初始设定应该 >=数据集中的最小数,越接近越好;只有这样才能减少交换次数;而求最大数的时候刚好相反。但最小数、最大数是那一个你原先那里知道,既然如此,你就在数据集中随便选一个好了。

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-7-28 12:57 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
wzsy2_mrf 发表于 2014-7-28 12:27
说句不客气的话,你以上两个程序都是没有必要的。第一,调用工作表函数也是要花费时间的,而这个工作表函 ...

呵呵,您说的有道理……但是您不明白我应用的具体情况……假设我的A列数据源按某一属性分为两组,不妨设为男子组和女子组,当要比较的目标数据也有这一属性时,比如D1单元格为女子组的数据,匹配时只能从女子组里匹配时,我的思路有所便捷……当然,男子组与女子组的最大值是已知的……呵呵
具体还请关注不久要发布的我的新帖中的应用!

TA的精华主题

TA的得分主题

发表于 2014-7-28 13:02 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
楼主的一楼说明中写明了“不用vlookup函数等”,楼主的代码中已经用了“WorksheetFunction.Max”,犯规了
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-11-18 22:26 , Processed in 0.050013 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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