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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM