并肩作战的好兄弟实现快速汇总:字典 + 数组

2024-02-06 06:50

本文主要是介绍并肩作战的好兄弟实现快速汇总:字典 + 数组,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

VBA开发者经常讨论的一个话题就是:字典和数组哪个效率更高?使得很多VBA初学者懵懂的认为,这两者非此即彼,水火不容。其实很多应用场景中,它们是并肩作战的好兄弟。

实例需求

已有生产排程数据如下所示。

需要整理为如下格式。

数据合并的要点有三个:

  • 料号和机种号为统计的关键字段
  • 未交数量求和
  • 交期汇总,包含时间和数量

示例代码

Sub LoadData()Dim aData, aRes(), lst, iRow, iCol, iKeyCol, DicConst COLUMNS_QTY = 21With Sheets("交货排程")iKeyCol = 5lst = .Cells(.Rows.Count, iKeyCol).End(xlUp).RowaData = .Cells(2, 1).Resize(lst, COLUMNS_QTY).ValueEnd WithSet Dic = CreateObject("Scripting.Dictionary")For iRow = 3 To UBound(aData, 1)skey = aData(iRow, 5) & "|" & aData(iRow, 6)If Len(skey) > 1 ThenIf Dic.exists(skey) ThenDic(skey) = Array(Val(aData(iRow, 9)) + Dic(skey)(0), Dic(skey)(1))ElseDic(skey) = Array(Val(aData(iRow, 9)), "")End IfFor iCol = 11 To UBound(aData, 2)If Val(aData(iRow, iCol)) > 0 Thensdate = VBA.Replace(Format(aData(2, iCol), "m-d"), "-", "/")Debug.Print Dic(skey)(1) & "," & sdate & "*" & aData(iRow, iCol)Dic(skey) = Array(Dic(skey)(0), Dic(skey)(1) & "," & sdate & "*" & aData(iRow, iCol))End IfNext iColEnd IfNext iRowReDim aRes(1 To Dic.Count, 1 To 4)n = 1For Each d In Dic.keysakey = Split(d, "|")aRes(n, 1) = akey(0)aRes(n, 2) = akey(1)aRes(n, 3) = Dic(d)(0)aRes(n, 4) = Mid(Dic(d)(1), 2)n = n + 1Next' 结果数组aRes回写到工作表中With Sheets("结果").Range("2:10000").ClearContents.Cells(2, 1).Resize(Dic.Count, 4).Value = aRes.Range("a1").CurrentRegion.Borders.LineStyle = xlContinuousEnd WithSet Dic = Nothing
End Sub
代码解析

对于需要进行排重统计的应用,使用数组就可以实现,对于每个数据行都需要循环对比数组的全部元素,然而字典对象元素具有唯一性,因此对于排重统计有着独到的优势。
对于每个关键字段组合,需要保存的信息有:两个关键字段,数量和相应的日期,此时数组就可以方便保存多个数据。因此使用字典和数组组合的双剑合璧,功力无敌!
将工作表数据加载到数组的代码,不需要多讲。

aData = .Cells(2, 1).Resize(lst, COLUMNS_QTY).Value

将关键字段进行组合,确定字典的键值。

skey = aData(iRow, 5) & "|" & aData(iRow, 6)

下面代码将一个 1 x 2的数组保存在字典对象中,如果skey是一个新的键值,那么将未交数量aData(iRow, 9)做为数组第一个元素,第二元素暂时留空。
如果skey是一个在字典中已经存在的键值,那么Val(aData(iRow, 9)) + Dic(skey)(0)将未交数量进行累加,并保留已有的交期信息Val(aData(iRow, 9)) + Dic(skey)(0)

If Dic.exists(skey) ThenDic(skey) = Array(Val(aData(iRow, 9)) + Dic(skey)(0), Dic(skey)(1))
ElseDic(skey) = Array(Val(aData(iRow, 9)), "")
End If

与此类似,下面代码将汇总交期信息。注意更新字典对象的数组元素时,只能全部重新赋值,而不能使用Dic(skey)(0)="xxx"的形式

For iCol = 11 To UBound(aData, 2)If Val(aData(iRow, iCol)) > 0 Thensdate = VBA.Replace(Format(aData(2, iCol), "m-d"), "-", "/")Debug.Print Dic(skey)(1) & "," & sdate & "*" & aData(iRow, iCol)Dic(skey) = Array(Dic(skey)(0), Dic(skey)(1) & "," & sdate & "*" & aData(iRow, iCol))End If
Next iCol

对于字典中保存的数组元素,无法直接回写到工作表中,因此需要先构建回写的二维数组。Mid(Dic(d)(1), 2)用于去掉交期信息中的第一个逗号。

    For Each d In Dic.keysakey = Split(d, "|")aRes(n, 1) = akey(0)aRes(n, 2) = akey(1)aRes(n, 3) = Dic(d)(0)aRes(n, 4) = Mid(Dic(d)(1), 2)n = n + 1Next

后记

对于这个实例,只用数组可以实现吗?肯定可以实现,而且在数据量不大的情况下,效率差距也不大。不用保存数组的字典对象,而使用字典对象嵌套也可以实现。条条大路通罗马,希望大家能够灵活运用字典和数组组合。

这篇关于并肩作战的好兄弟实现快速汇总:字典 + 数组的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/683477

相关文章

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

Python实现字典转字符串的五种方法

《Python实现字典转字符串的五种方法》本文介绍了在Python中如何将字典数据结构转换为字符串格式的多种方法,首先可以通过内置的str()函数进行简单转换;其次利用ison.dumps()函数能够... 目录1、使用json模块的dumps方法:2、使用str方法:3、使用循环和字符串拼接:4、使用字符

Linux下利用select实现串口数据读取过程

《Linux下利用select实现串口数据读取过程》文章介绍Linux中使用select、poll或epoll实现串口数据读取,通过I/O多路复用机制在数据到达时触发读取,避免持续轮询,示例代码展示设... 目录示例代码(使用select实现)代码解释总结在 linux 系统里,我们可以借助 select、

Linux挂载linux/Windows共享目录实现方式

《Linux挂载linux/Windows共享目录实现方式》:本文主要介绍Linux挂载linux/Windows共享目录实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录文件共享协议linux环境作为服务端(NFS)在服务器端安装 NFS创建要共享的目录修改 NFS 配

通过React实现页面的无限滚动效果

《通过React实现页面的无限滚动效果》今天我们来聊聊无限滚动这个现代Web开发中不可或缺的技术,无论你是刷微博、逛知乎还是看脚本,无限滚动都已经渗透到我们日常的浏览体验中,那么,如何优雅地实现它呢?... 目录1. 早期的解决方案2. 交叉观察者:IntersectionObserver2.1 Inter

Spring Gateway动态路由实现方案

《SpringGateway动态路由实现方案》本文主要介绍了SpringGateway动态路由实现方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随... 目录前沿何为路由RouteDefinitionRouteLocator工作流程动态路由实现尾巴前沿S