Associer une forme à une formule
Bonjour
J'ai associé une liste de choix ( validation de données) à une cellule excel.
En fonction de la valeur qui est sélectionnée dans le menu déroulant, je voudrais associer une forme (carré, losange) dans cette cellule ou une cellule adjacente.
Est ce que ca vous parait possible?
Merci d'avance.
Canic
Super,
Je n'avais pas pensé à l'option de la police.
Merci bcp
Bonjour tulipe, canic
Quelques remarques en marge et dans le prolongement du sujet...
On a en effet deux types de solutions relativement simples pour afficher des formes de ce type : soit générer un objet Shape en fonction du choix d'un nom de forme préalablement défini, soit utiliser une police qui comprend ces formes. Le choix dépendant du fait que l'on dispose d'une police adéquate par repport au projet et éventuellement de la dimension et du positionnement des formes.
Contrairement à ce qu'on pourrait penser le code d'un générateur de formes demeure relativement simple, dans la mesure ou toutes les formes polygonales peuvent être générées de la même façon, à partir d'un tableau de coordonnées...
Pour ce qui est des polices, en utilisant la table de caractères pour sélectionner les caractères souhaités, la table donne (dans l'angle inférieur gauche) le code (unicode) du caractère, sous la forme : U+xxxx. Ce xxxx est une valeur hexadécimale.
On peut la convertir facilement en décimal avec la fonction HEXDEC.
Excel dispose de fonctions CODE (renvoyant le code du caractère) et CAR (renvoyant le caractère à partir de son code) mais ces fonctions sont limitées à la table "ANSI" et ne prennent pas les caractères unicode.
Il n'y a pas de fonction pour cela (du moins jusqu'à la version 2010, au-delà je ne sais pas) mais on peut aisément créer des fonctions personnalisées pour cela. Par exemple :
Function CODU(car As String) As Long
Application.Volatile
CODU = AscW(Left(car, 1))
End Function
Function CARU(cod As Long) As String
Application.Volatile
CARU = ChrW(cod)
End FunctionSi on utilise CARU ci-dessus avec la valeur du code du caractère prélevé dans la table et converti en décimal, la fonction renverra le caractère.
Cordialement et bonne fin de weekend.
bonjour M Ferrand
comme tu l'auras constaté ; tout les carractères ne se pretent pas a une utilisation directe sans modification de la police de base du classeur
cordialement
Bonjour
Les caractères windgings ne suffisent pas à repondre au besoin.
Je souhaiterais pouvoir sur la base d'une case à cocher ou d'une liste déroulante faire afficher une forme construite manuellement avec l'outil Forme (voir exemple en pièce jointe).
Este ce joubale? A priori vu les messages ci dessous Oui mais il me faudrait un peu plus d'info sachant que je ne maîtrise la programmation des macros
merci d'avance
Merci Ceuzin
C'est bien ce que je recherche mais comment l'adapter maintenant sur une autre feuille.
J'ai essayé de rajouter sur ta feuille un dessin numéro 7 mais lors de la sélection dans le menu déroulant, il y a un bug.
y a t'il un moyen assez simple que je décripte le code VBA?
Si non peut être puis je vous envoyer ma feuille excel avec toutes les formes l'implantation déjà préte pour faire le code?
Bonjour,
Il y a de multiples façons de répondre à ta question...
Il serait bon de disposer d'un éventail complet des formes que tu souhaites utiliser, en précisant s'il y a lieu les détails (taille, épaisseur des traits, etc.)
Bjr
Je joins le fichier utilisé pour que éclaircir ma demande.
Voir onglets synoptique et données.
merci
Bonsoir,
Je livre une première version : la génération de formes se fait sur la feuille Synoptique. Elle est préparée et déclenchée par les évènements survenant sur la feuille.
La sélection d'une zone fusionnée sous liste déroulante provoque le calcul des paramètres.
Le changement dans cette zone provoque la suppression de la forme existante en regard et lance la génération d'une nouvelle forme selon sélection.
L'activation de la feuille provoque, si une zone fusionnée est sélectionnée, sa désélection (par sélection de la cellule de même niveau en 1re colonne) afin d'éviter qu'une opération soit lancée sans que les paramètres aient été calculés.
Les paramètres calculés sont pour le moment le nom de forme lié à l'emplacement sélectionné, les coordonnées (Left et Top) du point correspondant au centre de la forme à générer.
Le Module1 est dédié à ces calculs de paramètres.
Le Module2 contient la procédure de génération des formes.
Ce découpage doit te permettre de bien distinguer les différentes fonctions. Les explications détaillées, dès que je peux...
Cordialement.
Bonsoir,
Pour dégrossir les explications, d'abord les aménagements annexes apportés au fichier :
Sur la feuille Données, j'ai nommé Opér la plage B3:B43. En regard de la liste des opérations, en colonne E, j'ai indiqué le type de forme, codé : fftA à fftF.
Ce code type est l'indicateur qui permettra de la générer. La liste nommée Opér alimente la liste déroulante dans la feuille Synoptique. La sélection d'une opération dans cette liste permettra donc la détection du type de forme à produire.
Remarque : j'évite de multiplier les noms quand ce n'est pas indispensable... A partir d'un nom sur une feuille on peut atteindre n'importe quel emplacement d'une feuille...
Par exemple, j'ai sélectionné Dégraissage, je le cherche dans la plage Opér, et je le trouve à la 3e ligne de Opér, je sais aussi que le type correspondant que je veux extraire se trouve sur la même ligne et dans la 4e colonne comptée depuis Opér, donc :
[Opér].Cells(3, 4) me renverra le type cherché (le fait qu'il ne soit pas dans la plage nommée n'empêche nullement de l'atteindre à partir de ladite plage).
Ayant nommé la plage j'ai modifié la formule figurant en S dans Synoptique pour utiliser le nom. La formule utilise INDEX et EQUIV, et pointe la colonne cherchée avec DECALER appliqué à Opér. [L'équivalent en VBA utilise Offset, mais la méthode Cells comme vu plus haut permet une possibilité supplémentaire d'adressage relatif en VBA.]
J'ai laissé les indications des types visibles sur Données, pour que tu les voies ! Mais, n'ayant aucun besoin d'être vues pour que cela fonctionne, on peut mettre la police à blanc pour les masquer.
Voilà pour les éléments annexes.
Passons aux deux volets fonctionnels de l'opération : une forme est définie par des paramètres permettant de la construire d'une part (taille, nombre de sommets et leur disposition, épaisseur de trait...) d'une part, et d'autres permettant de la positionner et la retrouver (coordonnées sur une feuille, nom qui permet de l'atteindre).
Ces deux aspects doivent être bien distingués dans le dispositif global. Ils font l'objet chacun d'un module distinct de code, pas seulement parce que cela te permettra de t'y retrouver plus facilement, mais parce qu'un module séparé pour définir et stocker des paramètres définis automatiquement est logique (même si ce n'est pas complètement indispensable pour que cela fonctionne).
C'est l'emplacement de la sélection d'une opération qui conditionne l'emplacement de la forme qu'on ajoutera. C'est la sélection d'un emplacement qui déclenchera donc la définition et le stockage des paramètres liés à cet emplacement (une procédure SelectionChange de la feuille concernée donc).
On va utiliser le Module1 pour stocker ces paramètres. Trois variables sont déclarées au niveau module pour recueillir les paramètres : ffNom (type String) pour le nom de la forme lié à l'emplacement sélectionné (nom permettant de la supprimer s'il y a lieu) ; et deux de type Single (les données de positionnement sont de ce type), pcX et pcY, respectivement la distance en points du bord gauche et du bord haut au centre de la forme [la position du centre peut s'appliquer identiquement à tout type de forme, c'est lors de la création que l'on calculera les coordonnées Left et Top de positionnement de l'angle supérieur gauche de la forme, pouvant varier selon le type de forme].
Ces variables ne sont pas publiques, elles ne sont donc pas modifiables(ni accessibles) par des procédures situées dans d'autres modules. On va donc mettre en place dans le module des procédures destinées à affecter une valeur à ces variables ou à la renvoyer sur appel d'une autre procédure qui en a besoin.
On pourrait utiliser des procédures Sub et Function classiques pour réaliser cela, mais VBA dispose de procédures dédiées à cet usage, procédure d'écriture et de lecture de propriétés : Property Let pour définir une propriété (au cas particulier affecter une valeur à une variable), Property Get pour renvoyer la valeur d'une propriété (au cas particulier, renvoyer la valeur de la variable).
Ce procédé a l'avantage d'offrir d'emblée plus de clarté pour la compréhension de l'opération. Prenons le nom correspondant à une forme selon son emplacement : ce nom sera stocké dans la variable ffNom, on disposera d'une paire de procédure :
Property Get RefNom() As String qu'on pourra appeler pour renvoyer le nom,
et Property Let RefNom(Nff As String) qu'on appellera pour affecter un nom.
Ces procédures fonctionnement par paires (de même nom de procédure, la procédure d'affectation (Let) ayant un argument de plus que la procédure de renvoi (Get), argument dont le type de données est le même que le type de données renvoyé par Get.
[Même chose pour les coordonnées du centre, qu'on a regroupées dans une même paire de procédure, un argument supplémentaire "x" ou "y" identifiant la coordonnée concernée...]
Dans ce module on a donc le mécanisme de stockage et de renvoi des paramètres indiqués. Mais la définition des paramètres eux-mêmes est faite à l'extérieur de ce module. Comme indiqué au début, c'est la procédure SelectionChange de la feuille qui est en position de les définir.
Elle détermine si l'emplacement de la sélection se trouve dans le groupe de colonnes voulu et correspond à des cellules fusionnées. Si c'est le cas, il s'agit d'un emplacement où une opération peut être sélectionnée et associée à une forme.
Elle va donc définir les paramètres de la forme liés à l'emplacement : pour le nom par exemple, elle le forme avec l'adresse de la cellule fusionnée en éliminant le ":" et précédée de "ff", par exemple "ffD10N12", valeur qu'elle va affecter en utilisant la procédure Property Let RefNom sous la forme : RefNom = "ffD10N14" (ou une expression qui renvoie le nom).
[Même chose pour les coordonnées du centre de la forme, calculées sur la moitié de la distance entre le bord gauche et la cellule fusionnée, et la distance entre le bord haut et la mi-hauteur de la cellule fusionnée.]
Un effacement des paramètres est effectué lorsque la sélection n'est pas dans une cellule fusionnée, tout en se trouvant dans le groupe de colonnes adéquat (ce n'était pas indispensable mais..., par contre je ne l'ai pas fait pour le reste de la feuille pour éviter un déclenchement à répétition).
Un complément cependant intervient dans ce dispositif : si une cellule fusionnée se trouve sélectionnée lorsqu'on accède à la feuille, les paramètres peuvent ne pas avoir été définis ou avoir été effacés, et un changement d'opération provoquerait alors une erreur ou un résultat inattendu. Pour éviter cela, la procédure Activate de la feuille, si elle détecte que la cellule active se trouve dans une cellule fusionnée, déplace la sélection à proximité, permettant un recalcul des paramètres lors d'une sélection de cellule fusionnée.
Si l'évolution du projet conduit à devoir stocker d'autres paramètres, le même module sera utilisé pour ce faire...
Voilà pour ce volet qui déroge un peu aux façons courantes de procéder, mais qui demeure simple à appréhender une fois le tour fait des éléments inhabituels, et qui permet de distinguer et séparer la définition et le stockage de paramètres de leur utilisation ultérieure.
Bon weekend.
Dernier volet : la construction de la forme, à l'emplacement prévu.
Cette opération est lancée par l'évènement Change affectant une cellule fusionnée sous liste déroulante de la feuille Synoptique.
Lors d'une modification dans une telle cellule, la procédure est lancée, elle récupère d'abord le nom de la forme attachée à l'emplacement (en appelant la procédure de propriété ad-hoc, ainsi qu'on l'a vu précédemment), afin de la supprimer : si une telle forme n'existait pas cela déclencherait naturellement un erreur, donc cette partie de l'opération est sous gestion d'erreur, si la forme existait elle est supprimée, si elle n'existe pas la procédure se poursuit.
Si une opération a été sélectionnée dans la liste déroulante, la procédure l'identifie et identifie également le type de forme à générer pour l'opération sélectionnée. Elle lance alors la procédure de construction de la forme en lui en communiquant le type et la feuille destinataire. Les autres données étant définies automatiquement lors de changements d'emplacement, elles seront récupérées par le biais des procédures de propriétés...
Le dispositif de construction de formes est concentré dans Module2.
Est définie dans ce module une constante de taille (a) de type Single, dont on peut naturellement modifie la valeur, ce qui entrainera une variation de taille des formes construites.
Il s'agit d'une constante car à l'heure actuelle on ne génère qu'un lot de formes à taille unique (pour chacune). Cependant si l'on devaient étoffer et construire des formes de tailles diversifiées, cette constante devrait être transformée en variable, sa valeur variant alors selon des critères prédéfinis...
Et si ces critères devenaient liés à la position sur une feuille, un emplacement déterminé, etc., elle pourrait alors devenir définie automatiquement dans les mêmes conditions que le nom et les coordonnées de position du centre actuellement, d'autant plus que ces derniers paramètres varieraient forcément selon les mêmes critères.
(Elle prendrait alors naturellement place dans Module1 qui s'enrichirait des procédures afférentes. Ce qui accroîtrait les possibilités du dispositif, sans en modifier le fonctionnement global...)
Voyons le fonctionnement actuel de la contruction, qui est fort simple...
On aurait pu procéder à la construction en utilisant les types prédéfinis : rectangle, losange, cercle... ce qui aurait conduit à autant de procédures que de types, sans oublier les regroupements à opérer pour certaines formes (losange inscrit dans un rectangle, cercle inscrit dans un losange).
La simplification de cette opération consiste à utiliser une méthode unique de construction pour toutes les formes à générer.
La méthode consiste à les générer selon le type construction de forme libre : BuildFreeform.
On pose un premier point de construction (avec ses propriétés d'édition, qui seront invariablement "Auto" pour toute la construction, et ses coordonnées Left et Top).
On enchaîne ensuite la succession des points de construction (noeuds) : pour chacun le type de trait le liant au point précédent (qui sera soit ligne (Line) soit courbe (Curve)), la propriété d'édition (Auto), et les coordonnées.
Ce jusqu'à rejoindre le point de départ. La construction est alors convertie en forme (objet Shape) par la méthode ConvertToShape.
Pour que la procédure puisse s'appliquer à toutes les formes à construire, dont le nombre de points de construction est différents, elle a besoin que les coordonnées X (Left) et Y (Top) des points de chaque forme lui soient fournies sous forme de tableaux. Les coordonnées d'indice 0 étant celles du point de départ, la construction de chacun des points suivants 1 à fin pouvant alors se faire au moyen d'une boucle ajustée à la dimension des tableaux de coordonnées, méthode utilisable quel que soit le nombre de point.
Si la plupart des formes sont construites uniquement avec des lignes, l'une d'elles nécessite des courbes, ce qui justifie un 3e tableau pour le type de trait, utilisée dans les mêmes conditions que les tableaux de coordonnées.
A partir du type de forme, la procédure appelle une fonction pour lui demander de renvoyer selon le type de forme, un tableau des coordonnées X, un tableau des coordonnées Y, un tableau des types de traits ou segments. Elle récupère aussi le nom à donner à la forme.
Elle construit la forme, puis la finalise (pas de couleur d'intérieur, style et épaisseur du trait).
Pas utile de s'étendre sur la fonction, on lui fait renvoyer à chaque le tableau demandé selon les paramètres appelants... c'est un peu fastidieux à construire ( après avoir déterminé la dimension du tableau à renvoyer, énumération de valeurs calculées en utilisant les coordonnées du centre et la constante de taille pour définir le Left ou le Top de chaque point), mais on en tire indéniablement profit pour la suite.
Au total, deux procédures : la proc. de construction proprement dite (de taille relativement réduite) et une fonction lui fournissant les données nécessaires, suffisent et suffiront si l'on étend les possibilités tant que les formes construites peuvent l'être avec cette méthode.
Cordialement.