Excel精英培训网

 找回密码
 注册
数据透视表40+个常用小技巧,让你一次学会!
查看: 2118|回复: 9

[已解决]编写一个自定义函数 实现随机不重复抽取功能

[复制链接]
发表于 2017-5-25 15:41 | 显示全部楼层 |阅读模式
该函数有两个参数和返回值,一个参数是一维数组,另外一个是需要不重复抽取的个数。返回值是一个新的数组。目前遇到困难了,返回值不知道该怎么写代码。偶尔参数数组还会下标越界。
请各路大神帮忙看一下。在线等,挺急的

最佳答案
2017-5-25 16:56
不会改变,建议学习一下传值和传址。
原代码修改一下,把原始数组一起输出至D列供参考。
  1. Option Base 1
  2. Public Function GetRnd(arr, n)
  3. Dim brr, r&, m&
  4. ReDim brr(1 To n)
  5. Randomize
  6. Do
  7.   m = Int(Rnd() * UBound(arr) + 1)
  8.   If arr(m) <> "" Then
  9.     r = r + 1
  10.     brr(r) = arr(m): arr(m) = ""
  11.   End If
  12. Loop Until r = n
  13. GetRnd = brr
  14. End Function
  15. Sub aaa()
  16. Dim a
  17. Dim arr1
  18. arr1 = Range("a1:a6")
  19. a = GetRnd(Application.Transpose(arr1), 3)
  20. [b1].Resize(3, 1) = Application.Transpose(a)
  21. [d1].Resize(UBound(arr1)) = arr1
  22. End Sub
复制代码

新建 Microsoft Excel 工作表.rar

10.89 KB, 下载次数: 11

谢谢

excel精英培训的微信平台,每天都会发送excel学习教程和资料。扫一扫明天就可以收到新教程
发表于 2017-5-25 16:22 | 显示全部楼层
  1. Option Base 1
  2. Public Function GetRnd(arr, n)
  3. Dim brr, r&, m&
  4. ReDim brr(1 To n)
  5. Randomize
  6. Do
  7.   m = Int(Rnd() * UBound(arr) + 1)
  8.   If arr(m) <> "" Then
  9.     r = r + 1
  10.     brr(r) = arr(m): arr(m) = ""
  11.   End If
  12. Loop Until r = n
  13. GetRnd = brr
  14. End Function
  15. Sub aaa()
  16. Dim a
  17. Dim arr1
  18. arr1 = Range("a1:a6")
  19. a = GetRnd(Application.Transpose(arr1), 3)
  20. [b1].Resize(3, 1) = Application.Transpose(a)
  21. End Sub
复制代码
回复

使用道具 举报

 楼主| 发表于 2017-5-25 16:52 | 显示全部楼层

8到10行有点疑问,这样子直接把arr(m)=空值,会不会把函数过程外边的arr改变?函数外边的参数数组的值是不能改变的
回复

使用道具 举报

发表于 2017-5-25 16:56 | 显示全部楼层    本楼为最佳答案   
不会改变,建议学习一下传值和传址。
原代码修改一下,把原始数组一起输出至D列供参考。
  1. Option Base 1
  2. Public Function GetRnd(arr, n)
  3. Dim brr, r&, m&
  4. ReDim brr(1 To n)
  5. Randomize
  6. Do
  7.   m = Int(Rnd() * UBound(arr) + 1)
  8.   If arr(m) <> "" Then
  9.     r = r + 1
  10.     brr(r) = arr(m): arr(m) = ""
  11.   End If
  12. Loop Until r = n
  13. GetRnd = brr
  14. End Function
  15. Sub aaa()
  16. Dim a
  17. Dim arr1
  18. arr1 = Range("a1:a6")
  19. a = GetRnd(Application.Transpose(arr1), 3)
  20. [b1].Resize(3, 1) = Application.Transpose(a)
  21. [d1].Resize(UBound(arr1)) = arr1
  22. End Sub
复制代码
回复

使用道具 举报

 楼主| 发表于 2017-5-25 17:02 | 显示全部楼层
大灰狼1976 发表于 2017-5-25 16:56
不会改变,建议学习一下传值和传址。
原代码修改一下,把原始数组一起输出至D列供参考。

嗯 正在看按值传递和按址传递。好晕,毕竟不是专业出身。。。
还有个问题,我在做的其实是一个随机不重复抽取数据的东东。需要从很多列中的数据多次抽取,我想要的结果是每一次随机抽取的时候不受到上一次抽取的影响。
函数参数上到底应该写byref 还是byval呢?
回复

使用道具 举报

发表于 2017-5-25 17:04 | 显示全部楼层
不用纠结,现在的代码就是传值的,不会影响下次抽取。
回复

使用道具 举报

 楼主| 发表于 2017-5-25 17:07 | 显示全部楼层
大灰狼1976 发表于 2017-5-25 17:04
不用纠结,现在的代码就是传值的,不会影响下次抽取。

那么要是写上byval会有什么后果?我试了一下 发现没啥改变啊 ?

回复

使用道具 举报

发表于 2017-5-25 17:10 | 显示全部楼层
byval就是传值
回复

使用道具 举报

 楼主| 发表于 2017-5-25 17:17 | 显示全部楼层

大神,帮忙解答一下这问题吧  这写上byval和不写竟然完全一样,按照教程写的,按理说数组传递到函数里边了,函数里边是有改变数组的代码的,外边的原始数组怎么没收到影响呢?{:021:}
回复

使用道具 举报

发表于 2017-5-25 19:45 | 显示全部楼层
VBA函数默认为传址,也就是说会改变源数据,但是为什么没有变化呢,因为你的实参并不是ARR1,而是APPLICATION.TRANSPOSE(ARR1),所以ARR1不会被改变。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|Excel精英培训 ( 豫ICP备11015029号 )

GMT+8, 2024-4-26 14:53 , Processed in 0.496484 second(s), 11 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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