2016-05-15 129 views
3

我填A1A2如下:返回默認屬性

enter image description here
我然後運行:

Sub WhatIsGoingOn() 
    Dim r As Range, sh As Worksheet 

    Set r = Range(Cells(1, 1)) 
    Set sh = Sheets(Cells(2, 1)) 
End Sub 

我預計在這兩種情況下,VBA將使用單元格的默認屬性()屬性設置每個變量。但是,在最後一行代碼中出現運行時錯誤13!

爲了避免錯誤,我必須使用:

Sub WhatIsGoingOn2() 
    Dim r As Range, sh As Worksheet 

    Set r = Range(Cells(1, 1)) 
    Set sh = Sheets(Cells(2, 1).Value) 
End Sub 

這到底是怎麼回事?

+0

有趣的問題,你也可以把它包裝在CStr()中,它將工作沒有價值。 '表格(CStr(Cells(1,2)))'。所以它必須與Sheets()本身有關。 –

+1

看來Sheets()並沒有將值作爲字符串引入,而是試圖將值作爲Long來引入。如果你在A2中放入'1',它將抓取索引中的第一張,而不帶'.Value'。因此,爲了引入名稱,它要求它被告知它是一個字符串,使用CStr,.Value,或者你可以使用'「&Cells(2,1)'我認爲這是因爲Sheets()的默認查找,索引是一個Long而不是一個字符串。 –

+0

@ScottCraner我認爲你已經找到了一些...............我會再試驗一些。 –

回答

2

不同之處在於如何通過執行RangeSheets對象來處理對其默認屬性的輸入。

RangeSheets對象的默認屬性採用類型爲Variant的參數。你可以傳遞任何東西給它,所以不需要類型強制。在你的第一個例子中,你將一個Range對象傳遞給兩者。

默認屬性如何處理輸入取決於它們自己。顯然,Range的屬性嘗試檢索傳遞參數的默認值,在您的示例中爲String的地址。 Sheets對象似乎沒有如此寬容,並且引發錯誤,因爲您既沒有傳遞數字也沒有傳遞字符串。

不一致VBA的優勢之一...

順便說一句,路過CStr(Cells(2, 1))也將工作,因爲你明確地轉換爲字符串作爲參數傳遞之前。

+0

非常感謝! –

1

也許Leviathan的評論「不一致是VBA的強項之一......」可能是事實,但是他的回答忽略了一些背景細節(並且在一些細微的點上在技術上是不正確的)。他是正確的,對於給定的代碼,所有參數都是變體,但是「不需要強制類型強制」的說法在許多情況下可能是誤導性的,也許只是錯誤的。即使許多對象和方法被編程來處理多種類型和deafult值,但這個問題揭示了避免故意確保(或強制)正確的數據類型是錯誤的。完全避免默認屬性(通過始終輸入完整引用)可以避免許多令人頭痛的問題。

的代碼對於該特定問題的線之間的顯著區別是:範圍屬性即採用參數,而也是屬性但具有沒有參數。 範圍在這方面不是對象,儘管它們是屬性分別返回Range和Sheets對象。它們是爲特定模塊或Excel工作簿實例定義的(自動全局)對象的屬性。這些細節對於理解代碼實際在做什麼來說並不是微不足道的。

的Obect瀏覽器在窗口VBA揭示了兩個屬性的以下元數據:

Property Range(Cell1, [Cell2]) As Range 
Property Sheets As Sheets 

對於Range(Cells(1, 1)),參數Cells(1,1)被傳遞給參數Cell1。而且,事實證明Cells(rowindex, colindex)也是一個返回Range對象的參數化Property。所以這使得Set r = Range(Cells(1, 1))冗餘,因爲Set r = Cells(1, 1)是等價的。與Leviathan的回答相反,Cells(1, 1)對象的默認屬性可能永遠不會被調用(並且毫無意義),因爲該參數已經是預期的返回類型。順便說一下,R​​ange對象的默認屬性是Range.Value

Sheets類的默認屬性是參數化的Item(Index)方法。因此,Sheets(Cells(2, 1))相當於Sheets.Item(Cells(2, 1))。更重要的是,這意味着Sheets.Item(Cells(2, 1))傳遞一個Range對象作爲索引值,但文檔說它期望一個整數或字符串值。我們已經提到index參數是variant ...並且當將一個對象傳遞給一個變體時,它總是傳遞實際的對象而不是它的默認屬性。所以我們知道Sheets.Item在該調用中獲得一個Range對象。 Levithan是正確的,Sheets.Item可以決定如何處理它。它很可能已經足夠聰明,可以獲得單個字符串的值並繼續而不會出錯。 MS Office對象中的其他集合對象(具有默認的Item(index)屬性)似乎並沒有表現出同樣的「挑剔」,所以看起來Sheets.Item在驗證其參數方面相當嚴格。但這只是這種方法的一個特殊設計問題......不一定是VBA的總體問題。


難以確定哪些屬性的源對象是()。在ThisWorkbook模塊中,Me.Sheets顯示Sheets是模塊特定工作簿的屬性。但Me.Range在工作簿模塊中無效,但右鍵單擊Range屬性(不帶Me限定符),並選擇「定義」結果顯示消息「因爲隱藏而無法跳轉到範圍」。在這方面,從表單模塊調用它們時(即Me.Range有效,但不是Me.Sheets),Range和Sheets屬性相反。

爲什麼不一致和隱藏屬性?爲了使Excel的當前實例及其所有組件以「自然」方式可訪問,Excel(和所有Office應用程序)實現了這些各種隱藏屬性,以避免必須重複發現並輸出完整的「複雜性」引用。例如,自動全局應用程序對象也具有Range和Sheets屬性。例如,實際的documentation for Application.Sheets表示「使用不帶對象限定符的此屬性等效於使用ActiveWorkbook.Sheets」。即使該文檔沒有說的是,ActiveWorkbook反過來是全球Excel應用程序對象的屬性'。

+0

感謝您的意見。 –