2010-04-30 4 views
2

J'ai ajouté des contrôles de formulaire à une collection et je peux récupérer leurs propriétés lorsque je me réfère aux membres par index.Pourquoi ne puis-je pas obtenir les propriétés des membres de cette collection?

Cependant, lorsque j'essaie d'utiliser des propriétés en référençant des membres de la collection, je vois un 'Impossible de définir la propriété ControlSource. Membre introuvable. 'erreur dans la fenêtre Locals.

Voici une version simplifiée du code:

'Add controls to collection' 
For x = 0 To UBound(tabs) 
    activeTabs.Add Item:=Form.MultiPage.Pages(Val(tabs(x, 1))), _ 
     key:=Form.MultiPage.Pages(Val(tabs(x, 1))).Caption 
Next x 

'Check name using collection index' 
For x = 0 To UBound(tabs) 
    Debug.Print "Tab name from index: " & activeTabs(x + 1).Caption 
Next x 

'Check name using collection members' 
For Each formTab In activeTabs 
    Debug.Print "Tab name from collection: " & formTab.Caption 
Next formTab 

Les résultats dans la fenêtre immédiate sont:

Tab name from index: Caption1 
Tab name from index: Caption2 
Tab name from collection: 
Tab name from collection: 

Pourquoi une méthode de travail et l'autre échec?

Ceci est dans un module de code standard, mais j'ai un code similaire qui fonctionne très bien à l'intérieur des modules de formulaire. Cela aurait-il quelque chose à voir avec cela?

Edité pour ajouter

formTab a été déclarée comme témoin, mais je trouve que si elle est déclarée comme un objet puis le code fonctionne. Cela résoudra probablement mon problème, mais dans le but d'améliorer mes connaissances, je serais reconnaissant pour toute explication de ce comportement, en particulier en ce qui concerne la différence dans l'exécution du code dans les différents types de module.

Répondre

4

C'est une très bonne question. Votre modification à la fin de la publication révèle beaucoup de choses sur le fonctionnement de VBA et sur ce qui se passe ici. Je ne suis pas à 100% de ce qui se passe, mais je vais vous expliquer ce que je pense qui se passe.

Un Collection dans VBA (et VB6, d'ailleurs, même base de code) n'est pas fortement typé. Cela signifie que tout dans une collection est techniquement un "objet". Dans le monde .NET (à partir de .NET 2.0), il est possible d'avoir des collections fortement typées afin de pouvoir dire "tout dans cette collection est un objet Control". En VBA, ce n'est pas possible avec un Collection.

Lors de votre première itération, lorsque vous faites référence à l'article indexé dans la collection activeTabs, activeTabs(x + 1) fait référence à un object. Lorsque vous dites à VBA de rechercher .Caption de cet objet, il ne sait pas quel est le type sous-jacent (je pense), il doit donc simplement regarder si le type d'objet sous-jacent contient une propriété ou une méthode appelée Caption. Comme vous pouvez le voir, les contrôles Tab contiennent en fait une propriété appelée Caption.

Dans votre deuxième interation, où vous faites une boucle For Each, je pense que le problème est que le type Control n'a probablement pas une propriété appelée Caption, bien que différents types des contrôles font probablement. Par exemple, un contrôle de zone de texte n'a probablement pas de propriété Caption alors que le contrôle d'étiquette possède une propriété Caption.

Vous avez quelques options pour réparer votre deuxième boucle. 1) Vous pouvez déclarer formTab comme un contrôle Tab (je ne sais pas exactement comment il s'appelle). Le contrôle Onglet doit avoir une propriété Caption.2) Si chaque contrôle dans activeTabs n'est pas spécifiquement un contrôle onglet (dans ce cas, vous devriez probablement l'appeler activeControls au lieu de activeTabs), vous pouvez vérifier dans votre boucle pour voir si le formTab est en réalité un contrôle onglet. Si c'est le cas, lancez-le sous la forme d'un contrôle Onglet, puis appelez le .Caption. Jusqu'à ce que vous le transtypiez en tant que contrôle Onglet, VBA ne saura pas qu'il possède une propriété Caption car un objet Control normal ne possède pas de propriété de légende. En fin de compte, vous pouvez vous en sortir en utilisant des objets comme dans votre première boucle et en laissant le temps d'exécution découvrir ce qu'il faut faire, mais cela peut donner de très mauvaises performances. En général, il est préférable de travailler avec vos types spécifiques dans un langage fortement typé. Cela aide également à montrer dans votre code que vous savez précisément avec quoi vous travaillez plutôt que de le laisser à l'exécution pour décider quelles propriétés et méthodes vous pouvez utiliser.

+0

Merci, cela a beaucoup de sens. J'ai déclaré formTab comme page (le nom correct pour le contrôle, je préfère simplement les appeler des onglets) et comme vous le prédisez, cela fonctionne très bien. J'ai également copié le code dans un module de formulaire et là il fonctionne indépendamment du fait que formTab soit déclaré comme un contrôle, une page ou un objet. Bizarre. – Lunatik

+0

@Lunatik VB va parfois sauter à travers beaucoup de cerceaux pour essayer de comprendre ce que vous essayez de faire. Malheureusement, cela ne conduit pas toujours à un bon code et vous permettra de ne pas savoir vraiment ce que fait votre code. J'ai écrit une tonne de code où je ne savais pas ce qu'il faisait mais VBA a permis que ça marche :-). –

Questions connexes