sunjing-zxl 发表于 2012-1-4 09:33

[心得]字典第3课作业分析

本帖最后由 sunjing-zxl 于 2012-1-4 10:11 编辑


字典第三课作业,基本属于一类型的题目,我现在以“必做一的效果1”为例子来分析这类题目的思路和做法
效果二的分析在二楼

分析附件:

'这类题三大步:
'第一步:找出新数组的行数和列数(用redim定义数组)
'第二步:找出特殊赋值数据对规律赋值数据进行分析凑数
'第三步:找出循环到该数据的复制行号和列号
'心得:这类题万变不离其中,就是一句话找出规律凑数



Sub 必做1效果1_012_sunjing_zxl()
'定义变量,这个我一般是先写程序,然后后面要用什么变量就加什么。
'当然还有先想思路然后,然后看自己的思路需要什么就一次性定义什么变量
    Dim d As New Dictionary, d1 As New Dictionary, d2 As New Dictionary
    Dim arr, arr1()
    Dim i As Long, j As Long, n As Long, m As Long
'下面两句是一般是程序完成后最后添加
    Range("F1:IV1000").ClearContents '清空,可以说是90%以上VBA程序说必须的
    Range("F1:IV1000").NumberFormatLocal = "@" '自定义单元格格式,有数字当文本用的时候说必须的
'给数组赋值,毫无疑问,我们既然学习了数组就不能再用单元格循环
'不管它三七二十一,先把数据区域赋值给数组再说
    arr = Range("A1:D" & .End(xlUp).Row)
'真正的思路重下面开始了
'第一步:找出我们格式转换后的数据到底有多少行列
'我一般情况不喜欢用ReDim Preserve定义数组,我一贯思路就是先找出
'我们结果数组的总行总列然后直接用ReDim定义数组
'效果1的总行数是规定死了,每个仓库的种类站5行,有多的在列数上扩展
'那么我们计算行就是仓库种类数*5,而计算列呢?不需要找到每个仓库种类的个数。
'只需要最多的一个仓库种类有多少个就行了。而排列是每4组数据换列。而没换一次列是要占用5列。
'所以就用仓库该种类的个数除以4向上取证之后再乘以5就是我们需要的总列数。(而这个数只需要用最
'多的一个个数来计算就行了)
    For i = 2 To UBound(arr)
      d(arr(i, 1)) = d(arr(i, 1)) + 1
    Next i '看这个i循环,不用说这个字典的key是仓库种类,对应的item就是仓库每个种类的个数
    n = WorksheetFunction.Large(d.Items(), 1) '找出一个最大的item值
    m = d.Count '字典key个数及就是仓库种类数
'm*5不就是行数了吗,Abs(Int(-n / 4)) * 5不就是列数了吗
    ReDim arr1(1 To m * 5, 1 To Abs(Int(-n / 4)) * 5) '定义我们的结果数组的范围。
'上面就是第一步,这类题不管三七二十一先把这一步写出绝对没错,而且也是需要的。我反正不喜欢用ReDim Preserve来定义数组
'第二步:本类题目的关键所在
'大家应该都知道做函数用到OFFSET,INDEX等函数就需要凑数,凑出我们说要的数来解决问题,那么我们这类的VBA也是一样--凑数
'下面凑数循环赋值具体思路见附件
    For i = 2 To UBound(arr)
      d1(arr(i, 1)) = d1(arr(i, 1)) + 1
      m = 1 + (d1.Count - 1) * 5
      For j = 1 To 4
            arr1(m, j) = arr(1, j) '特殊标题行的赋值,可以加一个判断(if d1(arr(i, 1))=1 才赋值,否则就不赋值了)
'循环赋值计算的关键(数组凑数赋值)
            arr1(m + ((d1(arr(i, 1)) - 1) Mod 4) + 1, Int((d1(arr(i, 1)) - 1) / 4) * 5 + j) = arr(i, j)
      Next j
    Next i
    Range("F1").Resize(UBound(arr1), UBound(arr1, 2)) = arr1
End Sub

sunjing-zxl 发表于 2012-1-4 10:10

下面在用第一题的效果二来说明一下思路,完全和效果1是一样的。
关键在于凑数Sub 必做1效果2_012_sunjing_zxl()
    Dim d As New Dictionary, d1 As New Dictionary
    Dim d2 As New Dictionary, d3 As New Dictionary
    Dim arr, arr1()
    Dim i As Long, j As Long, n As Long, m As Long
    Range("F1:IV1000").ClearContents
    Range("F1:IV1000").NumberFormatLocal = "@"
    arr = Range("A1:D" & .End(xlUp).Row)
    '统计每个仓库名的个数
    For i = 2 To UBound(arr)
      d(arr(i, 1)) = d(arr(i, 1)) + 1
    Next i
    '添加两个计数器
    n = 1
    m = 0
    '统计每个仓库名所占行数(d2)
    '统计每个仓库名起点行号(d3)
    '行号不固定,列好固定所以需要计算数组的行数
    '由题意(5行是基本行数,超出5行就添加)
    '上面字典的item值是每个仓库的总个数
    '所以RoundUp((d.Items(i) + 1) / 3, 0),就是该仓库需要用的行数,而加上最低行数限制。用max比较取一个最大值即可
    For i = 0 To d.Count - 1
      'd2的item就是key所需要的行数
      d2(d.Keys(i)) = WorksheetFunction.max(WorksheetFunction.RoundUp((d.Items(i) + 1) / 3, 0), 5)
      'd3的item就是key的起点行号
      d3(d.Keys(i)) = n
      '计数器n计算下一个的起点行号
      m = d2(d.Keys(i))
      n = n + m
    Next i
    '最后的n值减1肯定就我们所需要数组的总行数了
    ReDim arr1(1 To n - 1, 1 To 14)
    '规律循环赋值(万变不离其中的凑数)
    For i = 2 To UBound(arr)
      '统计循环点得仓库类别及该类别的个数
      d1(arr(i, 1)) = d1(arr(i, 1)) + 1
      '分析标题需要站一行数据,所以每一类仓库前面5行只能放下14个
      '所以用D1的item值+1来判断是否超出15个,超出15就需要添加行数了
      If d1(arr(i, 1)) + 1 > 15 Then
            m = d3(arr(i, 1)) + 5    '超出5行的起点行号
            n = d2(arr(i, 1)) - 5    '增加的行数
            '用m,n来凑数达到行列变化
            m = (d1(arr(i, 1)) - 15) Mod n + m
            n = Int((d1(arr(i, 1)) - 15) / n) * 5
            For j = 1 To 4
                arr1(m, n + j) = arr(i, j)
            Next j
      'else下面的就不说了 , 和效果1基本一样
      Else
            m = d3(arr(i, 1)) + d1(arr(i, 1)) Mod 5
            n = Int(d1(arr(i, 1)) / 5) * 5
            For j = 1 To 4
                arr1(d3(arr(i, 1)), j) = arr(1, j)
                arr1(m, n + j) = arr(i, j)
            Next j
      End If
    Next i
    Range("F1").Resize(UBound(arr1), UBound(arr1, 2)) = arr1
End Sub

qushui 发表于 2012-1-4 10:51

孙哥辛苦了 很给力啊 赞一个!

EP学员 发表于 2012-1-4 19:59

谢谢分享               

wcymiss 发表于 2012-1-13 09:10

vba这样的思路用的比较少,函数倒是很常见

bbhiox 发表于 2012-2-20 19:31

wcymiss 发表于 2012-1-13 09:10 static/image/common/back.gif
vba这样的思路用的比较少,函数倒是很常见

不断提高并且不断学习

开心萝卜惠州 发表于 2012-4-6 08:00

学习,谢谢分享!
页: [1]
查看完整版本: [心得]字典第3课作业分析