VBA中批量标记Or1-Or100变量重复值的高效实现方案咨询
更优雅高效的重复值标记方案
嘿,这个问题我之前帮同事解决过——用几百条If语句两两判断确实太折磨人了,写起来累不说,运行时要做近5000次比较,效率低得离谱。给你两个亲测好用的优化方案,代码简洁还快:
方案1:用字典(Dictionary)统计频率(推荐)
字典是处理这类重复值问题的利器,它能快速统计每个值的出现次数,而且查找效率是O(1)的,整个流程时间复杂度只有O(n),比两两比较的O(n²)快N倍。
具体步骤:
- 把所有
Or1-Or100的Long值统一存到数组里(如果是从Excel单元格读值,直接读整个区域到数组更高效); - 用字典统计每个值的出现次数;
- 动态设置对应的
Or1x-Or100x布尔变量,只要对应值出现次数>1就设为True。
VBA代码示例:
Sub MarkDuplicateValues() Dim valueDict As Object Set valueDict = CreateObject("Scripting.Dictionary") ' 不用提前引用库,兼容性更好 ' 1. 收集所有Long变量的值到数组(如果是从Excel读,直接用区域赋值更高效) Dim longVals(1 To 100) As Long Dim i As Integer ' 模拟将Or1-Or100存入数组(实际中如果从单元格读,替换成下面的注释行) For i = 1 To 100 longVals(i) = CallByName(Me, "Or" & i, VbGet) ' 动态读取Or1-Or100的值 ' 替代方案:从Excel单元格直接读区域 → longVals = Sheets("你的工作表名").Range("A1:A100").Value Next i ' 2. 统计每个值的出现次数 For i = 1 To 100 If valueDict.Exists(longVals(i)) Then valueDict(longVals(i)) = valueDict(longVals(i)) + 1 Else valueDict(longVals(i)) = 1 End If Next i ' 3. 动态设置对应的布尔变量 For i = 1 To 100 CallByName Me, "Or" & i & "x", VbLet, (valueDict(longVals(i)) > 1) Next i ' 清理对象 Set valueDict = Nothing End Sub
为什么这个方案更好?
- 效率爆炸:从原来的4950次两两比较,变成200次循环操作,运行速度提升几十倍;
- 代码简洁:不用写几百条If语句,新增变量数量(比如到Or200)只要改数字就行;
- 减少Excel交互:如果直接从单元格读区域到数组,避免了100次单独读取单元格的缓慢操作,这也是提升速度的关键。
方案2:排序后找相邻重复值(备选)
如果不想用字典,也可以把数组排序后,通过对比相邻元素来标记重复值,最后再映射回原变量:
Sub MarkDuplicatesWithSort() Dim longVals(1 To 100) As Long Dim originalIndices(1 To 100) As Integer Dim i As Integer, j As Integer Dim temp As Long, tempIdx As Integer Dim isDuplicate(1 To 100) As Boolean ' 1. 初始化数组和原索引 For i = 1 To 100 longVals(i) = CallByName(Me, "Or" & i, VbGet) originalIndices(i) = i Next i ' 2. 冒泡排序(也可以用更高效的排序算法) For i = 1 To 99 For j = i + 1 To 100 If longVals(i) > longVals(j) Then temp = longVals(i) longVals(i) = longVals(j) longVals(j) = temp tempIdx = originalIndices(i) originalIndices(i) = originalIndices(j) originalIndices(j) = tempIdx End If Next j Next i ' 3. 标记重复值 For i = 2 To 100 If longVals(i) = longVals(i - 1) Then isDuplicate(originalIndices(i)) = True isDuplicate(originalIndices(i - 1)) = True End If Next i ' 4. 设置布尔变量 For i = 1 To 100 CallByName Me, "Or" & i & "x", VbLet, isDuplicate(i) Next i End Sub
这个方案的效率比字典稍低,但不用依赖Scripting.Dictionary,适合特殊场景。
内容的提问来源于stack exchange,提问作者Duna
相关产品推荐
相关产品推荐

