Option Explicit
' 从选择单元格中 随机选取n个不同单元格
Private Function sampling(ByVal n As Long)
' 选中单元格总数
Dim totalCellsCnt As Long
' 目标区域 为选择区域与使用区域的交集 防止误选整个工作表造成程序假死
Dim targetRng As Range
' 合并所有随机选取的单元格 再填色
Dim tmpRng As Range
Dim i
Set targetRng = Intersect(Selection, ActiveSheet.UsedRange)
totalCellsCnt = targetRng.Cells.Count
' 如果总数小于等于需要选取目标单元格数
If totalCellsCnt <= n Then
fill targetRng, 6
Else
' 生成 不重复 的随机数 将索引对应的所有单元通过Union选取
For Each i In generateNRndNr(1, totalCellsCnt, n)
If tmpRng Is Nothing Then
Set tmpRng = targetRng.Cells(i)
Else
Set tmpRng = Union(tmpRng, targetRng.Cells(i))
End If
Next i
' 填色
fill tmpRng, 6
End If
End Function
' 将目标范围填色
Private Function fill(ByRef rng As Range, ByRef colorIdx As Long)
Selection.Interior.ColorIndex = -4142
rng.Interior.ColorIndex = colorIdx
End Function
' 生成n个不重复的随机数, 范围 大于 start 小于 ende
Private Function generateNRndNr(ByRef start As Long, ByRef ende As Long, ByRef n As Long) As Variant
If n < ende - start + 1 Then
ReDim res(0 To n - 1)
Dim i
Dim cnt As Long
' 数据结构 之 字典, 字典的索引的惟一性 保证返回5个惟一值
Dim d As Object
Set d = CreateObject("scripting.dictionary")
' 字典索引数目小于 所要求数目时 进行取值 并存入 索引(键)
' 由于值不重要 统一设为1
Do While d.Count < n
d(start + Int(Rnd * (ende - start))) = 1
Loop
End If
generateNRndNr = d.Keys
End Function
Sub main()
sampling 5
End Sub
上期代码。今天是又农历春节,首先祝愿大家新春快乐!圣诞跟春节都不能阻挡更新的日常。
上期练习介绍了Excel中的随机模式。代码本身并没有什么疑难之处。关于 字典(dictionary) 这种数据结构我们之后会有详细介绍,此处初步了解即可。请亲手敲一遍代码。
今天把其他常用函数说完。
请看 对象浏览器 中 DateTime 模块
其中 重点掌握 DateSerial
Function DateSerial(Year As Integer, Month As Integer, Day As Integer)
三个参数分别为年、月、日。请注意,月、日的参数可以为零或负数。
例如,
DateSerial(2018, 2, 0)
表示2018年1月31日。 注意此种技巧。
另一个函数 weekday 取得对应日期的星期数,默认第一天为周日
Function Weekday(Date, [FirstDayOfWeek As VbDayOfWeek = vbSunday])
取得当天星期数可以采用下列方法
? weekday(date,vbMonday)
date为返回当前系列日期的方法, vbMonday 将周一设定为每周第一天 。 同理,now返回当前系统时间。
例子 2.7.1 发薪日为每月最后一个周五, 函数签名为
Private Function payDay(ByVal y As Integer, ByVal m As Integer) As Date
参数y为年, m为月,返回值为该月发薪日
Private Function payDay(ByVal y As Integer, ByVal m As Integer) As Date
' 最后一天
Dim d As Date
' 星期数
Dim wd As Integer
d = DateSerial(y, m + 1, 0)
wd = Weekday(d, vbMonday)
' 星期数与对应天数关系
' 1-> -3 2-> -4 3-> -5 4 -> -6 5 -> 0 6 -> -1 7-> -2
payDay = DateAdd("d", IIf(wd >= 5, 5 - wd, -2 - wd), d)
End Function
代码本身没有什么难度, DateAdd可以查看API, 其实也可以写成
payDay = DateAdd("d", IIf(wd >= 5, 5 - wd, -2 - wd), d)
两代码功能相同
payDay = DateSerial(y, m + 1, IIf(wd >= 5, 5 - wd, -2 - wd))
再来看Information模块
主要是用来判断参数类型 的Is-类函数
之前我们已经用过isArray, isEmpty 其他函数我们在后续项目中进行介绍,由于用法极其简单目前只需了解。
最后说一下Conversion转换模块
用于不同数据类型之间转换,常用的如cDbl转换为双精度Double, cInt转为整型Int, cDate转为日期Date,转字符串一般直接用 "" & 也可以采用Cstr。
以上是VBA常用内置函数的全部内容,以上这些函数适用于所有Office产品。也就是说只要不涉及Excel特定的对象模型,在Excel VBA 下编写的程序可以完美兼容于其他Office程序。
从下一期开始,我们将开始系统介绍 对象模型的属性和方法。对于函数以及流程控制部分的示例程序请大家再动手试试。我们掌握知识越多,对于以前的知识或许会有一种新的认识,对程序编写的直觉感也就越强烈。其实编程到最后就是一种肌肉记忆。
有任何问题请在下方留言。
本专栏所有文章著作权归属本人。未经本人书面许可,除知乎日报外,任何人不得转载。