zoukankan      html  css  js  c++  java
  • VB默认属性、动态数组、Range对象的默认属性的一点不成熟的想法

    1、默认属性

           VB6.0有默认属性的特性。当没有给对象指定具体的属性时,"默认属性"是VB6.0将使用的属性。在某些情形下,省略常用属性名,使代码更为精简。

           因为CommandButton的默认属性是Value,所以下面两句代码是等价的:

    1 Sub Test()
    2 Debug.Print UserForm1.CommandButton1     '输出Falue
    3 Dim a
    4 a = UserForm1.CommandButton1
    5 Debug.Print a                            '输出False
    6 End Sub

             而从F2对象浏览器中,可以看到Value确实是CommandButton的缺省成员(默认属性)——属性图标也和其它不同,左上角多了一个小圆圈。

          另一些情况,假如我们需要的是对象本身,而不是它的某个属性,比如我们想要把CommandButton1这个对象本身赋值给一个变量,就要使用Set “显式” 声明:

    1 Sub Test()
    2 Dim cmd As MSForms.CommandButton
    3 Set cmd = UserForm1.CommandButton1
    4 End Sub

          当一个对象不存在默认属性,获得对象本身是否需要使用set?答案是肯定的,将一个对象赋值给变量,必须使用Set关键字:Set a = Sheet1

    2、动态数组Variant

         定义动态数组:(没有初始化长度)

          Dim arr() As Integer '元素为整型的动态数组 

          Dim brr() As Variant '元素为variant类型的动态数组 

          Dim crr() '元素为variant类型的动态数组 

          动态数组的特性之一:可被同一类型的静态数组初始化(赋值)

     1 Sub Test()
     2 Dim arr() As Integer
     3 Dim brr(1 To 3) As Integer    '静态数组
     4     brr(1) = 1
     5     brr(2) = 2
     6     brr(3) = 3
     7     arr = brr
     8 Dim crr() As Variant
     9 Dim drr(1 To 3) As Variant
    10     drr(1) = 1
    11     drr(2) = True
    12     drr(3) = "张三"
    13     crr = drr
    14 End Sub

         如果静态数组和动态数组的元素类型不一致,则产生错误。下面的代码报编译错误“不能给数组赋值”。

    1 Sub Test()
    2 Dim arr()
    3 Dim brr(1 To 3) As Integer
    4     arr = brr                  '不能给数组赋值
    5 End Sub

    3、利用Range的Value属性和Variant()接收单元格区域的值

           Range是一个区域时,它的Value返回一个静态Variant(),而动态Variant()是可是接收这个返回值的。

    1 Sub Test()
    2 Dim arr()
    3 arr = Range("A1:A5").Value
    4 arr = ThisWorkbook.Worksheets(1).Range("A1:A5").Value
    5 End Sub

          实际写VBA代码时,更多是像下面这样,使用variant变量达到相同效果:

    1 Sub Test()
    2 Dim arr
    3     arr = Range("A1:A5")
    4     arr = ThisWorkbook.Worksheets(1).Range("A1:A5")
    5 End Sub

         这样的写法没有属性的显式调用,可能许多人会认为利用了Range对象的默认属性,这个默认属性会让人觉得是Value或Value2。

    4、Range对象的默认属性是什么?

          入门VBA的时候,绝多数人都说Value是Range对象的默认属性,所以下面这样写,大多数人认为是省略Value的写法:

    1 Sub Test()
    2 Dim arr()
    3        arr = Range("A1:A5")
    4 End Sub

           而这个说法有可能是错的。实际上,可能_Default 才是Range的默认属性

          1、_Default属性两个参数都是可选的。意味着两个参数都可以没有。而这个属性的返回值没有定义,意味着它可以是Variant()或Variant。

          2、Range("A1")和Range("A1").Value,从截图中可猜测上例的情况并不是省略了Value的写法。

          3、_Default是Range对象的默认属性,而且是没有名字的。(仅仅是推测,可以有不取名字的属性么?)

    推测证据1:

        [题外话:worksheets也有一个_Default默认属性,事实上,发现集合类对象几乎都有_Default默认属性(用作索引)。可自行求证] 

         下面这些写法是成立的:

    Debug.Print Range("A1:A5")(2, 1)

    Debug.Print Range("A1:A5")(1) 

    推测证据2:

          我们常用Cells(index,index)的方式表示一个单元格。那这个表示法是从何而来呢?Cells属性本身并没有参数,见图:

           但Cells属性返回的是Range对象,Range对象的默认属性即_Default:

    5Object类型和一个保留问题
         
    使用默认属性常常会见到这样的问题:

          正常运行的代码A

    1 Sub Test1()
    2 Dim arr()
    3     arr = Range("A1:A5")
    4 End Sub

         正常运行的代码B :

    1 Sub Test2()
    2 Dim arr
    3     arr = ThisWorkbook.Worksheets(1).Range("A1:A5")
    4 End Sub

         运行会报错的代码C

    1 Sub Test3()
    2 Dim arr()
    3     arr = ThisWorkbook.Worksheets(1).Range("A1:A5")
    4 End Sub

          上面的写法均省略了默认属性。(是Value?   还是_Dafault?)

          B和C等式右边的表达式是完全相同的。但在运行时,arr可以正常赋值,arr()就会报错。

          需要留意的是,Worksheets(1)的类型是Object,不是一个强类型。arr()遇到Object.Range(),正是这种情况会出现问题,而不能正常解析的问题原因没找出。

         

         上面报错的代码,如果换一种方式,先声明一个显式类型Worksheet,问题就解决了。

    1 Sub Test4()
    2 Dim arr()
    3 Dim sht As Worksheet
    4     Set sht = ThisWorkbook.Worksheets(1)
    5     arr = sht.Range("A1:A5")
    6 End Sub

    6、自定义类的默认属性 

          如何在自己类中定义默认属性呢?

          VB6实现:(一个对象只能有一个默认属性)

          步骤1:在写好属性过程后,然后点击工具—过程属性

         

         步骤2:在过程属性中,选择要设置为默认属性的名称,点选高级,最近设置过程标识符为“缺省”

         

       VBA实现:

       方法: 将类模块代码导出,使用文本编缉器(比如notepad)修改代码,然后重新导入VBA类模块。

       案例:写一个Person类,有一个属性叫P_name,现在想要设置它为Person类的默认属性。

     1 Private name As String
     2 
     3 Public Property Get P_name() As String
     4    P_name = name
     5 End Property
     6 
     7 Public Property Let P_name(ByVal vNewValue As String)
     8      name = vNewValue
     9 End Property
    10 
    11 Private Sub Class_Initialize()
    12     name = "张三"
    13 End Sub

        1、导出类文件到本地,默认文件名为:Person.cls
        2、使用文本编缉器打开。(文字涂灰的部分是自动生成的)
        3、修改属性过程代码,在P_name属性过程中添加一句:Attribute P_name.VB_UserMemId = 0
        4、将修改后的cls重新导入类模块。

     1 VERSION 1.0 CLASS
     2 BEGIN
     3   MultiUse = -1  'True
     4 END
     5 
     6 Attribute VB_Name = "Person"
     7 Attribute VB_GlobalNameSpace = False
     8 Attribute VB_Creatable = False
     9 Attribute VB_PredeclaredId = False
    10 Attribute VB_Exposed = False
    11 
    12 
    13 Private name As String
    14 
    15 Public Property Get P_name() As String
    16    Attribute P_name.VB_UserMemId = 0
    17    P_name = name
    18 End Property
    19 
    20 Public Property Let P_name(ByVal vNewValue As String)
    21      Attribute P_name.VB_UserMemId = 0
    22      name = vNewValue
    23 End Property
    24 
    25 Private Sub Class_Initialize()
    26     name = "张三"
    27 End Sub

          使用:

     1 Sub Test()
     2 Dim p As New Person
     3 
     4 Debug.Print p
     5 'Debug.Print p.P_name
     6 
     7 p = "李四"               '直接给对象赋值(实际赋值给了默认属性)
     8 Debug.Print p
     9 'Debug.Print p.P_name
    10 
    11 End Sub
  • 相关阅读:
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    449. Serialize and Deserialize BST
    114. Flatten Binary Tree to Linked List
    199. Binary Tree Right Side View
    173. Binary Search Tree Iterator
    98. Validate Binary Search Tree
    965. Univalued Binary Tree
    589. N-ary Tree Preorder Traversal
    eclipse设置总结
  • 原文地址:https://www.cnblogs.com/zzstone/p/6145874.html
Copyright © 2011-2022 走看看