Excel精英培训网

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

VBA 矩阵式随机数生成——感觉超复杂

[复制链接]
发表于 2020-3-12 18:26 | 显示全部楼层 |阅读模式
本帖最后由 zglibk 于 2020-3-14 14:00 编辑

老师们好!
  我有一个生成随机数的需求,需要根据参数(组数、行数、偏差系数、保留小数)设置,生成矩阵式随机数,想了一天,实在没撤,就把这部分拆分了出来,求解!
一、界面图
界面.jpg


二、需要达到的效果图
1、选择2组时
2组的效果.jpg
2、选择3组时
3行效果.jpg


三、文件附件
矩阵随机数.rar (15.27 KB, 下载次数: 3)
发表于 2020-3-13 10:07 | 显示全部楼层
我感觉你这不是在问随机数的问题,而是如何用好控件的问题。随机数不管怎么算,毕竟只是一个相对简单的算法而已;你问  'For i=    For s=   该如何写?说明你对基本的循环都不太清楚,那么要用好控件就比较难了;
我在这里不回答你随机数的问题,也不解释你循环的问题,这都是基础的东西,你自己琢磨就好了,我重点说下控件的循环:
1、通常控件是直接引用,比如 me.textbox4.text,因为窗体里面的控件数量都是很有限的,逐个指定比较简单;
2、偶尔会有动态添加控件的情况,一般用 set 来指定控件名称,本质上与直接引用没什么差别;
3、你这种大批量预先设立控件的情况比较少见,其实如果一定要这么来设置,根据参数动态添加控件还是更好些,当然难度也更大些。
     下面我就重点来说如何动态引用控件(为了简化不包含动态添加):
      你的写法:Me.Controls("TextBox" & s) 我认为是不成立的,对象没有这么来引用的,只有普通变量才可以这么使用;      

     我认为正确的写法是:

     Dim kj As Control     ‘定义控件
     i = 1
     For Each kj In Me.Controls      '循环所有控件,单元格区域对象的循环也是这种用法,表单的shape对象同样也是这么用;
           If UCase(TypeName(kj)) = "TEXTBOX" Then   '筛选指定类型的控件
              If (kj.Name <> "TextBox18") And (kj.Name <> "TextBox9") And (kj.Name <> "TextBox10") And (kj.Name <> "TextBox11") And (kj.Name <> "TextBox14") Then                 '剔除用于参数的文本框,但第一行的文本框没有剔除,代码要写很长,你自己改好了

               kj.Text = i                    '对指定类型的对象赋值,对于你的问题,就是要把生成的随机数写在这里就可以了;
               i = i + 1
           End If
     Next

回复

使用道具 举报

发表于 2020-3-13 16:07 | 显示全部楼层
偏差系数怎么使用?处理简单的。
回复

使用道具 举报

发表于 2020-3-13 16:31 | 显示全部楼层
未测试,基本上就这个样子,下班后下载附件测试。
注意代码要放到窗体模块内,不然Me会出错。
  1. Sub test()
  2.     Dim n&, i&, j&, k&, rCnt&, x#, fmt$, gCnt&, b#, NO&
  3.     gCnt = TextBox9
  4.     n = TextBox10
  5.     rCnt = TextBox11
  6.     x = TextBox14
  7.     fmt = "0." & String(TextBox18, "0")
  8.     For j = 1 To n
  9.         b = Me("TextBox" & j + 18)
  10.         For i = 0 To gCnt - 1
  11.             For k = 0 To rCnt - 1
  12.                 NO = i * 40 + k * 10 + j + 18
  13.                 If NO > 28 Then Me("TextBox" & NO) = Format(CDbl(b) + CDbl(x * Rnd()), fmt)
  14.             Next k
  15.         Next i
  16.     Next j
  17. End Sub
复制代码
回复

使用道具 举报

发表于 2020-3-13 16:35 | 显示全部楼层
貌似I*40要改成I*30
回复

使用道具 举报

发表于 2020-3-13 19:30 | 显示全部楼层
测试OK,再加上一段清除前次运行结果的代码。
不过我看你的示例里面,有比基准值高的,也有比基准值低的,范围也有超过0.02系数的,
但是你的示例代码里面却是简单的加法,所以我不确定代码的计算结果符合你的要求。
  1. Sub 随机数()
  2.     Dim n&, i&, j&, k&, rCnt&, x#, fmt$, gCnt&, b#, NO&
  3.     gCnt = TextBox9
  4.     n = TextBox10
  5.     rCnt = TextBox11
  6.     x = TextBox14
  7.     fmt = "0." & String(TextBox18, "0")
  8.     For NO = 29 To 108
  9.         Me("TextBox" & NO) = ""
  10.     Next NO
  11.     For j = 1 To n
  12.         b = Me("TextBox" & j + 18)
  13.         For i = 0 To gCnt - 1
  14.             For k = 0 To rCnt - 1
  15.                 NO = i * 30 + k * 10 + j + 18
  16.                 If NO > 28 Then Me("TextBox" & NO) = Format(CDbl(b) + CDbl(x * Rnd()), fmt)
  17.             Next k
  18.         Next i
  19.     Next j
  20. End Sub
复制代码
回复

使用道具 举报

 楼主| 发表于 2020-3-13 19:46 | 显示全部楼层
大灰狼1976 发表于 2020-3-13 19:30
测试OK,再加上一段清除前次运行结果的代码。
不过我看你的示例里面,有比基准值高的,也有比基准值低的, ...

感谢版主!辛苦了!!
    示例里是手工乱编的数字,只用来展示结构
    我运行试试~
回复

使用道具 举报

 楼主| 发表于 2020-3-13 22:50 | 显示全部楼层
本帖最后由 zglibk 于 2020-3-13 23:06 编辑
大灰狼1976 发表于 2020-3-13 19:30
测试OK,再加上一段清除前次运行结果的代码。
不过我看你的示例里面,有比基准值高的,也有比基准值低的, ...

版主大神,
    单独运行您的代码,完全没问题
    但是,为什么我整合进我原有的第一段代码,
    您这句 b = Me("TextBox" & j + 18) 会报错“类型不匹配”?
    麻烦再帮我看看哪里需要修改!!

      矩阵随机数(类型不匹配).rar (14.8 KB, 下载次数: 3)
回复

使用道具 举报

发表于 2020-3-14 10:58 | 显示全部楼层
你套错循环了,t循环是和j循环重复的,另外,你有清除数据的过程,我就把原来清除数据的代码删除了,整体如下:
  1. Sub 随机数()
  2.     Dim n&, i&, j&, k&, rCnt&, x#, fmt$, gCnt&, b#, NO&, t&
  3.     gCnt = TextBox9
  4.     n = TextBox10
  5.     rCnt = TextBox11
  6.     x = TextBox14
  7.     fmt = "0." & String(TextBox18, "0")
  8.    
  9.     Call 清空数据
  10.     For j = 1 To n
  11.     '生成起、止范围内的文本框的首行随机数
  12.         Me("TextBox" & j + 18) = Format(CDbl(Me.TextBox16.Text) + CDbl(Me.TextBox17.Text) * Rnd() * (-1) ^ Round(Rnd() * 100, 0), fmt)
  13.         b = Me("TextBox" & j + 18)
  14.         '以首行已生成的随机数为基准,根据参数(“组数”、“行数”、“偏差系数”、“小数位数”)生成其余相应行、列随机数
  15.         For i = 0 To gCnt - 1
  16.             For k = 0 To rCnt - 1
  17.                 NO = i * 30 + k * 10 + j + 18
  18.                 If NO > 28 Then Me("TextBox" & NO) = Format(CDbl(b) + CDbl(x * Rnd()), fmt)
  19.             Next k
  20.         Next i
  21.     Next j
  22. End Sub
复制代码

评分

参与人数 1学分 +2 收起 理由
zglibk + 2 学习

查看全部评分

回复

使用道具 举报

 楼主| 发表于 2020-3-14 13:59 | 显示全部楼层
大灰狼1976 发表于 2020-3-14 10:58
你套错循环了,t循环是和j循环重复的,另外,你有清除数据的过程,我就把原来清除数据的代码删除了,整体如 ...

谢谢大灰狼版主,人好技术强!
——完美达到我想要的效果。
同时也感谢@及其他关注本贴的老师。

回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-27 12:08 , Processed in 0.337823 second(s), 11 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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