Excel精英培训网

 找回密码
 注册
数据透视表40+个常用小技巧,让你一次学会!
楼主: shzzhy

[已解决]求爱疯老师再出手帮忙“如何自动插入空行并计算平均数”

[复制链接]
发表于 2016-12-12 18:42 | 显示全部楼层
shzzhy 发表于 2016-12-12 17:01
  我还是没搞明白,空行是如何添加上去了?
  以“插入空行并求平均值(20160501 求平均问题)9.rar” ...

Option Explicit

Dim arr()                   '数据源
Dim arrResult()             '结果
Dim NotRecord As Integer    '非记录(指平均行或空白行)
Dim Record As Integer       '记录
Const LineCount = 20        '行数 = 多行记录 + 1行平均值

'主程序
Sub test()
    Dim i As Integer, j As Integer

    Sheets("原始数据表").Select
    '    arr = Range("a1").CurrentRegion.Value
    arr = Range("a1:ab" & Range("b65536").End(3).Row).Value
    ReDim arrResult(1 To UBound(arr) * LineCount, 1 To UBound(arr, 2))
    NotRecord = 0
    Record = 0

    For i = 2 To UBound(arr)
        '如果本行和上行不同,则处理平均行
        If i > 2 And arr(i, 4) <> arr(i - 1, 4) Then Call AverageLine(i)

        '某个产品进行添加记录
        Record = Record + 1
        If Record < LineCount Then
            For j = 1 To UBound(arr, 2)
                '结果的行号 = 累计的记录数 + 累计的非记录行数
                arrResult(i + NotRecord, j) = arr(i, j)
            Next j
        End If
    Next i
    '最后一个产品的平均行,单独处理
    Call AverageLine(i)

    Sheets(2).Activate
    Cells.Clear
    Range("F:R").NumberFormat = "0.0"
    Range("Z:AB").NumberFormat = "0.00"
    Range("a1").Resize(i + NotRecord, UBound(arrResult, 2)) = arrResult     '结果
    Range("a1").Resize(1, UBound(arr, 2)) = Application.Index(arr, 1, 0)    '标题
    Range("a1").Select
    Call FillColor(LineCount, UBound(arr, 2)) '可选
End Sub

'处理平均行
Sub AverageLine(iData)
    Dim dic As Object               '字典,用于文本型产品的计数
    Dim ProductAvg As Long          '产品的平均行行号
    Dim ProductSum As Double        '数字型产品的和
    Dim ProductCount As Integer     '产品的累计次数
    Dim ProductColumn As Integer    '产品的参照列号
    Dim i As Integer, j As Integer, startRow As Integer, endRow As Integer

    Set dic = CreateObject("scripting.dictionary")
    NotRecord = NotRecord + (LineCount - Record)    'LineCount - Record表示非记录数,即平均行和空白行
    ProductAvg = iData + NotRecord - 1    '某产品的平均行行号 = 累计记录数 + 累计非记录数 - 1
    startRow = ProductAvg - LineCount + 1
    endRow = ProductAvg - 1

    '从第6列(株高cm),到最后1列(经济系数),求各产品的平均值
    For j = 6 To UBound(arr, 2)
        '1)清零
        ProductSum = 0: ProductCount = 0: ProductColumn = 0: dic.RemoveAll

        '2)求和
        For i = startRow To endRow
            '如果产品的值非空
            If arrResult(i, j) <> "" Then
                '如果产品的值是数字
                If IsNumeric(arrResult(i, j)) Then
                    '累计产品值的和
                    ProductSum = ProductSum + arrResult(i, j)
                End If
                '更新终止排号
                arrResult(ProductAvg, 2) = arrResult(i, 2)
            End If
        Next i

        '3)求次数
        '更新产品的参照列号
        Select Case j
        Case 10, 14
            ProductColumn = 16
        Case Else
            ProductColumn = j
        End Select
        '求和的列与求次数的列,因为可能不一样,所以必须再循环
        For i = startRow To endRow
            '如果产品的值非空
            If arrResult(i, ProductColumn) <> "" Then
                '如果产品的值是数字
                If IsNumeric(arrResult(i, ProductColumn)) Then
                    '数字型产品的累计次数
                    ProductCount = ProductCount + 1
                Else
                    '文本型产品的累计次数
                    dic(arrResult(i, ProductColumn)) = dic(arrResult(i, ProductColumn)) + 1
                End If
            End If
        Next i

        '4)求平均值
        If ProductCount Then arrResult(ProductAvg, j) = ProductSum / ProductCount   '数字型 = 和 / 次数
        If dic.count Then arrResult(ProductAvg, j) = getItem(dic.keys, dic.items)   '文本型 = 最多次数的条目
    Next j

    '处理前5列
    arrResult(ProductAvg, 1) = ""                                                               'A列,统计号
    arrResult(ProductAvg, 2) = "  " & arrResult(startRow, 2) & "-" & arrResult(ProductAvg, 2)   'B列,排号
    arrResult(ProductAvg, 3) = "平均"                                                           'C列,材料序号2014年
    arrResult(ProductAvg, 4) = arrResult(startRow, 4)                                           'D列,材料名称
    arrResult(ProductAvg, 5) = "平均"                                                           'E列,株号

    Record = 0
End Sub

'自定义函数:最多次数的条目
Function getItem(k, t) As String
    Dim i As Integer
    Dim temp As Integer     '最大次数
    Dim Id As Integer       '最大次数的下标
    For i = 0 To UBound(k)
        'k是条目的数组,t是条目次数的数组
        If temp < t(i) Then
            temp = t(i)     '最大次数
            Id = i          '最大次数的下标
        End If
    Next i
    getItem = k(Id)    '最大次数下标对应的条目
End Function

'将结果表里每种材料名称的平均行填充颜色
Sub FillColor(LineCount, c)
    Dim r, i
    Sheets(2).Activate
    r = Range("b65536").End(xlUp).Row
    For i = r To 2 Step -LineCount
        Range(Cells(i, 1), Cells(i, c)).Interior.ColorIndex = 15
    Next i
End Sub

插入空行并求平均值(20160501 求平均问题)10.rar (97.58 KB, 下载次数: 8)
excel精英培训的微信平台,每天都会发送excel学习教程和资料。扫一扫明天就可以收到新教程
回复

使用道具 举报

 楼主| 发表于 2016-12-14 16:10 | 显示全部楼层
多谢爱疯老师,已测试,非常好用。我再在其他数据上应用下,看不同表格上否会有不同。再次感谢!!!
回复

使用道具 举报

 楼主| 发表于 2016-12-15 13:11 | 显示全部楼层
爱疯 发表于 2016-12-12 18:42
Option Explicit

Dim arr()                   '数据源

  爱疯老师好,你帮忙编的程序已学习很长时间了,虽不会写,但根据其中的注释和我的学习也明白了一部分。基于这个程序,根据现在表格的实际情况又做了些改动,但老是报错,通不过,请爱疯老师帮忙看看是什么问题?

鲜籽考种平均-测试.zip

76.04 KB, 下载次数: 4

回复

使用道具 举报

发表于 2016-12-15 14:10 | 显示全部楼层
shzzhy 发表于 2016-12-15 13:11
  爱疯老师好,你帮忙编的程序已学习很长时间了,虽不会写,但根据其中的注释和我的学习也明白了一部分 ...

    Cells.SpecialCells(xlCellTypeConstants, 16).Delete    '清除 错误常量


最开始,加一句。
用于清除原始数据里存在的错误值(比如,M82,M182,M221),再执行就不报错了。

鲜籽考种平均2-测试.rar (73.96 KB, 下载次数: 4)
回复

使用道具 举报

 楼主| 发表于 2016-12-15 15:05 | 显示全部楼层
本帖最后由 shzzhy 于 2016-12-15 15:19 编辑
爱疯 发表于 2016-12-15 14:10
Cells.SpecialCells(xlCellTypeConstants, 16).Delete    '清除 错误常量

  爱疯老师,运行结果不对呀:程序把每一行后面均增加了空行并求了平均;清除了错误后,它又给斌了新的值。
回复

使用道具 举报

 楼主| 发表于 2016-12-15 15:09 | 显示全部楼层
爱疯 发表于 2016-12-15 14:10
Cells.SpecialCells(xlCellTypeConstants, 16).Delete    '清除 错误常量

  我利用“鲜籽考种平均-测试.zip”这个文件,将M82,M182,M221的错误值去掉后可以运行。但在C列,即“2016年排号”这列只能出现“37-”、“16-”等,不能出现正确的“37-38”、“16-17”等。其它的目前未发现错误。
回复

使用道具 举报

发表于 2016-12-15 15:44 | 显示全部楼层
shzzhy 发表于 2016-12-15 15:09
  我利用“鲜籽考种平均-测试.zip”这个文件,将M82,M182,M221的错误值去掉后可以运行。但在C列,即“ ...

鲜籽考种平均3-测试.rar (74.84 KB, 下载次数: 8)
回复

使用道具 举报

 楼主| 发表于 2016-12-15 23:13 | 显示全部楼层

       哦,多谢老师出手。是我没交待清楚。
    1、不论前5列的顺序如何,首先是对“品种名称”进行排序,品种就好比是商店里的产品,我们要先把相同的产品归为一类,排在一起进行计算;“排号”就相当于不同的区域,在同一类产品中,再按区域进行归类、排序;第三才排列小区号、单株号。“插入空行并求平均值(20160501 求平均问题)10”这个文件中也是按这种方式排好序的。
    2、你解释的“因为排号的位置,所以排号功能没有执行”,说明排号对位置有要求,我将前五列的顺序调整了下,程序就可正常运行了,行标连接也正常了。我是想知道,程序中哪个语句控制的是排号的位置,能否在程序中进行调整呢?我反复看了多遍也没发现。
    3、同样,对D列也是有要求的,必须要先排序,目前“鲜籽考种平均-测试”我是按B列排序的,我试了下程序也可以用,计算结果也是对的。反倒是“鲜籽考种平均3-测试”结果不对了。
回复

使用道具 举报

发表于 2016-12-16 08:22 | 显示全部楼层
shzzhy 发表于 2016-12-15 23:13
哦,多谢老师出手。是我没交待清楚。
    1、不论前5列的顺序如何,首先是对“品种名称”进行排 ...

"插入空行并求平均值"中的"材料名称",首先排序,是吗?

"材料名称"对应"鲜籽考种平均"中的哪一列?

回复

使用道具 举报

 楼主| 发表于 2016-12-16 09:01 | 显示全部楼层
爱疯 发表于 2016-12-16 08:22
"插入空行并求平均值"中的"材料名称",首先排序,是吗?

"材料名称"对应"鲜籽考种平均"中的哪一列?

                  "插入空行并求平均值"中的"材料名称",是首先排序
统计号
排号
材料序号2014年
材料名称
株号



  “鲜籽考种平均-测试”中的“2016年品种名称”与上面的“材料名称”是一致的,也是首先排序
统计号
2016年排号
2016年小区号
2016年品种名称
2016年单株号

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|Excel精英培训 ( 豫ICP备11015029号 )

GMT+8, 2024-5-7 10:29 , Processed in 0.152319 second(s), 10 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表