ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[分享] 字典基本语句、以及中级字典运用例子

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2014-9-25 15:01 | 显示全部楼层 |阅读模式
本帖已被收录到知识树中,索引项:数组集合和字典
先给个简化版的字典基本语句:


基本功能已经尽在其中了。

如能熟练掌握,则可游刃有余。

Sub DicTest()

    Set Dic = CreateObject("Scripting.Dictionary") 'use Dictionary
    '引用字典 【按后期绑定方式引用,这样代码比较通用。】
    ' 如采取前期绑定 Dim Dic as New Dictionary 则可能有些电脑没有引用Scripting Runtime设置而不能用
               
    '语法:Dic(Key) = Item 将[关键词/项目]同时加入字典 并能忽略关键词不存在错误

    Dic("A") = "A1" 'Add [key/item] if key is new
    '如果key不存在则直接加入[key/item]
   
    Dic("A") = "A2" 'Cover [item] if key is exists without Err
    '如果key存在则覆盖更新item 且不产生key存在的错误提示
    '因此本质上,用这个方法给字典赋值、比使用 Dic.Add 更好!
    '(如需要对key存在进行错误处理,可使用Dic.Exists(key)方法,更加灵活。例子在下面
   
    Dic.key("A") = "B"   'Change exists key to new key and erase old key
    '当key和item已经存在时,更新key内容但保留已经存在的item内容。
    '其实这个语句实际意义不大。即实际使用的情况很少,几乎没有。
    '备注:也可以用 tmp = Dic("A") : Dic.Remove("A") : Dic("B")= tmp来完成。

    Dic("B") = "B1" 'Cover [item] if key is exists
    Dic("C") = "C1" 'Add [key/item] if key is new
   

    Dic(1) = 1 'you can use number as key
    '通常使用Sting文本字符串作为字典key关键词,也可以使用数字、数值作为key
    '但特别提醒: 如果整个字典关键词中既有数字又有字符串,应统一为字符串格式以提高效率
    '否则运行速度可能会慢十倍以上。
    '速度差异: 纯数字>纯文本字符>>>文本/数值混合型

    '下面是Dic.Exists(key)方法的常用模式: 和If判断结合起来使用
    For i = 1 To 2
        If Not Dic.Exists(i) Then
            Dic(i) = i 'if key not exists then add [key/item]
            '如果检查发现字典中尚不存在关键词、则加入字典 (一般会这么用)
        Else
            Dic(i) = Dic(i) * 10 'if key exists then Change [item]
            '如果检查发现字典中已经存在关键词、则更新字典中key对应的item (或什么也不做)
        End If
    Next
   
    '提取字典中keys/items结果分别得到各自的一维数组、顺序为加入字典时的先后顺序
    kr = Dic.keys   'Get keys result as Array
    tr = Dic.items  'Get items result as Array
   
    '循环遍历字典中的keys/items内容
    For i = 0 To Dic.Count - 1        t1 = kr(i)
        t2 = tr(i)
    Next

    '把字典中keys/items结果分别输出到工作表的某一列
    [a1].Resize(Dic.Count) = WorksheetFunction.Transpose(Dic.keys)   'Output keys result
    [b1].Resize(Dic.Count) = WorksheetFunction.Transpose(Dic.items)  'Output items result
   
End Sub

需要注意的是,一般推荐把工作表区域中的内容读入VBA内存数组,然后再使用。
此时得到的结果,默认都已经是Range(Rng).Value ,所以字典使用不会有问题。


但有些初学者会直接引用单元格使用,此时必须按 Dic(Range("A1").Value) = item 方式使用字典。
否则即会错误地把 Range("A1")装入字典而产生非预期的结果。

话说,我到现在也不知道,把Range()对象装入字典有何实际意义。也许只是一种未排除的错误用法。
所以我的建议是:大家完全不需要考虑Dic(Range())这样的用法。

评分

28

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-9-25 15:02 | 显示全部楼层
普通字典用法和结果的输出方式:

Sub DicTest1()

    Set dic = CreateObject("Scripting.Dictionary") 'use Dictionary
               
    For i = 1 To 3
        dic(i) = i * 10 '字典赋值
    Next
   
'输出方法-1: 传统方法、提取一维数组结果后转置输出
    [a1].Resize(dic.Count) = WorksheetFunction.Transpose(dic.Keys)
    [b1].Resize(dic.Count) = WorksheetFunction.Transpose(dic.items)
   

'输出方法-2: Array数组合并结果后转置输出   
    [a1].Resize(dic.Count, 2) = WorksheetFunction.Transpose(Array(dic.Keys, dic.items))

   
'下面是详细分解过程:
    kr = dic.Keys '提取keys
    tr = dic.items '提取items
    t1 = Array(dic.Keys, dic.items) '合并
    t2 = WorksheetFunction.Transpose(t1) '转置

'上述过程可以合并为一句代码:
    t = WorksheetFunction.Transpose(Array(dic.Keys, dic.items))
   
End Sub

点评

“WorksheetFunction.Transpose(Array(dic.Keys, dic.items))”  精彩的用法!!!  发表于 2014-9-25 18:47

评分

10

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-9-25 15:04 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
字典Item项目的数组用法、以及结果的输出方式:

Sub DicTest2()

    Set dic = CreateObject("Scripting.Dictionary") 'use Dictionary
               
    For i = 1 To 5
        dic(i) = Array(i, i * 10, i * 100) '把数组作为Item项目写入字典
    Next
   
    [a1].CurrentRegion = ""
    [a1].Resize(dic.Count) = WorksheetFunction.Transpose(dic.Keys) 'Output keys result

'字典Items内容为数组时、需要二次转置后才能输出:
    [b1].Resize(dic.Count, 3) = Application.Transpose(Application.Transpose(dic.items))

'或者可以用这个Rept函数处理方法: 不需要转置。
    [b1].Resize(dic.Count, 3) = Application.Rept(dic.items, 1)   
   
End Sub

点评

rept的用法有点匪夷所思……得好好思忖再三……  发表于 2014-9-25 18:54

评分

9

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-9-25 15:05 | 显示全部楼层
本帖最后由 香川群子 于 2014-9-25 15:13 编辑

字典Key的嵌套字典用法、以及结果的输出方式:

Sub DicTest3()

    Set dic = CreateObject("Scripting.Dictionary") 'use Dictionary
               
    For i = 1 To 3
        Set dic(i) = CreateObject("Scripting.Dictionary")
       '把每一个dic的key也设置为字典,结果得到一个嵌套的字典。
       '如果多层循环下去,就能得到多级嵌套字典   
    Next
   
    '循环给嵌套字典赋值
    For i = 1 To 3
        For j = 1 To 5
            dic(i)(j) = i * 10 + j
            '注意语法: dic(i) 是dic的key= i 的项目、但它自身已被设置为一个嵌套子字典
            '该嵌套子字典的关键字key = j 、必须以 dic(i)(j)的方式被使用。
        Next
    Next
   
    krr = dic.keys   '提取主字典中的关键词 Get keys result as Array
    ReDim kr(3 - 1) '定义数组kr存放嵌套子字典中的【子key】
    ReDim tr(3 - 1) '定义数组tr存放嵌套子字典中的【子item】
    For i = 0 To 3 - 1
        kr(i) = dic(krr(i)).keys
        tr(i) = dic(krr(i)).items
    Next
   
    [a1].CurrentRegion = ""
    [a1].Resize(dic.Count) = WorksheetFunction.Transpose(dic.keys) 'Output keys result
    [b1].Resize(dic.Count, UBound(kr(0)) + 1) = WorksheetFunction.Transpose(WorksheetFunction.Transpose(kr))
   '输出嵌套【子key】

    [a5].CurrentRegion = ""
    [a5].Resize(dic.Count) = WorksheetFunction.Transpose(dic.keys) 'Output keys result
    [b5].Resize(dic.Count, UBound(tr(0)) + 1) = WorksheetFunction.Transpose(WorksheetFunction.Transpose(tr))
   '输出嵌套【子item】
End Sub

点评

高级用法,精致的例子!!!  发表于 2014-9-25 19:35

评分

4

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-9-25 15:08 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖是中级程度的字典基本技术帖,
虽然不包括实际运用,但可以开阔初学者的思路,以便更灵活自如地运用字典方法。

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-9-25 15:26 | 显示全部楼层
字典的作用:

字典的最重要作用有以下:
一、任意关键词快速查询。
二、检查并处理重复关键词
三、一一对应并记录、更新关键词对应项目内容(合并、统计、分组……等等)



一、任意关键词快速查询。
在数组中寻找一个符合要求的值,一般说需要遍历……这个很耗时。
而字典可以快速得到符合值所在位置……当字典项目=数组Index位置时。

因此,使用字典+数组的方法,可以简洁高效地得到结果。

举例:
Sub DicTest4()

    ar = [a1].CurrentRegion
   
    Set dic = CreateObject("Scripting.Dictionary") 'use Dictionary
               
    For i = 1 To UBound(ar)
        dic(ar(i, 1)) = i
    Next
   
    r = Int(Rnd * UBound(ar)) + 1
    s = ar(r, 1)
    t = dic(s)
    MsgBox r & " = " & t & " is " & (r = t)
End Sub


评分

2

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-9-25 16:08 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2014-9-25 19:35 | 显示全部楼层
香川群子 发表于 2014-9-25 15:05
字典Key的嵌套字典用法、以及结果的输出方式:

Sub DicTest3()

  备注:4楼代码运行结果如下图:
   jg.jpg

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-9-25 20:28 | 显示全部楼层
技术贴,收藏是必须的,谢谢分享啊!搬小凳子听课。

TA的精华主题

TA的得分主题

发表于 2014-9-25 21:12 | 显示全部楼层
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-11-15 12:37 , Processed in 0.039080 second(s), 11 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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