|
我花了6个小时读懂了大师的代码, 为了避免健忘我这里做个详细的叙述,注意教课书是不会说的这么细的.
Sub dit3()
Application.Volatile 定义函数为易失, 已使 其在单元格改变时,自动更新数据.
On Error Resume Next 如果出现错误则继续,因为字典避免重复,重复就装不进去,所以必须让程序出了错误continue到
下一次循环。
Dim answer As String 定义字符串变量。
Dim a As String
Dim Arr11, LastRow, LastRow2, Arr, Arr1 定义整形变量。
Dim Arr21(), Arr22() 定义2个数组。
Set D = CreateObject("scripting.dictionary") 定义2个字典对象,这个字典和现实中的字典几乎一样,健无重复。
Set d1 = CreateObject("scripting.dictionary")
With Sheet2 注意,sheet2这个表示为了装入字典而写好的2维表(航班号 承运人)key/value pair。
LastRow = .Range("A65536").End(xlUp).Row 找到这个作为字典源的最后以行数据。
Rem lastrow 的值为 2001 sheet2 因为有2000行数据,所以加上标题 输出值为 2001。
注意以下不好理解了:
Arr11 = .Range("A2:B" & LastRow) 把2列2000行的字典用根数据作为 2维数组装入 2维数组 Arr11。
Rem MsgBox UBound(Arr11) 2000 下届为1 :这里debug.print 输出了数组的上,下届以方便理解。
End With
既然数据已经装入了数组,则现在开始完数组,以在内存中完成任务。
For i = 1 To UBound(Arr11) 注意Arr11 的内容 实际为 sheet2!A2:B2000 (只是作为基准的输入字典用的根key/value数据表)注意实际 For i = 1 to 2000
If Not D.Exists(Arr11(i, 1)) Then 这是为了防止根数据存在相同的航班号而做的去除重复处理。
n = n + 1 如果能装入字典的话 则 计数器就 +1 。
D(Arr11(i, 1)) = n 左边是不重复的航班号,右边是自然数。
ReDim Preserve Arr21(1 To 2, 1 To n) 定义新的可变数组,并保留原值。定义了一个 1-2 行,1 到 n 列的 2维数组。
Arr21(1, n) = Arr11(i, 1) 数组之间的负值开始了, 右边的其实是原表格中第一列的不重复的航班号,
在向左边的负值中,其实反转了数据 (行列互换了) 注意现在数组第一行为不重复的航班号了。
Arr21(2, n) = Arr11(i, 2) 注意右边的其实是原表格的写好的某个航班号的实际承运人列表。
行列互换后向左边负值。注意这个 i 不是自然数,因为前面有过字典判断所以 如果
有重复的话 i 会自动跳过重复航班号的行数。
End If
Next
Rem n的值为2000 是字典对的 个数。sheet2
Rem 以上产生了一个不重复的数组 Ar21 上面是航班号,下面是承运人,不重复数组已经搞定。
Rem Arr21 留着以后用 是一个第一行是航班号,第二行是承运人的两行表。且删除了重复。
这里已经大功告成了一半。
简单的说数据源曾是通过2层循环执行判断的,第一层循环,在每个单元格内,第二层循环在 所有那一例里循环。
看过 盗梦空间a吗? 就是 tiered dream in a dream
Rem 下面到了数据源层面
With Sheet1
LastRow2 = .Range("A65536").End(xlUp).Row 找到数据源层的最后一行。
Rem MsgBox LastRow2 求值为1001 sheet
Arr = .Range([A2], "A" & LastRow2) 把需要判断的那个列整个装入 1维数组。
Rem MsgBox LBound(Arr)
Rem Ubound(Arr) 一维 数组上届为 1000 下届 为1
End With
ReDim Arr22(1 To UBound(Arr), 1 To 1) 注意Arr22 是第一次出现,他的目的是,为了装入 以上Arr载入的一纬数据源。
Rem 把已经定义好的字典定义成与数据源相同的高度且保留值 ,是多行1列的数组。
Rem Arr 为实际数据源的1维数组
For i = 1 To UBound(Arr)
Rem 遍历数据源 1 to 1000 数据源重要
Arr1 = Split(Arr(i, 1), "-")
Rem 将数据源每行分割后给数组 Arr1 ,将每个单元格的数据 用 - 拆分后放入数组Arr1。
For j = 0 To UBound(Arr1)
cy = Arr21(2, D(Arr1(j))) 注意Arr21 的第2行是实际承运人, 注意这个D()字典的值是自然数。
所以根据2维数组的 行 列 号 即可以返回实际的值,也就是 承运人是谁?
Rem 由于字典的值是列数所以根据航班号可以返回字典的值也就是列数 所以cy已经返回承运人了
If Not d1.Exists(cy) Then 注意字典d1 是第一次出现,注意那个 not 也就是说只有字典的 值不存在实才往下执行
否则跳过。
answer = answer + Arr21(2, D(Arr1(j))) & " " 把答案 Arr21 的第2行 第 n 列 恰好是实际承运人(答案)负值给anser.
n1 = n1 + 1 负值成功一次 自然数+1 。
d1(cy) = n1 注意字典的值是自然数。 让字典d1 的值为自然数n1。
End If
Next j
Rem n1 为被分割的航班号在能在字典中能查到的不重复的个数。
Rem 如果n1 即航班号出现过那么 字典肯定就不能在输入键了
Rem 这样巧妙的删除了重复
Arr22(i, 1) = answer Arr22 的行数与sheet 1数据源相同,1为第一列。 注意 i 是跳跃的自然数(行数)
结果是对符合条件的行进行 判断结果注释。
answer = "" 释放变量
n1 = 0 释放变量
d1.RemoveAll 释放变量
Next i 选换下一行。
Sheet1.[b2].Resize(UBound(Arr22), 1) = Arr22 将数组Arr22 一次写入数据源sheet1 判断列单元格。
End Sub
|
评分
-
查看全部评分
|