ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: 彭希仁

[讨论]有点难度的汇总

[复制链接]

TA的精华主题

TA的得分主题

发表于 2007-11-30 13:44 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册

彭,提供的数据用1.5秒左右,ldy888提供60000行数据用90秒左右,太慢了!都有点不好意思传上来,但我想,必究是学习交流.

总的来说,也能用自己的理解,完成了这一任务.

学无止境!!!努力着!!!


Sub 泓()
Application.ScreenUpdating = False
Dim dic As Object, dic1 As Object, cel, arr, brr, crr, temp()
Dim i&, j&, k&, l&, sum&, sum1&, n&, m&, p&, sp$, spl$, xxx$, aa#
aa = Timer
Set dic = CreateObject("Scripting.Dictionary")
Set dic1 = CreateObject("Scripting.Dictionary")
Sheet3.Range("a3:k10000").ClearContents
n = Cells(65536, 1).End(xlUp).Row
cel = [b2].Resize(n, 1)
For i = 1 To UBound(cel)
    dic(cel(i, 1)) = ""
Next
arr = dic.keys: dic.RemoveAll
cel = [c2].Resize(n, 1)
For i = 1 To UBound(cel)
    dic(Replace(cel(i, 1), " ", "")) = ""
Next
brr = dic.keys: dic.RemoveAll
cel = [a2].Resize(n, 1)
For i = 1 To UBound(cel)
    dic(cel(i, 1)) = ""
Next
crr = dic.keys: dic.RemoveAll
For i = 0 To UBound(arr) - 1
    For j = 0 To UBound(brr) - 1
        For k = 0 To UBound(crr) - 1
            dic.Add arr(i) & "," & brr(j) & "," & crr(k), 0
        Next
    Next
Next
cel = [a2].Resize(n - 1, 3)
For p = 1 To n - 1
    s = cel(p, 2) & "," & Replace(cel(p, 3), " ", "") & "," & cel(p, 1)
    If dic.exists(s) Then dic.Item(s) = dic.Item(s) + 1
Next
ReDim temp1(UBound(brr) - 1)
ReDim temp2(1 To 6)
For i = 1 To UBound(arr)
    sum1 = 0
    For j = 1 To UBound(brr)
        sum = 0
        For k = 1 To UBound(crr)
            m = m + 1
            sum = sum + Application.Index(dic.items, m)
            ReDim Preserve temp(k - 1)
            temp(k - 1) = Application.Index(dic.items, m) + 0.0001 * (10000 - m)
        Next
        sp = Split(Application.Index(dic.keys, m), ",")(1)
        For l = 1 To 3
            xxx = WorksheetFunction.Large(temp, l)
            xx = IIf(Len(Split(xxx, ".")(1)) = 4, Split(xxx, ".")(1), Split(xxx, ".")(1) * 10 ^ (4 - Len(Split(xxx, ".")

(1))))
            temp2(l * 2 - 1) = Split(Application.Index(dic.keys, 10000 - xx), ",")(2)
            temp2(l * 2) = Application.Index(dic.items, 10000 - xx)
            If temp2(l * 2) = 0 Then temp2(l * 2) = "": temp2(l * 2 - 1) = ""
        Next
        spl = Split(Application.Index(dic.keys, m), ",")(0)
        sum1 = sum1 + sum: temp1(j - 1) = sum + 0.001 * j
        dic1.Add sp, Array(j, spl, sp, sum, 0, temp2(1), temp2(2), temp2(3), temp2(4), temp2(5), temp2(6))
    Next
    cel = Application.Transpose(Application.Transpose(dic1.items))
    dic1.RemoveAll
    For l = 1 To UBound(brr)
        xxx = WorksheetFunction.Small(temp1, l)
        xx = IIf(Len(Split(xxx, ".")(1)) = 3, Split(xxx, ".")(1), Split(xxx, ".")(1) * 10 ^ (3 - Len(Split(xxx, ".")(1))))
        dic1.Add l, Array(l, cel(xx, 2), cel(xx, 3), cel(xx, 4), cel(xx, 4) / sum1, cel(xx, 6), cel(xx, 7), cel(xx, 8), cel

(xx, 9), cel(xx, 10), cel(xx, 11))
    Next
    dic1.Add UBound(brr) + 1, Array(l, cel(xx, 2), "合计", sum1, 1, "", "", "", "", "", "")
    If Len(Sheet3.[a3]) <> 0 Then n = Sheet3.Cells(65536, 1).End(xlUp).Row + 1 Else n = 3
    Sheet3.Cells(n, 1).Resize(dic1.Count, 11) = Application.Transpose(Application.Transpose(dic1.items))
    dic1.RemoveAll
Next
Set dic = Nothing
Set dic1 = Nothing
Sheets("报表").Activate
Application.ScreenUpdating = True
MsgBox "Total:=" & Format(Timer - aa, "0.0000") & "s"

End Sub

TA的精华主题

TA的得分主题

发表于 2007-11-30 14:01 | 显示全部楼层
QUOTE:

好啊
[此贴子已经被作者于2007-11-30 14:02:39编辑过]

ORca49Ac.rar

215.22 KB, 下载次数: 7

[讨论]有点难度的汇总

TA的精华主题

TA的得分主题

 楼主| 发表于 2007-11-30 14:04 | 显示全部楼层
QUOTE:
以下是引用ldy888在2007-11-30 12:45:47的发言:

自定义数据类型倒是个很好的想法。但是是如何定义才是速度的关键。这一方面要求很高(我是没这水平的)。

字典和数组我都写过类似要求的代码,算是比较了解两者的差别。

用字典完成工作,写代码的时间短一些,用数组时间长一些,因为要考虑的因素多很多。

一个疏忽就会导致结果错误,(彭兄的新代码,就有一个瑕疵,在最后一行出错)

大多数情况下,字典完成的代码,可以用数组更快的完成,前提是写代码的水平高。

我处理这类问题通常都是先用字典,如果速度很不理想(创建了N多的字典),再花更多的时间换成数组。

通用的东西只在某一方面做的较理想,字典就是微软提供的一个通用的类,字典处理重复值就很快。

但用在这里,不是最快的(但代码完成的时间是最早的,不用考虑太多的因素)。

做这道题60000行的汇总,个人感觉应该能在0.1秒内完成计算(没吃过猪肉,还没见过猪跑吗)。

这个汇总统计很有实用价值,希望高人引起兴趣。

顶!!!

ldy888兄,由于开始用ADO写的时候最后一行出错,所以用排序加数组做的时候专门验证了一下,不知你是用什么数据测的结果能否提供上来?用我的数据测试,结果是正确的,而你的字典算出的结果不知何故少了1015

图片点击可在新窗口打开查看点击浏览该文件

TA的精华主题

TA的得分主题

发表于 2007-11-30 15:18 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册

绝对不搞笑,而是一定可以达到!!

并且速度还可以!!

其实公式是OFFICE里自带的,与OFFICE的结合很好,速度比VBA做二次开发应该要好些

TA的精华主题

TA的得分主题

发表于 2007-11-30 16:13 | 显示全部楼层
QUOTE:
QUOTE:
QUOTE:
以下是引用彭希仁在2007-11-30 14:04:15的发言:

ldy888兄,由于开始用ADO写的时候最后一行出错,所以用排序加数组做的时候专门验证了一下,不知你是用什么数据测的结果能否提供上来?用我的数据测试,结果是正确的,而你的字典算出的结果不知何故少了1015

图片点击可在新窗口打开查看点击浏览该文件

彭兄请检查 你的代码汇总后 FK 和 fk  机型的情况 

 

 

还有最后一两行

15qjk触摸屏失灵46343.5%广东188湖南40黑龙江38
16qjk触摸屏失灵10.1%      

TA的精华主题

TA的得分主题

发表于 2007-11-30 16:20 | 显示全部楼层

Ihoggzmv.rar (242.06 KB, 下载次数: 27)

原来做的两层字典也不知道在那里出错,不想找了

请用 三层字典 核对吧,不用对原数据排序。速度和 两层差不多

彭兄和我原来的代码都没有对大小写 进行处理,都要依靠excel的排序功能,所以各有各的错误。

我写的三层字典结果应该正确。

[此贴子已经被作者于2007-11-30 16:28:18编辑过]

TA的精华主题

TA的得分主题

发表于 2007-11-30 16:39 | 显示全部楼层
QUOTE:
以下是引用morganwong在2007-11-30 15:18:03的发言:

绝对不搞笑,而是一定可以达到!!

并且速度还可以!!

其实公式是OFFICE里自带的,与OFFICE的结合很好,速度比VBA做二次开发应该要好些

morganwong 兄估计没看清题意

你提供的函数,没有实现 分段合计,分段统计百分比,分行统计前三名

你的汇总表中 机型 故障现象 栏 是手打的 你如何得知有什么 机型 和 故障?

你的 地区数量 栏 中的 地区是手打的,你如何得知哪个地区的故障最多?

相信你能用函数算出来,但写这个函数不会比写VBA容易

TA的精华主题

TA的得分主题

发表于 2007-11-30 16:50 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
支持ldy888,招招精彩!

TA的精华主题

TA的得分主题

发表于 2007-11-30 17:02 | 显示全部楼层
QUOTE:
以下是引用泓()在2007-11-30 16:50:52的发言:
支持ldy888,招招精彩!

呵呵 彭兄的场一定要捧,他教会我写递归了

TA的精华主题

TA的得分主题

发表于 2007-11-30 17:19 | 显示全部楼层

大家看一下,取前三地区的排序中,那儿出了问题?从"数据显示"那段来看,数据都对了,但下面注释掉选择排序出了什么问题,大家帮忙诊断一下!!!.

Option Explicit
'-----------------------
Type tsf
    name As String
    sum As Integer
End Type
'-----------------------
Type tgz
    name As String
    sum As Long
    sfsum As Byte
End Type
'-----------------------
Type tjx
    name As String
    sum As Long
    gzsum As Byte
End Type
'----------------------
Dim data(1 To 50) As tjx, data1(1 To 50, 1 To 250) As tgz, data2(1 To 50, 1 To 200, 1 To 100) As tsf
Dim over As Boolean, over1 As Boolean, over2 As Boolean
Dim sf As String, jx As String, gz As String

Sub erw()
    Dim a, arr, sw
    Dim swt As tsf
    Dim i As Long, m As Long, k As Integer, kk As Integer, jxsum As Byte, j As Byte, temp As Long
    Dim list(), pp As Long, t As Long
    Erase data
    Erase data1
    Erase data2
    a = Timer
    With Worksheets("数据")
        i = .Range("a65536").End(xlUp).Row
        arr = .Range("a2:c" & i)
    End With
    m = UBound(arr, 1)
    ReDim list(1 To m, 1 To 11)
    jxsum = 0
    For i = 1 To m
        over = False
        sf = Trim(arr(i, 1))
        jx = Trim(arr(i, 2))
        gz = Trim(arr(i, 3))
        For j = 1 To jxsum
            If data(j).name = jx Then
                over = True
                data(j).sum = data(j).sum + 1
                checkgz j
                Exit For
            End If
        Next
        If over = False Then
            jxsum = jxsum + 1
            data(jxsum).name = jx
            data(jxsum).sum = data(jxsum).sum + 1
            data(jxsum).gzsum = data(jxsum).gzsum + 1
            data1(jxsum, data(jxsum).gzsum).name = gz
            data1(jxsum, data(jxsum).gzsum).sum = data1(jxsum, data(jxsum).gzsum).sum + 1
            data1(jxsum, data(jxsum).gzsum).sfsum = data1(jxsum, data(jxsum).gzsum).sfsum + 1
            data2(jxsum, data(jxsum).gzsum, data1(jxsum, data(jxsum).gzsum).sfsum).name = sf
            data2(jxsum, data(jxsum).gzsum, data1(jxsum, data(jxsum).gzsum).sfsum).sum = data2(jxsum, data(jxsum).gzsum, data1(jxsum, data(jxsum).gzsum).sfsum).sum + 1
        End If
    Next

    '数据显示------------------------------------------------------------------
    pp = 0
    For i = 1 To jxsum
    For m = 1 To data(i).gzsum
    For k = 1 To data1(i, m).sfsum
    pp = pp + 1
    Cells(pp, 4) = data(i).name & data1(i, m).name & " - " & data1(i, m).sum
    Cells(pp, 5) = data2(i, m, k).name
    Cells(pp, 6) = data2(i, m, k).sum
    Next
    Next
    Nex
    '--------------------------------------------------------------------------
    ' 下面那儿出了问题!
''    pp = 0
''    For i = 1 To jxsum
''    For m = 1 To data(i).gzsum
''    pp = pp + 1
''    list(pp, 1) = m
''    list(pp, 2) = data(i).name
''    list(pp, 3) = data1(i, m).name
''    list(pp, 4) = data1(i, m).sum
''    list(pp, 5) = list(pp, 4) / data(i).sum
''    '---------------------------------------------
''    For k = 1 To data1(i, m).sfsum - 1
''    temp = k
''    For kk = k + 1 To data1(i, m).sfsum
''    If data2(i, m, kk).sum > data2(i, m, temp).sum Then
''    temp = kk
''    End If
''    Next
''    swt = data2(i, m, k)
''    data2(i, m, k) = data2(i, m, temp)
''    data2(i, m, temp) = swt
''    Next
''    '--------------------------------------------------
''   If data1(i, m).sfsum > 3 Then
''         sw = 3
''        Else
''         sw = data1(i, m).sfsum
''   End If
''   For temp = 1 To sw
''   list(m, 2 * temp + 4) = data2(i, m, temp).name
''   list(m, 2 * temp + 5) = data2(i, m, temp).sum
''   Next
''   Next
''   pp = pp + 1
''    list(pp, 1) = m
''    list(pp, 2) = data(i).name
''    list(pp, 3) = "合计"
''    list(pp, 4) = data(i).sum
''   Next
'    Worksheets("报表").Range("l3").Resize(pp, 11) = list

'    '-------------------------------------------------------------------
'

   
     MsgBox Format(Timer - a, "0.00") & "_" & jxsum
    
End Sub
Sub checkgz(n As Byte)
    over1 = False
    Dim i As Byte
    For i = 1 To data(n).gzsum
        If data1(n, i).name = gz Then
            over1 = True
            data1(n, i).sum = data1(n, i).sum + 1
            checksf n, i
            Exit For
        End If
    Next
    If over1 = False Then
       data(n).gzsum = data(n).gzsum + 1
       data1(n, data(n).gzsum).name = gz
       data1(n, data(n).gzsum).sum = data1(n, data(n).gzsum).sum + 1
       data1(n, data(n).gzsum).sfsum = data1(n, data(n).gzsum).sfsum + 1
       data2(n, data(n).gzsum, data1(n, data(n).gzsum).sfsum).name = sf
       data2(n, data(n).gzsum, data1(n, data(n).gzsum).sfsum).sum = data2(n, data(n).gzsum, data1(n, data(n).gzsum).sfsum).sum + 1
    End If
End Sub
Sub checksf(a As Byte, b As Byte)
    over2 = False
    Dim i As Byte
    For i = 1 To data1(a, b).sfsum
        If data2(a, b, i).name = sf Then
            over2 = True
            data2(a, b, i).sum = data2(a, b, i).sum + 1
            Exit For
        End If
    Next
    If over2 = False Then
        data1(a, b).sfsum = data1(a, b).sfsum + 1
        data2(a, b, data1(a, b).sfsum).name = sf
        data2(a, b, data1(a, b).sfsum).sum = data2(a, b, data1(a, b).sfsum).sum + 1
    End If
End Sub

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

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-15 10:11 , Processed in 0.048605 second(s), 9 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

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