2014-10-16 155 views
2

只是一個問題,我似乎無法找到答案。將用戶窗體聲明爲對象與MSForms.Userform之間的區別?

我正在編程創建一個用戶窗體,我發現如果我聲明我的對象爲「MSForms.Userform」類型,似乎沒有辦法設置高度和寬度,因爲這些屬性不存在,insideheight/insidewidth是隻讀屬性。

我發現的是,如果我將其聲明爲泛型類型「對象」,我可以設置高度和寬度屬性並按照我的意願使用它。

所以,以後我初始化對象,我查了當地人窗口和差異似乎是:

  • 當類型「對象」將初始化類型的實例「UserForm1」
  • 聲明
  • 當類型「MSForms.Userform」,宣佈它將初始化類型「窗體」的一個實例

所以我的問題是,是什麼在使用不同的申報statments區別?

謝謝!

編輯:添加了一些示例代碼,以便您可以看到如何聲明不同的方式時,對象的行爲是不同的。當您導入組件到項目

Sub TestUserForm() 
'NOTE: You need to add a reference to Microsoft Visual Basic 
'  for Applications Extensibility 5.3 

'Declare variables 
    Dim oForm   As MSForms.UserForm 
    Dim oForm1   As Object 
    Dim oComp   As VBComponent 
    Dim oComp1   As VBComponent 

'Create new form objects in the VBA project programmatically 
Set oComp = Application.VBE.ActiveVBProject.VBComponents.Add(ComponentType:=vbext_ct_MSForm) 
Set oComp1 = Application.VBE.ActiveVBProject.VBComponents.Add(ComponentType:=vbext_ct_MSForm) 

'Initailize an object of each new form 
    Set oForm = VBA.UserForms.Add(oComp.Name) 
    Set oForm1 = VBA.UserForms.Add(oComp1.Name) 

'Compare what happends when trying to set the width and height properties 
    With oForm1  'This works 
     .Height = 200 
     .Width = 100 
    End With 

    With oForm1  'This does not work 
     .Properties("Width") = 100 
     .Properties("Height") = 200 
    End With 

    With oForm  'This does not work 
     .Height = 200 
     .Width = 100 
    End With 

    With oForm  'This does not work 
     .Properties("Width") = 100 
     .Properties("Height") = 200 
    End With 

'Remove the forms from the project 
    Application.VBE.ActiveVBProject.VBComponents.Remove oComp 
    Application.VBE.ActiveVBProject.VBComponents.Remove oComp1 
End Sub 
+1

'UserForm1'是UserForm'的'特定實例,並且只在您的VBA項目的存在。類似於'Sheet1'和'Worksheet' – 2014-10-16 16:08:59

+0

蒂姆,我想我明白你在說什麼,但仍然困惑於聲明對象類型的差異。我在原始問題中添加了一些示例代碼,以便您可以看到我在說什麼。 – CBRF23 2014-10-16 19:42:11

+1

不同之處在於,至少有一部分是當你將它聲明爲一個對象時VB不會試圖驗證它的類型。你不明智,正如你看到它可以改變你如何訪問屬性。當你聲明某種類型的東西時,VB會獲得關於該類型的信息,併爲你提供intellisense中的屬性和方法。它也會阻止你將oForm設置爲不是UserForm的東西。 – jac 2014-10-16 20:24:11

回答

5

將它命名分別爲UserForm1可能UserForm2 -
(即使聲明爲基礎的語言,我不能得到這個代碼塊才能正常顯示)。

oForm == UserForm1

OFORM1 == UserForm2

現在,看着MSDN docs for Object我們發現:

可以聲明與對象數據的對象變量在特定對象類型未知時才鍵入,直到該過程運行。使用對象數據類型來創建對任何對象的通用引用。

你聲明的變量,像這樣:

Dim oForm   As MSForms.UserForm 
Dim oForm1   As Object 

所以,當你初始化對象是oForm被初始化爲用戶窗體,當運行時確定對象oForm1是發生了什麼UserForm1的實例,這是不一樣的事情。

嘗試在初始化之前更改oForm1的組件名稱,並且您應該很快看到差異。

現在,如果你想聲明的通用形式的類型安全,你要訪問的Width屬性,你可以投你的用戶窗體爲對象,以及訪問它像這樣。

Dim FormAsForm As UserForm 
Dim FormAsObject As Object 

Set FormAsForm = New UserForm1 
Set FormAsObject = FormAsForm 

FormAsObject.Width = 200 

Debug.Print TypeName(FormAsForm) 
Debug.Print TypeName(FormAsObject) 

這是我們在實現多個接口時經常使用的技巧。編譯器將只允許您使用在聲明類對象的特定類型中定義的屬性。


那麼有什麼區別?實際上,當你將對象聲明爲事物時,你不會有智能感知。你也沒有類型安全。這是完全有效的做到這一點(雖然不推薦)。

Dim foo As New Baz 
Dim bar As New Qux 
Dim var As Object 

Set var = foo 
Set var = bar 

對象不進來非常方便,當你使用後期綁定,以避免添加引用到您的項目,雖然。如果沒有添加引用,您將被迫使用未知類型。

Dim xl As Object 
Set xl = CreateObject("Excel.Application") 

另一個很大的區別是你將它留給運行時間來確定變量是什麼類型的對象。正如你發現的那樣,它有時(很少,但有時)會產生令人驚訝的結果。

+1

ckuhn2003,謝謝你對兩種情況下發生的事情的詳細解釋。對我瞭解正在發生的事情非常有幫助。 提供的示例很容易理解。 謝謝! – CBRF23 2014-10-17 19:07:05

+0

不客氣! – RubberDuck 2014-10-17 19:14:00

1

我覺得你有你對差異答案:

  • 一個是類UserForm1的用戶窗體對象,包裹在一個Object對象(類型對象/ UserForm1),可在PROC否則以後可以設定成什麼,
  • 另一個是UserForm2類的UserForm對象。

但是,編譯器將只允許使用屬性/方法對於現有類型的類對象被聲明爲:

  • 對象有.WIDTH和.Height屬性,因此OFORM1將允許您訪問VBE組件UserForm2的實例化形式的這些屬性(看看HERE進一步瞭解這一點),但oForm不會。
  • UserForms有一個.Show/.Hide方法,所以將有oForm顯示VBE組件UserForm1的實例化/加載形式,但oForm1不會。

我已經做了一些測試,我只是想在我認爲的修正過程寧可指向:

Dim FormAsForm As **UserForm1*** 
Dim FormAsObject As Object 

Set FormAsForm = New UserForm1 
Set FormAsObject = FormAsForm 

FormAsObject.Width = 200 

Debug.Print TypeName(FormAsForm) 
Debug.Print TypeName(FormAsObject) 

這裏宣佈FormAsForm爲UserForm1,而不是用戶窗體造成此錯誤在我的身邊:

運行時錯誤 '438':對象不支持此屬性或方法

然而,使用這個,FormAsForm已經加載並顯示一次後。顯示,然後卸載,FormAsForm從類型UserForm11/UserForm11降級到UserForm11/UserForm,並且不能用.Show再次顯示。任何應該工作方法會造成這樣的錯誤:

錯誤 '-2147418105':自動化錯誤

錯誤 '-2147418105':ERREUR自動化:L'appelé(serveur [PAS應用serveur])N」 est pas pas disponible et a disparu; aucune connexion n'est valide。 L'appel peut-êtreétéexécuté。

當然,變量類型我只是給了來自當地人VBE窗口被讀取,因爲類型名(FormAsForm)只會帶來一個:

運行時錯誤「13」:類型不匹配

對於記錄,?TypeName(FormAsObject)在downcast後返回UserForm,而.Show方法會導致相同的「自動化錯誤」。

empty

這整個的一部分,我無法解釋......

相關問題