Affecter un propriété à plusieurs Shapes

Bonjour,

Je développe un programme qui manipule des formes (Shapes) sur un feuille Excel.

J’ai déjà simplifié mon code en définissant un variable Sr à laquelle j’ai affecté les formes de ma feuille Wr :

Set Sr = Wr.Shapes.

Ça marche très bien, car pour accéder à la forme « RC » de ma feuille « Wr » il suffit d’écrire :

Sr(« RC ») à la place de Wr.Shapes(« RC »).

Mais je dois souvent affecter une propriété à plusieurs objets en écrivant :

Sr.Range(Array(« RC », « Vx », « Vy », etc)

Je suis persuadé qu’il est possible de simplifier ici aussi mon écriture en tapant quelque chose comme :

Rs(« RC », « Vx », « Vy », etc).

C’est bête, mais je n’y arrive pas !

Merci à celui qui voudra bien m’aider…

bonjour,

C’est bête, mais je n’y arrive pas !

c'est parce que selon moi, ce n'est pas possible.

vba te permet parfois des raccourcis en prenant des options par défaut. mais dans ce cas-ci l'option par défaut, appliquée à la syntaxe que tu veux utiliser te donne une erreur.

si tu veux simplifier l'écriture d'une instruction, tu peux écrire une fonction ou écrire une courte séquence de caractères au moment de l'écriture de ta macro, puis utiliser chercher/remplacer pour remplacer cette séquence par la syntaxe correcte de ton instruction

Merci à h2so4, je n'avais pas pensé à la solution "fonction" !

A+

Bonjour GEOLEK, H2so4,

On peut appliquer une ou un ensemble de propriétés à plusieurs formes simultanément.

Par contre, il est préférable que ce soit un nombre limité (en une voire jusqu'à deux dizaine(s) de formes). Après tout dépend du contexte...

Voir le code ci-dessous.

Public Sh() As String
Sub Groupe()
'Le choix des formes à affecter: Exemple sur 2 formes rectangle nommées Rect1 et Rect2 dont on veut changer la couleur
'Séparer les différentes formes par un espace, caractère par défaut pour Split. Et appliquer le nombre de formes affectées à Union
Sh = Split("Rect1 Rect2"): Union (2)
End Sub

Sub Union(Nb As Integer)
'Macro gérant la ou les propriété(s) affectant les formes choisies de la feuille "Forme"
Set Sr = Sheets("Forme").Shapes
Select Case Nb  'Nombre de formes touchées pour la propriété
Case 2
Set Rs = Sr.Range(Array(Sh(0), Sh(1)))  'Le cas exemple: Sh(0) est "Rect1", Sh(1) est "Rect2")
Case 3
Set Rs = Sr.Range(Array(Sh(0), Sh(1), Sh(2)))
'etc... rajouter autant de Case que de formes devant être touchées par la propriété
End Select
'Sélection des formes
Rs.Select
With Selection
.Interior.ColorIndex = 24 'Propriété a affecter aux formes, ici un fond bleu clair
End With
Range("A1").Select
End Sub

Bons tests, bonne continuation.

bonjour Xcellus,

je pense que la demande de Geolek était "comment s'affranchir de cette syntaxe range(array( ..."

Sr.Range(Array(Sh(0), Sh(1)))

A nouveau,

@H2s04,

Mais je dois souvent affecter une propriété à plusieurs objets en écrivant :

Sr.Range(Array(« RC », « Vx », « Vy », etc)

Je suis persuadé qu’il est possible de simplifier ici aussi mon écriture en tapant quelque chose comme :

Rs(« RC », « Vx », « Vy », etc).

Comme tu as pu le voir, j'ai proposé deux macros. La deuxième fait office de Pack. J'aurais pu la nommer UnionPack...

La 1ière est la simplification souhaitée par Geolek; Rs("Rc"...etc..). C'est uniquement sur celle-ci que l'on agit.

L'autre est réalisée une fois pour toute. Avec la ou les propriété(s) applicables aux formes souhaitées.

Donc plus besoin de répéter Array à chaque fois que l'on veut manipuler certaines formes. Il suffit d'appeler le Pack prévu pour cela, selon le schéma évolutif de la 1ière macro. Plus il y aura de formes, plus il y aura de split.

Après il prend ou pas...

A+

@ X Cellus

au temps pour moi !

Merci pour votre aide qui m’inspire pour d’autres séquences de mon projet !

Dans ce projet, je manipule souvent des chaînes de caractères, donc des séparateurs.

Je choisi toujours l’espace parce qu’il ne doit pas être spécifié, en ensuite, pour plus de clarté dans mon code, le caractère « | » (ne figurant ni dans l’alphabet, ni dans la ponctuation).

Comme expliqué dans ma demande d’aide, mon problème est de devoir souvent modifier la propriété « Visible » des nombreuses formes « Shapes » de ma feuille.

Vos idées m’ont fait trouver la solution ci-dessous qui me convient parfaitement.

Lorsque je dois afficher ou masquer des formes, j’introduis dans une variable String la liste des formes que je désire effacer ou afficher. Par exemple :

T = « Sp1 Sp2|Sp3 Sp4 » … si je désire masquer (Sp1, Sp2) et afficher (Sp3, Sp4), ou

T = « Sp1 Sp2 Sp3 Sp4| » … si je dois tout masquer (séparateur « | » à la fin), ou

T = « Sp1 Sp2 Sp3 Sp4 » … si je dois tout afficher (sans séparateur)

J’envoie ensuite T dans la « GoSub » ou la procédure suivante :

Public Sub SpVis(arg As String)

'Masque les formes dont le nom est donné dans <arg> avant le séparateur "|"

'Affiche celles dont le nom est donné après le séparateur ou si ce dernier est absent

Dim T As String, U As String

Set Sr = Wr.Shapes

While InStr(T, "|") > 0

U = Split(Split(T, "|")(0))(0): T = Mid(T, Len(U) + 2): Sr(U).Visible = False

Wend

While T > ""

U = Split(T)(0): T = Mid(T, Len(U) + 2): Sr(U).Visible = True

Wend

End Sub

… et le tour est joué ! … C’est pas beau Excel ?

J’ai découvert que les syntaxes :

• Split(T)(0) ou Split(T, « | »)(0) … ne provoquent pas d’erreur si T ne contient pas de séparateur. Dans ces cas-là, elles renvoient T (ou rien si T est nul).

• Mid(T, 6) … ne provoque pas d’erreur si Len(T) < 6.

Encore merci à vous !

A nouveau,

Très bien, il y a en effet différentes façons d'arriver à Rome (au résultat) selon le contexte et les besoins de chacun.

Dans le cas de la propriété visible des formes. On peut aussi rendre visible toutes les formes. Puis ensuite ne rendre qu'une sélection de formes invisibles.

Bonne continuation.

Merci encore X Cellus car, sans le savoir, tu m'as remis sur une piste très intéressante !

Je connaissait bien cette possibilité de passer par une fonction distincte de la procédure développée pour traiter une liste d'instructions récurantes.

Mais je m'entêtait à le faire via des "GoSub", pour ne pas multiplier le nombre de procédures de mon code.

J'avais commencé à me rendre compte que cette méthode n'est pas très pratique car, outre le fait que chaque GoSub allongeait ma procédure, elle m'obligeait souvent à définir de nouvelles variables pour ne pas foutre le bordel dans celles utilisées dans la partie principale de la procédure.

Une fonction extérieure ne présente pas cet inconvénient.

Du coup je me suis demandé si on ne pouvait pas concevoir une Fonction "universelle" qui serait appelée par n'importe quelle procédure lorsque des problèmes récurants devaient être traités. C'est un peu l'idée que l'on retrouve dans la solution que tu as proposée pour résoudre mon problème.

J'ai donc créer cette fonction universelle que j'ai appelée "FU".

Je compte l'utiliser pour supprimer tous les "GoSub" du très gros programme que je développe, donc beaucoup de lignes et de variables puisque celles de ma fonction seront disponibles pour exécuter toutes les routines du code.

Je la recopie ci-dessous pour le cas où cela pourrait inspirer l'un ou l'autre.

Elle contient ici les quelques lignes que j'avais trouvées ce matin pour traiter mon problème actuel de deux façon différentes : en passant l'argument par un tableau (ID = 100) ou par une chaîne une variable String (ID = 101).

Voici la ligne, toute simple, qui doit être écrite dans la procédure appellante dans chacun des deux cas :

Dim A(0): A(0) = "Sp1 Sp2... " (liste des nom de formes à masquer ou afficher): FU 100, A

... cette option n'a de sens que si l'on doit passer n arguments, dans ce cas la procédure appelante doit définir : Dim A(n)...

Ici, la seconde option est plus sympa car elle envoie directement la liste dans l'argument (Variant) A (qui devient String) :

Fu 101, "Sp1 Sp2... "

... tout simplement, mais ma fonction peut traiter toutes les situations.

Public Function FU(ID As Byte, Optional A As Variant) As Boolean

'Fonction Universelle pouvant exécuter des instructions sur base des valeurs reçue dans son second argument <A>

'Si ces valeurs ne sont pas utiles ou qu'elles doivent être recherchées par la fonction, l'argument A est omis.

'La série d'instructions à exécuter est déterminée par l'index <ID> donné en premier argument.

'Peut être utilisée en mode "Function" pour retourner une valeur booléenne ou en mode "Sub" pour exécuter les

'Instructions et, si nécessaire, retourner des valeurs de tout type à travers l'argument A.

'Cet argument peut être un tableau dont les dimensions sont déterminées par la procédure appelante en fonction

'du nombre de valeurs à passer à l'appel et au retour.

'Définition de variables pouvant traiter tous les appels :

Dim L As Integer, C As Integer, i As Integer, j As Integer, k As Integer

Dim T As String, U As String

Select Case ID

Case 100, 101

Set Sr = Wr.Shapes

If ID = 100 Then T = A(0) Else T = A

While InStr(T, "|") > 0

U = Split(Split(T, "|")(0))(0): T = Mid(T, Len(U) + 2): Sr(U).Visible = False

Wend

While T > ""

U = Split(T)(0): T = Mid(T, Len(U) + 2): Sr(U).Visible = True

Wend

Case 102

...

Case 103

etc ...

End Select

End Function

Désolé d'avoir été aussi bavard, mais comme vous le savez tous, on voit plus clair dans ses propres solutions quand on fait l'effort de les expliquer aux autres !

Merci encore !

Rechercher des sujets similaires à "affecter propriete shapes"