也許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)
對象的默認屬性可能永遠不會被調用(並且毫無意義),因爲該參數已經是預期的返回類型。順便說一下,Range對象的默認屬性是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應用程序對象的屬性'。
有趣的問題,你也可以把它包裝在CStr()中,它將工作沒有價值。 '表格(CStr(Cells(1,2)))'。所以它必須與Sheets()本身有關。 –
看來Sheets()並沒有將值作爲字符串引入,而是試圖將值作爲Long來引入。如果你在A2中放入'1',它將抓取索引中的第一張,而不帶'.Value'。因此,爲了引入名稱,它要求它被告知它是一個字符串,使用CStr,.Value,或者你可以使用'「&Cells(2,1)'我認爲這是因爲Sheets()的默認查找,索引是一個Long而不是一個字符串。 –
@ScottCraner我認爲你已經找到了一些...............我會再試驗一些。 –