Excel精英培训网

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

[已解决]不放回抽取

[复制链接]
发表于 2015-10-15 18:36 | 显示全部楼层 |阅读模式
本帖最后由 张雄友 于 2015-10-20 18:31 编辑

不放回随机抽取参加市对抗赛,每人只能被抽取一次(即抽过的不能再抽),每次抽取的个数不定,如下格式。
  1. Sub 随机抽取()
  2. Dim rng As Range, 抽取个数, 剩下个数
  3. Dim d As Object
  4. Dim d1 As Object
  5. Dim r&, i&
  6. Dim arr, brr()
  7. Set d = CreateObject("scripting.dictionary")
  8. Set d1 = CreateObject("scripting.dictionary")
  9. On Error Resume Next
  10. 抽取个数 = Val(InputBox("看看谁被抽到" & Chr(10) & "多少个?", "市名额", 17))
  11. Randomize
  12. With Worksheets("data")
  13. r = .Cells(.Rows.Count, 1).End(xlUp).Row
  14. arr = .Range("A7:B" & r)
  15. End With
  16. For i = 1 To r - 1
  17. If Not d.Exists(arr(i, 1)) Then
  18. Set d(arr(i, 1)) = CreateObject("scripting.dictionary")
  19. End If
  20. d(arr(i, 1))(i) = ""
  21. Next

  22. m = 1
  23. For Each aa In d.Keys
  24. n = Application.Min(抽取个数, d(aa).Count) '随机抽取

  25. For i = 1 To n
  26. kk = d(aa).Keys
  27. n = Int(Rnd() * d(aa).Count)
  28. d1(kk(n)) = ""
  29. d(aa).Remove kk(n)
  30. Next
  31. Next
  32. ReDim brr(1 To d1.Count, 1 To 2)
  33. kk = d1.Keys
  34. For i = 0 To UBound(kk)
  35. brr(i + 1, 1) = arr(kk(i), 1)
  36. brr(i + 1, 2) = arr(kk(i), 2)
  37. Next
  38. Set rng = Application.InputBox("请选择输出单元格如 D7", "如下", , , , , , 8)
  39. rng.Resize(抽取个数, 1).NumberFormatLocal = "@"
  40. rng.Resize(抽取个数, 2) = brr
  41. End Sub
复制代码
最佳答案
2015-10-20 09:23
1、for j=4 to .....,循环取j=4,10,16。。。。每次都是取已提取数组的第4列(姓名)作为key进字典(因为源数组中也是拿第4列(工号唯一)作为key相比较的)
2、step 6 是因为每次提取都有5列,加上1列空格,是为6列
3、tqrr=.....是因为定义已提取数组要把已经提取的内容全部放进去,c是第一列的列号,而每次提取都有5列(其实只要保证姓名那列放进数组,c+3就可以了)

不放回抽取.rar

30.11 KB, 下载次数: 18

发表于 2015-10-16 10:16 | 显示全部楼层
回复

使用道具 举报

发表于 2015-10-16 10:56 | 显示全部楼层
  1. Sub 提取()
  2.     arr = Range("a7:b" & [a65536].End(3).Row)
  3.     n = UBound(arr)     '总组数
  4.     Set d = CreateObject("scripting.dictionary")
  5.     ytq = Application.WorksheetFunction.Sum(Rows(3))  '已提取量
  6.     n = n - ytq   '剩下的总提取量
  7.     tql = Val(InputBox("看看谁被抽到" & Chr(10) & "多少个?", "市名额", 17))      '本次提取量
  8.     If tql > n Then tql = n    '如果提取量大于剩余量,那么提取量=剩余量
  9.    
  10.     ReDim brr(1 To tql, 1 To 2)
  11.     If ytq = 0 Then '未进行过提取
  12.         c = 1
  13.     Else          '已进行过提取
  14.         c = Cells(3, 256).End(xlToLeft).Column
  15.         tqrr = Range([d7], Cells(UBound(arr) + 6, c + 1)) '已提取的组
  16.         For j = 1 To UBound(tqrr, 2) Step 3     '已提取过的内容进字典
  17.             For i = 1 To UBound(tqrr)
  18.                 If tqrr(i, j) <> "" Then
  19.                     d(tqrr(i, j)) = ""
  20.                 End If
  21.             Next
  22.         Next
  23.       
  24.         For i = 1 To UBound(arr)           '剩下可提取的内容放到数组arr的前n位
  25.             If Not d.exists(arr(i, 1)) Then
  26.                 kk = kk + 1
  27.                 arr(kk, 1) = arr(i, 1): arr(kk, 2) = arr(i, 2)
  28.             End If
  29.         Next
  30.     End If
  31.    
  32.     For i = 1 To tql    '在arr中的前n位中提取tql个数
  33.         k = Int(Rnd * n) + 1       '生成1--n的随机数
  34.         brr(i, 1) = arr(k, 1): arr(k, 1) = arr(n, 1)
  35.         brr(i, 2) = arr(k, 2): arr(k, 2) = arr(n, 2)
  36.         n = n - 1
  37.     Next
  38.    
  39.     Cells(3, c + 3) = tql
  40.     Cells(6, c + 3).Resize(1, 2) = Array("工号唯一", "体重公斤")
  41.     Cells(7, c + 3).Resize(tql, 2) = brr
  42. End Sub
复制代码
回复

使用道具 举报

发表于 2015-10-16 10:57 | 显示全部楼层
改了简洁一点。

不放回抽取.rar

33.86 KB, 下载次数: 12

评分

参与人数 1 +9 收起 理由
张雄友 + 9 我测试看是否会重复

查看全部评分

回复

使用道具 举报

 楼主| 发表于 2015-10-16 13:09 | 显示全部楼层
grf1973 发表于 2015-10-16 10:57
改了简洁一点。

第六句用相同变量n看不懂,不知下面的n是什么意思。?
回复

使用道具 举报

发表于 2015-10-16 16:54 | 显示全部楼层
自己逐句调试一下不就明白了?
回复

使用道具 举报

发表于 2015-10-16 16:55 | 显示全部楼层
n是可提取的总组数,每提掉一个,n=n-1

评分

参与人数 1 +9 收起 理由
张雄友 + 9 很给力!

查看全部评分

回复

使用道具 举报

 楼主| 发表于 2015-10-16 18:09 | 显示全部楼层
grf1973 发表于 2015-10-16 16:55
n是可提取的总组数,每提掉一个,n=n-1

测试了一下午发现第16句;For j = 1 To UBound(tqrr, 2) Step 3     '已提取过的内容进字典

要将 Step 3  去掉才正确,如果不去掉有时会不正确。
回复

使用道具 举报

 楼主| 发表于 2015-10-16 18:37 | 显示全部楼层
grf1973 发表于 2015-10-16 16:55
n是可提取的总组数,每提掉一个,n=n-1

用数字验证了一下,是错误的。假设用三次抽完,第一次抽17,第二次抽17,第三次抽600(第三次任)何大于总数的数保证抽完

不放回抽取.rar

29.64 KB, 下载次数: 2

回复

使用道具 举报

 楼主| 发表于 2015-10-17 18:36 | 显示全部楼层
grf1973 发表于 2015-10-16 16:55
n是可提取的总组数,每提掉一个,n=n-1

If Not d.exists(arr(i, 1)) Then

是什么意思?如果不重复项目在第四列,是否If Not d.exists(arr(i, 4)) Then  ?

还有什么要改的吗?数据测试了不正确。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-23 23:54 , Processed in 0.534989 second(s), 15 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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