ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[讨论]有点难度的汇总

[复制链接]

TA的精华主题

TA的得分主题

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

哈哈,太不可思以了,我的程序竟然越乱越快!,没打乱数据之前

字典套字典,1.7秒

排序加数组,0.8秒

我的程序也是,0.8秒

打乱数据之后,竟然只要0.5秒!!

TA的精华主题

TA的得分主题

发表于 2007-11-30 18:26 | 显示全部楼层

贴上源代码,欢迎测试,数据最好不要排序,越乱越好!

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
    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) = Round(list(pp, 4) / data(i).sum, 2)
    '---------------------------------------------
    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
    If temp <> k Then
    swt = data2(i, m, k)
    data2(i, m, k) = data2(i, m, temp)
    data2(i, m, temp) = swt
    End If
    Next
    '--------------------------------------------------
   If data1(i, m).sfsum > 3 Then
         sw = 3
        Else
         sw = data1(i, m).sfsum
   End If
   For temp = 1 To sw
   list(pp, 2 * temp + 4) = data2(i, m, temp).name
   list(pp, 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.00000000")
    
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


TA的精华主题

TA的得分主题

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

 [em17] 太值得学习了。

bety  Integer 数据类型 全改为 long  还能稍快一些。

测试 658 行(1 楼) ok  测试 29998行(103楼) ok

测试 60860 行 (62楼  )报错 下标越界   “data(jxsum).name = jx”

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

这一句如能改为动态大小就好了

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

TA的精华主题

TA的得分主题

发表于 2007-11-30 20:06 | 显示全部楼层
QUOTE:
以下是引用ldy888在2007-11-30 19:17:46的发言:

 [em17] 太值得学习了。

bety  Integer 数据类型 全改为 long  还能稍快一些。

测试 658 行(1 楼) ok  测试 29998行(103楼) ok

测试 60860 行 (62楼  )报错 下标越界   “data(jxsum).name = jx”

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

这一句如能改为动态大小就好了


晕,你那故障才5个,机型到是超过50个,改成这样就行了

Dim data(1 To 100) As tjx, data1(1 To 100, 1 To 10) As tgz, data2(1 To 100, 1 To 10, 1 To 100) As tsf

测试结果,0.7秒,打乱数据的话估计更快,好象我以前用一维数组是30多秒,而且还没做完!

TA的精华主题

TA的得分主题

发表于 2007-11-30 20:19 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
QUOTE:
以下是引用ldy888在2007-11-30 19:17:46的发言:

 [em17] 太值得学习了。

bety  Integer 数据类型 全改为 long  还能稍快一些。

测试 658 行(1 楼) ok  测试 29998行(103楼) ok

测试 60860 行 (62楼  )报错 下标越界   “data(jxsum).name = jx”

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

这一句如能改为动态大小就好了


改为动态大小不太好吧,因为事先并不知道里面有多少机型,多少故障,多少省份,不可能为了得到这些数据先去循环一次,那样浪费时间了!

TA的精华主题

TA的得分主题

 楼主| 发表于 2007-11-30 20:22 | 显示全部楼层
QUOTE:
以下是引用ldy888在2007-11-30 16:13:29的发言:
QUOTE:
QUOTE:

多谢ldy888兄,错误原因找到了

Sub xi()
    Dim h As Long
    Dim i As Long
    Dim j As Long
    Dim x As Long
    Dim y As Long
    Dim z As Long
    t = Timer
    r = Sheet2.[A65536].End(xlUp).Row
    Sheet2.Range("a2").Resize(r, 3).sort Key1:=Sheet2.Range("B2"), Key2:=Sheet2.Range("C2"), Key3:=Sheet2.Range("A2")
    arr = Sheet2.Cells(1, 1).Resize(r + 2, 4)
    For i = 2 To r                       '为加速做准备
        arr(i, 4) = arr(i, 2) & arr(i, 3)
    Next i
    ReDim arr1(1 To r / 2, 1 To 11)
    ReDim arr2(1 To r, 1 To 2) As Long

    For i = 2 To r
        If arr(i, 1) & arr(i, 4) = arr(i - 1, 1) & arr(i - 1, 4) Then            '地区计数
            arr2(x, 2) = arr2(x, 2) + 1
        Else
            x = x + 1
            arr2(x, 1) = i
            arr2(x, 2) = 1
        End If
        jh = jh + 1
        If arr(i, 4) = arr(i - 1, 4) Then               '故障计数
            arr1(y, 4) = arr1(y, 4) + 1
        Else
            y = y + 1
            arr1(y, 2) = arr(i, 2)
            arr1(y, 3) = arr(i, 3)
            arr1(y, 4) = 1
        End If
        If arr(i, 2) <> arr(i + 1, 2) Then            '生成合计
            y = y + 1
            arr1(y, 2) = arr(i, 2)
            arr1(y, 3) = "合计"
            arr1(y, 4) = jh
            jh = 0
        End If
    Next i
    For h = 7 To 11 Step 2
        j = 1
        For i = 1 To y
            If arr1(i, 3) = "合计" Then i = i + 1
            For j = j To x
                If arr(arr2(j, 1), 4) = arr1(i, 2) & arr1(i, 3) And j < x Then
                    If arr2(j, 2) > arr1(i, h) Then            '记录大小和位置
                        arr1(i, h) = arr2(j, 2)
                        arr1(i, h - 1) = j
                    End If
                Else
                    If arr1(i, h) > 0 Then
                        arr2(arr1(i, h - 1), 2) = 0
                        arr1(i, h - 1) = arr(arr2(arr1(i, h - 1), 1), 1)
                    End If
                    Exit For
                End If
            Next j
        Next i
    Next h

    arr1(1, 1) = 1
    For i = 2 To y
        If arr1(i, 2) = arr1(i - 1, 2) Then
            arr1(i, 1) = arr1(i - 1, 1) + 1
        Else
            arr1(i, 1) = 1
        End If
    Next i
    For i = y To 1 Step -1
        If arr1(i, 3) = "合计" Then x = arr1(i, 4)
        arr1(i, 5) = arr1(i, 4) / x
    Next i
    Cells(3, 1).Resize(y, 11) = arr1
    [p2] = Timer - t
End Sub

[此贴子已经被作者于2007-11-30 21:29:37编辑过]

TA的精华主题

TA的得分主题

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

我还有一个想法不知是否行得通,就是用字典建立树形结构库.最后再提出数字,速度也有可能是很快.

TA的精华主题

TA的得分主题

 楼主| 发表于 2007-11-30 20:26 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
QUOTE:
以下是引用tycp在2007-11-30 20:06:33的发言:

晕,你那故障才5个,机型到是超过50个,改成这样就行了

Dim data(1 To 100) As tjx, data1(1 To 100, 1 To 10) As tgz, data2(1 To 100, 1 To 10, 1 To 100) As tsf

测试结果,0.7秒,打乱数据的话估计更快,好象我以前用一维数组是30多秒,而且还没做完!

太牛了,从头上服到脚步底了,

TA的精华主题

TA的得分主题

发表于 2007-11-30 21:04 | 显示全部楼层
QUOTE:
以下是引用彭希仁在2007-11-30 20:26:45的发言:

太牛了,从头上服到脚步底了,

那里,彭兄我才服你啊,有时间跟你学学递归算法,!!!那才是难学的!

TA的精华主题

TA的得分主题

发表于 2007-11-30 21:23 | 显示全部楼层
QUOTE:
以下是引用彭希仁在2007-11-30 20:25:15的发言:

我还有一个想法不知是否行得通,就是用字典建立树形结构库.最后再提出数字,速度也有可能是很快.

行的通啊,我的就是用数组构造的类似的树形结构库,当然,用字典构造的话,,速度更快!

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

本版积分规则

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

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

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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