04 其他

自定义函数解决在0~N的数据区间随机出现n次的问题(n≤N)

  这样一个问题:“Excel考勤表,已经知道了月度总出勤天数,如何在考勤表里、快速"√"勾选出来,要求"√"出现的次数和出勤天数一致,且在当月是随机分布的!”

格式如图所示!
点击放大的图片

  看的出来,它是在事后补考勤表!,并且还提到:“不止一个月的,当年1-7月份的考勤表每月都需要补充,看有没高效的办法?”

  这类从结果推导过程,过程还得是随机的且在一定的数值范围内,当前内置函数有两个随机函数:

  • RAND(返回了一个大于等于0且小于1的平均分布的随机实数)
  • RANDBETWEEN(返回位于两个指定数之间的一个随机整数)

  看来都不能直接解决这个问题。

  在VBA的基础知识的第14章节,介绍函数时提到:"现存的内置函数无法满足特定业务逻辑需求,又需要重复使用这个计算过程时,就需要自己开发函数了。",这类情况非常适合开发自定义函数,它满足开发的一切要素!

运行视频:

源码下载:

描述:

  已知出勤总天数、当月总天数,求一个出勤天数在当月的随机分布(打上"√")。

需求分析:
  • 1、开发并定义一个函数;
  • 2、函数的有两个参数,出勤总天数和当月总天数,默认出勤天数引用单元格值,月总天数手动输入。
VBA实现过程:

  (一个的典型自定义函数步骤)

  • 1.在VBA编辑器中插入模块;
  • 2.Functin关键字声明函数,并制定函数名称和参数;
  • RandCells函数名
  • Day_make参数,单元格,出勤天数的引用
  • Day_month参数,数值,月总天数
  • 3.在函数体内编写计算逻辑(部分需要添加错误处理);
  • 三个错误处理:出勤天数不能超过31天,出勤天数必须是数值,出勤天数不能超过月天数
  • 4.逻辑实现:
  • ①生成一个元素个数为月度总天数、元素值都为空的数组;
  • ②Randomize,初始化随机数生成器,使用它可以让 Rnd 函数在每次运行程序时产生真正不同、不可预测的随机数序列
  • ③Do While循环中,"√"元素个数不能高于出勤天数,Day_random=Int(Day_month *Rnd+1),随机生成一个小于等于当月总天数的数值,INT取整;If数组中该元素不是"√"时Then DateArray(Day_random) = "√",修改为"√",Day_step = Day_step + 1,"√"元素个数累加1;直到循环结束,这时"√"元素个数,随机分布在"月总天数"的数组中;
  • 5.将计算结果赋值给函数名(作为返回值)RandCells = DateArray,数组赋值给函数名。
  • 6.注意,因为结果返回的是一个数组,我们是使用函数时,用数组函数的方法Ctrl+Shift+Enter完成!
示例代码
复制成功!
1

Function RandCells(Day_make As Range, Day_month As Integer) As Variant
'---------------------------------------------------------------------
'对参数验证,月总天数(第二个参数)不能超过31天,月总出勤天数(第一个参数)必须是数值,且不能超过当月总天数
    If Day_month > 31 Then
        RandCells = "错误:当月总天数必须是小于31天"
        Exit Function
    End If

    If Not IsNumeric(Day_make.Value) Then
        RandCells = "错误:第一个参数必须是数值"
        Exit Function
    End If

    If Day_make.Value > Day_month Then
        RandCells = "错误:超出当月日期数"
        Exit Function
    End If

'-----------------------------------------------------------------------
'逻辑实现
    Dim DateArray() As String
    ReDim DateArray(1 To Day_month) '定义一个动态数组

    Dim i As Integer
    For i = 1 To Day_month          '先对数组部署元素,每个都是空值
        DateArray(i) = ""
    Next i

    Randomize                      '初始化随机数生成器
    Dim Day_step As Integer
    Day_step = 0

    Do While Day_step < Day_make.Value   '在出勤天数内循环
        Dim Day_random As Integer
        Day_random = Int(Day_month * Rnd + 1) '随机数值

        If DateArray(Day_random) <> "√" Then
            DateArray(Day_random) = "√"      '随机将√添加到数组中
            Day_step = Day_step + 1
        End If
    Loop

    RandCells = DateArray    '返回水平数组
End Function

请开发者喝杯咖啡 请开发者喝杯咖啡!