Excel精英培训网

 找回密码
 注册
数据透视表40+个常用小技巧,让你一次学会!
查看: 15987|回复: 40

[分享] 我学习字典使用

[复制链接]
发表于 2007-9-30 10:36 | 显示全部楼层 |阅读模式
看了ldy版主ttp://www.excelpx.com/dispbbs.asp?boardID=5&ID=27869&page=1贴子,努力学习一番,终于有点体会,特写出来,一是还有3个问题需寻求帮助,二是给象我这样的初学者一个分享:
sheet12100行中,A列为部门,5列为工资,目的是算出各部门的工资之和,写入cells(2,10)起的单元格中,使用字典方式:
方式一:VBE窗口---工具---引用---microsoft scripting runtime
Sub test()
Dim d As New Dictionary ‘创建字典
d.CompareMode = TextCompare ' = vbTextCompare
For I = 2 To 100
d.Item(Cells(I, 1).Value) = d.Item(Cells(I, 1).Value) + Cells(I, 5)
‘1、此处必须加.value,否则达不到目的,不清楚为什么。
‘2、向字典d中添加项目,类似于d.add cells(I,1).value,cells(I,5) .value,但不同的在于:遇到重复的部门名时,则累加,而用后者会报错。
‘3、也可写成d(Cells(I, 1).Value) =d(Cells(I, 1).Value)+ Cells(I,5)
‘4、机理:设cells(2,1)cells(10,1)都是“后勤”,工资分别为50004000,运行到cells(2,1)时,第二个d(Cells(I, 1).Value)(或d.Item(Cells(I, 1).Value))自动将当前的“后勤”写入当前的KEY,同时ITEM为空,+ Cells(I,5)后写入ITEM,使d(Cells(I, 1).Value) =d(Cells(I, 1).Value)+ Cells(I,5)的结果为d(Cells(I, 1).Value) =5000;运行到cells(10,1)时,由于前边已有“后勤”的key了,直接使d(Cells(I, 1).Value) =d(Cells(I, 1).Value)+ Cells(I,5)=5000+4000=9000。要注意的是KEY的写入,如原贴中的s=d(arr(i)),此处的s无实际作用,只起到个执行d(arr(i)),即将arr(i)写入KEY的目的。
‘5、不要企图象数组一样按项写入,如想让字典d的第一个key为“aaaaa”就写成d(0)= aaaaa(这样写结果成了key0item为“aaaaa)等等方式
Next
For I = 0 To d.Count – 1 ‘写典项从0开始
Cells(I + 2, 10) = d.Keys(I) ‘按项引用,有点象对数组的引用;
Cells(I + 2, 11) = d.Items(I) ‘item的引用 ,也可以为Cells(I + 2, 11) = d (Cells(I + 2, 11).value),与前边一样,为什么一定要加上.value,否则不成功,也不明白。
Next
End Sub
方式二:Set d = CreateObject("scripting.Dictionary")
Sub test()
Set d = CreateObject("scripting.Dictionary")
d.CompareMode = vbTextCompare '此处必须加上VB两字,否则按默认的比较方式,这是与方式一不同之一
For I = 1 To 10 ‘与方式一相同,不再说
d.Item(Cells(I, 1).Value) = d.Item(Cells(I, 1).Value) + Cells(I, 2)
Next
arr = d.keys ‘不同之二,不能象方式一一样用Cells(I + 2, 10) = d.Keys(I) 按项引用key,我就只有将所有的KEY写入数组ARR了,这是为什么也不清楚。
For I = 0 To d.Count - 1
Cells(I + 2, 10) = arr(I)
Cells(I + 2, 11) = d(arr(i))
Next
End Sub
求教3个问题:
1d.Item(Cells(I, 1).Value) = d.Item(Cells(I, 1).Value) + Cells(I, 5)为什么必须加.value?
2、方式二中d.CompareMode =VBTextCompareVB为什么必须加,而方式一却可有可无
3、方式一中对ikey的引用可以用d.Keys(I),而方式二为什么不可以? 望各位不吝赐教!
 楼主| 发表于 2007-9-30 15:11 | 显示全部楼层
非常感谢飞版和ldy辅导!!又让我好好学习了一盘(当然仍然是七窍通了六窍)! 对于ldy辅导对d.Item(Cells(I, 1).Value) = d.Item(Cells(I, 1).Value) + Cells(I, 5) 的改写我还不理解,因为想达到的目的是如前述:cells(2,1)cells(10,1)都是“后勤”,工资分别为50004000,运行到cells(2,1)时,d(“后勤")=5000,相当于add;运行到cells(10,1)时,由于已有d(“后勤")了(相当于来了个if Exists的判断) ,直接使d(“后勤") =d(“后勤")+ Cells(I,5)=5000+4000=9000。 也就是相同则累加,不同则新建 若写成d(Cells(I, 1).Value) = Cells(I, 1) + Cells(I, 5) 能行吗? 另外,从老编程模式下走来的,对飞版讲的面向对象思想的确很缺,老想象以前操作数组那样来操作字典,需学的还多呀!
回复

使用道具 举报

发表于 2007-9-30 16:24 | 显示全部楼层

d.(Cells(I, 1).Value) = d.(Cells(I, 1).Value) + Cells(I, 5) ' 实现累加

手误 应为 d(Cells(I, 1).Value) = d(Cells(I, 1).Value) + Cells(I, 5)  

d(key)= 1   这是没有就添加,有就覆盖

d.add key , 1  这是没有就添加,有就报错

 

[此贴子已经被作者于2008-1-20 19:29:31编辑过]
回复

使用道具 举报

发表于 2007-9-30 12:33 | 显示全部楼层

没有学习过字典。说一下第二个问题吧,因为比较明显

Dictionary的CompareMode属性仅适用于VBScript,当比较字符串键时,允许指定比较的方式。两个允许的值为BinaryCompare(0)和TextCompare(1)。BinaryCompare(0)为二进制数对照(即区分大小写);TextCompare(1)为文本对照(即不区分大小写)。

而第一类你引用了scripting,则对应属性就是TextCompare

而第二类你运用了VB的Object

CompareMode的属性是

VbUseCompareOption–1使用 Option Compare 语句的设置值进行比较。
vbBinaryCompare 0进行二进制比较。
vbTextCompare 1进行文字比较。
vbDatabaseCompare 2仅用于 Microsoft Access。进行基于您自己数据库中信息的比较。
所以有所不同,不过都是引用值都为1,使用引用值时就一样了。

回复

使用道具 举报

发表于 2007-9-30 12:38 | 显示全部楼层

补充一下Scripting.Dictionary对象属性说明

许多Microsoft的编程语言,如Visual Basic、VBScript和Jscript,都提供集合(collection)。可以把集合想象为数组,可以使用其中内建的函数完成存储和操纵数据等基本任务。无须担心数据是在哪些行列,而是使用唯一的键进行访问。
    VBScript和Jscript都提供类似的对象,通称Scripting.Dictionary对象或Dictionary对象。它类似于二维数组,把键和相关条目的数据存放在一起。然而真正的面向对象的方法,不应直接访问数据条目,必须使用Dictionary对象支持的方法和属性来实现。
 
属 性    说 明
CompareMode    (仅用于VBScript)设定或返回键的字符串比较模式
Count    只读。返回Dictionary里的键/条目对的数量
Item(key)    设定或返回指定的键的条目值
Key(key)    设定键值
表5-3  Dictionary对象的方法和说明
方 法    说 明
Add(key,item)    增加键/条目对到Dictionary
Exists(key)    如果指定的键存在,返回True,否则返回False
Items()    返回一个包含Dictionary对象中所有条目的数组
Keys()    返回一个包含Dictionary对象中所有键的数组
Remove(key)    删除一个指定的键/条目对
RemoveAll()    删除全部键/条目对
2.    对Dictionary中增加和删除条目
一旦得到一个新的(空的)Dictionary,可以对其添加条目,从中获取条目以及删除条目:
3.    修改键或条目的值
可以通过修改键的值,或通过修改与特定的键关联的条目的数据,来改变存储在Dictionary内的数据。下面的代码改变键为MyKey的条目中的数据。
如果指定的键在Dictionary未找到,将在Dictionary中创建一个以MyKey为键,以New Value为其条目值的新的键/条目对。有意思的是,如果使用一个不存在的键来检索条目,不仅得到一个空的字符串(这是可以想到的),而且还在Dictionary里添加一个新的键/条目对,键即是指定的键,但条目的数据为空。
可以使用Key属性仅改变键的值而不改变与之对应的条目的数据。将一个已存在的键MyKey改变为MyNewKey,如果指定的键未找到,则产生运行期错误。
4.    设置比较模式
Dictionary的CompareMode属性仅适用于VBScript,不能在JScript中使用。当比较字符串键时,允许指定比较的方式。两个允许的值为BinaryCompare(0)和TextCompare(1)。BinaryCompare(0)为二进制数对照(即区分大小写);TextCompare(1)为文本对照(即不区分大小写)。
5.    遍历Dictionary
研究Dictionary时,有两个方法和一个属性需要特别注意,它们允许我们遍历存储在Dictionary里的所有键/条目对。Items方法用一个一维数组的形式返回Dictionary里所有的条目数据,而keys方法用一个一维数组返回所有已存在的键值。可以使用Count属性得到键或条目的数量。
例如,可以使用下列代码得到名称为objMyData的Dictionary中所有的键和条目值。注意,虽然Count属性保存了在Dictionary里的键/条目数量,但VBScript和JScript的数组总是从下标0开始的。因此,数组下标应从0到Count-1。
回复

使用道具 举报

发表于 2007-9-30 12:50 | 显示全部楼层

学习了
回复

使用道具 举报

发表于 2007-9-30 12:52 | 显示全部楼层

字典”是啥东东还搞不明白!
回复

使用道具 举报

发表于 2007-9-30 13:04 | 显示全部楼层

这句写法不规范,但也能运行,效率低,字典处理了三次 包括一次纠错(字典还能纠错??!!)

d.Item(Cells(I, 1).Value) = d.Item(Cells(I, 1).Value) + Cells(I, 5)  

这是教科书上的标准写法。

因为自己从来不这么写,猛一看还以为错了。

效果同下

d(Cells(I, 1).Value) = d(Cells(I, 1).Value) + Cells(I, 5)  

 

[此贴子已经被作者于2008-1-20 22:09:15编辑过]
回复

使用道具 举报

发表于 2007-9-30 13:31 | 显示全部楼层

问题2 飘版已解释了

问题1 字典的key 可以是初数组为的任何类型

d.(cells(1,1))= 1  '以range为key,而每个range都是唯一的

d.(cells(1,1).value)=1 '以range的值为key

debug.print typename(cells(1,1))'------〉range

debug.print typename(cells(1,1).value)'-----〉string

问题3 与问题2 有关 引用对象和代码创建对象的 差异

这问题谈下去就深了,我也第一次遇到

回复

使用道具 举报

发表于 2007-10-4 22:23 | 显示全部楼层

学习中!

回复

使用道具 举报

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

本版积分规则

小黑屋|手机版|Archiver|Excel精英培训 ( 豫ICP备11015029号 )

GMT+8, 2024-6-1 03:14 , Processed in 0.172011 second(s), 6 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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