ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 2001|回复: 8

[原创] 字典嵌套与递归的混合应用教程范例

[复制链接]

TA的精华主题

TA的得分主题

发表于 2019-10-21 17:39 | 显示全部楼层 |阅读模式
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 microyip 于 2019-10-21 17:42 编辑

最近,看到了“月关”坛友对字典嵌套的热衷,今天又刚好有个坛友问及字典嵌套的应用,突然想弄个字典嵌套与递归的混合应用教程范例出来的冲动。
先看看本帖二楼的常规字典嵌套的应用,代码也不是很复杂,也易于理解,但存在一个缺陷,对字典嵌套层数必须用手工一层层写进代码里。
利用递归方式写字典嵌套,就可以相对简单解决层数问题了,就代码相对复杂了点。
其中,代码中关于建设字典过程基本是没问题的,但递归应用字典代码中,我已知有一定的Bug,但具体这个Bug在实际应用会不会产生呢?暂时不知道,所以我也没有预先设置代码去处理了。如果有朋友专门指出或者其他我未知的Bug,欢迎提出指正。
  1. Sub 递归建立字典嵌套示例()
  2.     Dim oDic As Object, vKey As Variant, vMsg As Variant, sMsg As String
  3.     Dim vData As Variant, nRow As Long, nCol As Long
  4.    
  5.     vData = [{"广东省","深圳市","罗湖区";"广东省","深圳市","宝安区";"广东省","广州市","海珠区";"广东省","广州市","白云区"}]
  6.         '需要设置字典的数据
  7.     For nRow = 1 To UBound(vData)
  8.         vKey = Application.WorksheetFunction.Index(vData, nRow) '获取字典设置需要的关键字数组
  9.         Set oDic = SetDic(oDic, vKey, nRow) '对vKey指定关键字进行字典层级设置
  10.     Next
  11.    
  12.     vData = [{"广东省","深圳市","罗湖区";"广东省","广州市","东山区";"广东省","珠海市","香山区";"浙江省","杭州市","西湖区"}]
  13.         '需要检索字典的结果
  14.     For nRow = 1 To UBound(vData)
  15.         vKey = Application.WorksheetFunction.Index(vData, nRow) '检索字典的关键字数组
  16.         vMsg = GetDicMsg(oDic, vKey) '获取指定关键字在检索字典过程中的信息
  17.         If vMsg(3) = "" Then
  18.             sMsg = "【" & vMsg(2) & "】的数据排序是:" & vMsg(1)
  19.         Else '存在出错关键字
  20.             If Not vMsg(4) Then  '当存在最后关键字得到是字典
  21.                 sMsg = "数据内存在【"
  22.                 If vMsg(2) <> "" Then sMsg = sMsg & vMsg(2) & ","
  23.                 sMsg = sMsg & vMsg(3) & "】,但不是一个最终值"
  24.             Else
  25.                 sMsg = "数据内不存在【"
  26.                 If vMsg(2) <> "" Then sMsg = sMsg & vMsg(2) & "】的【"
  27.                 sMsg = sMsg & vMsg(3) & "】"
  28.             End If
  29.         End If
  30.         If sMsg <> "" Then MsgBox sMsg
  31.     Next
  32. End Sub

  33. Private Function SetDic(ByVal oDic As Variant, ByVal vKey As Variant, Optional ByVal vItem As Variant, Optional ByVal nIndex As Long) As Object
  34. 'oDic,设定的字典初始状态
  35. 'vKey,字典的关键字或者关键字数组
  36. 'vItem,字典最终设置的Item值
  37. 'nIndex,需要设置的字典层数
  38.     If IsMissing(vItem) Then '当函数接收的vItem参数没有被传过来参数值时
  39.         vItem = Empty '预设一个参数值
  40.     End If
  41.     If TypeName(oDic) <> "Dictionary" Then '参数oDic的类型不是字典类型时
  42.         Set oDic = CreateObject("Scripting.Dictionary") '设置oDic为一个新字典
  43.     End If
  44.     If IsArray(vKey) Then 'vKey是数组时
  45.         If nIndex = 0 Then '当函数接收的nIndex参数没有被传过来参数值时
  46.             nIndex = LBound(vKey) '获取第一层关键字数组的序号
  47.         End If
  48.         If nIndex = UBound(vKey) Then '需要设置的字典层数为最大关键字数组序号时
  49.             oDic(vKey(nIndex)) = vItem '建立字典
  50.         Else
  51.             Set oDic(vKey(nIndex)) = SetDic(oDic(vKey(nIndex)), vKey, vItem, nIndex + 1) '建立下一层字典
  52.         End If
  53.     Else 'vKey不是数组时
  54.         oDic(vKey) = vItem '建立字典
  55.     End If
  56.     Set SetDic = oDic '返回已建立的字典
  57. End Function

  58. Private Function GetDicMsg(ByVal oDic As Object, ByVal vKey As Variant, Optional ByVal vMsg As Variant, Optional ByVal nIndex As Long) As Variant
  59. 'oDic,匹配数据的字典
  60. 'vKey,字典的关键字或者关键字数组
  61. 'vMsg,返回用的信息
  62. 'nIndex,需要设置的字典层数
  63.     Dim nI As Long, vKey_Now As Variant
  64.    
  65.     If IsMissing(vMsg) Then '当函数接收的vMsg参数没有被传过来参数值时
  66.         ReDim vMsg(1 To 4) '重置数组,1、最终的Item结果;2、能获取的关键字;3、不能获取的关键字或获取的关键字得到的是一个字典;4、最终Item结果不是字典
  67.         vMsg(4) = True
  68.     End If
  69.     If IsArray(vKey) Then 'vKey是数组时
  70.         If nIndex = 0 Then '当函数接收的nIndex参数没有被传过来参数值时
  71.             nIndex = LBound(vKey) '获取第一层关键字数组的序号
  72.         End If
  73.         vKey_Now = vKey(nIndex) '当前的关键字值
  74.         If oDic.Exists(vKey_Now) Then '存在对应层字典的关键字
  75.             If nIndex = UBound(vKey) Then '需要读取的字典层数为最大关键字数组序号时
  76.                 vMsg(4) = TypeName(oDic(vKey_Now)) <> "Dictionary" '当前关键字得到的是否字典类型
  77.                 If vMsg(4) Then '当前关键字的不是字典类型
  78.                     vMsg(1) = oDic(vKey_Now) '记录最终的Item结果
  79.                     If vMsg(2) <> "" Then vMsg(2) = vMsg(2) & ","
  80.                     vMsg(2) = vMsg(2) & vKey_Now '记录获取的关键字
  81.                 Else
  82.                     vMsg(3) = vKey_Now '记录获取的关键字得到的是一个字典
  83.                 End If
  84.             Else
  85.                 If vMsg(2) <> "" Then vMsg(2) = vMsg(2) & ","
  86.                 vMsg(2) = vMsg(2) & vKey_Now '记录获取的关键字
  87.                 vMsg = GetDicMsg(oDic(vKey_Now), vKey, vMsg, nIndex + 1) '对下一层级的字典检索
  88.             End If
  89.         Else
  90.             vMsg(3) = vKey_Now '记录不能获取的关键字
  91.         End If
  92.     Else 'vKey不是数组时
  93.         If oDic.Exists(vKey) Then
  94.             vMsg(4) = TypeName(oDic(vKey)) <> "Dictionary" '当前关键字得到的是否字典类型
  95.             If vMsg(4) Then '当前关键字的不是字典类型
  96.                 vMsg(1) = oDic(vKey) '记录最终的Item结果
  97.                 vMsg(2) = vKey '记录获取的关键字
  98.             Else
  99.                 vMsg(3) = vKey '记录获取的关键字得到的是一个字典
  100.             End If
  101.         Else
  102.             vMsg(3) = vKey '记录不能获取的关键字
  103.         End If
  104.     End If
  105.     GetDicMsg = vMsg '返回信息
  106. End Function
复制代码


附上附件以供参考
递归建立字典嵌套示例(by.micro).rar (22.92 KB, 下载次数: 126)

评分

4

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-10-21 17:41 | 显示全部楼层
常规字典嵌套应用
  1. Sub 常规建立字典嵌套示例()
  2.     Dim oDic As Object, vKey As Variant, vItem As Variant
  3.     Dim vData As Variant, nRow As Long, nCol As Long
  4.    
  5.     vData = [{"广东省","深圳市","罗湖区";"广东省","深圳市","宝安区";"广东省","广州市","海珠区";"广东省","广州市","白云区"}]
  6.     Set oDic = CreateObject("Scripting.Dictionary")
  7.     ReDim vKey(1 To UBound(vData, 2))
  8.     For nRow = 1 To UBound(vData)
  9.         vKey = Application.WorksheetFunction.Index(vData, nRow)
  10.         If Not oDic.Exists(vKey(1)) Then Set oDic(vKey(1)) = CreateObject("Scripting.Dictionary")
  11.         If Not oDic(vKey(1)).Exists(vKey(2)) Then Set oDic(vKey(1))(vKey(2)) = CreateObject("Scripting.Dictionary")
  12.         oDic(vKey(1))(vKey(2))(vKey(3)) = nRow
  13.     Next
  14.    
  15.    
  16.     vData = [{"广东省","深圳市","罗湖区";"广东省","广州市","东山区";"广东省","珠海市","香山区";"浙江省","杭州市","西湖区"}]
  17.     For nRow = 1 To UBound(vData)
  18.         vKey = Application.WorksheetFunction.Index(vData, nRow)
  19.         If oDic.Exists(vKey(1)) Then
  20.             If oDic(vKey(1)).Exists(vKey(2)) Then
  21.                 If oDic(vKey(1))(vKey(2)).Exists(vKey(3)) Then
  22.                     MsgBox "【" & vKey(1) & "," & vKey(2) & "," & vKey(3) & "】的数据排序是:" & oDic(vKey(1))(vKey(2))(vKey(3))
  23.                 Else
  24.                     MsgBox "数据内不存在【" & vKey(1) & "," & vKey(2) & "】的【" & vKey(3) & "】"
  25.                 End If
  26.             Else
  27.                 MsgBox "数据内不存在【" & vKey(1) & "】的【" & vKey(2) & "】"
  28.             End If
  29.         Else
  30.             MsgBox "数据内不存在【" & vKey(1) & "】"
  31.         End If
  32.     Next
  33. End Sub
复制代码

评分

3

查看全部评分

TA的精华主题

TA的得分主题

发表于 2019-10-23 11:05 | 显示全部楼层
感谢感谢!十分感谢老师用心良苦,我就当为我量身订制的了,话说 老师怎么知道我要开始学递归呢。

字典已经告一段落了,话说这块以后我就是大神了,涉及到字典的问题随便喊我过来指导昂各位………
前面疑似飞过来一块砖状物,我先战略性地回避一下

TA的精华主题

TA的得分主题

发表于 2019-12-6 16:00 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2019-12-6 16:12 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2020-10-4 15:57 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2020-10-4 19:01 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2022-1-30 20:42 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
能给建立个多层嵌套的模型吗

TA的精华主题

TA的得分主题

发表于 2022-3-19 21:28 | 显示全部楼层
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-5-16 02:56 , Processed in 0.050376 second(s), 17 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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