Aller au contenu

Récuperer la valeur d\'un Attribut


Messages recommandés

Posté(e)

Bonjour,

Je recherche la façon en lisp de [surligneur] lire la valeur [/surligneur]d'un Attribut pour l'exploiter dans le reste de mon programme.

Je n'arrive pas à récuperer la valeur de 191.00 de lst (une liste ?)

Ensuite comment modifier le lisp si j'ai 2 attributs ? NGFZ et NIVEAU

 

Nom du bloc : NGFX

Nom de l'attribut : NGFZ

 

La routine est de la "récup" de plusieurs lisp

 

Routine :

 

 (Defun C:NGF ()
(setq BN "NGFX")

(setq EN (cdr (assoc -2 (tblsearch "BLOCK" BN))))

    (while EN
       (setq EL (entget EN))
       (if (= (cdr (assoc 0 EL)) "ATTDEF")
          (setq TAGL (cons (cdr (assoc 2 EL)) TAGL)))
       (setq EN (entnext EN))
    )
;*******************************************
  (if TAGL
    (progn
      (setq TAGS (car TAGL)
            TAGT (cdr TAGL)
      )
      (foreach TAG TAGT
        (setq TAGS (strcat TAGS " " TAG))
      )
    )
  ); fin if TAGL
;*******************************************
(initget TAGS)
(setq Esel "NGFZ")
          (setq ESel (xstrcase ESel))
          (if (member ESel TAGL)
            (setq Pass 'T
                  TG    ESel
            )
            (prompt "\nInvalid attribute name.")
          ); fin if
;*******************************************

        (Setq
           SS1 (SsGet "_X"
                (List
                   (Cons 0 "INSERT")
                   (Cons 2 bn)
                   (Cons 66 1)
                )
             )
           N (If SS1 (SsLength SS1) 0)
        )
;*******************************************
(setq ss ss1)

(setq n 0)
(repeat (sslength ss)
 (setq   na (ssname ss n)
         e1 (entget na)
        lst (acet-insert-attrib-get (list na 1))    ;<---- la valeur de lst est ((NGFZ 191.00))
        blk (cdr (assoc 2 e1))
        hnd (cdr (assoc 5 e1))
       lst3 (append lst3 (list (list hnd blk lst)))
 );setq
;*******************************************
) ; fin defun

[Edité le 22/8/2011 par ASTERIXII]

Posté(e)

coucou

 

faire des copier-coller dans des routines sans vraiment savoir ce qui se passe

n'est pas, à mes yeux, une bonne méthode

 

essaie de te taper ton code, tu comprendras bien mieux ce que tu fais

 

ton cas est simple

 

tu choisis ton bloc

(setq ent (car (entsel)))

 

tu recherches la valeur de l'attribut

je fais simple, je sais que mon attribut à changer est le premier attribut du bloc

(setq valatt (cdr(assoc 1 (entget (entnext ent)))))

en français je mémorise le code 1 de la liste de définition

de la première entité suivante de mon bloc (attribut en première position)

 

ensuite tu la modifies avec entmod, tu connais ?

 

amicalement

Posté(e)

Bonjour,

Pour la methode, c'est que j'ai le niveau débutant et que la gestion des blocs et compliqué.

Ensuite, je ne veux pas selectionner le bloc ni modifier l'attribut mais seulement

lire la valeur.

Dans mon code [surligneur] lst (acet-insert-attrib-get (list na 1)) ;<---- la valeur de lst est la valeur que je cherche[/surligneur]

mais je n'arrive pas à la passer à une variable

 

[Edité le 22/8/2011 par ASTERIXII]

Posté(e)

Salut,

 

Je suis entièrement d'accord avec la remarque de Didier, à fortiori si tu es débutant.

 

je ne veux pas selectionner le bloc

Cette remarque illustre bien que tu comprends pas précisément ce que tu fais (ni ce que tu veux faire).

Si tu ne sélectionne pas de référence de bloc, comment le programme peut-il deviner la valeur de quelle référence de bloc il doit trouver ?

 

Quand tu utilises tblsearch, tu cherches dans une table des blocs une définition de bloc (et pas une référence). Une définition de bloc ne contient que des définitions d'attributs qui n'ont pas de valeur (si ce n'est une valeur par défaut).

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

coucou

 

je crois bien qu'on parle d'une même voix, avec (gile) ;)

 

à ASTERIXII,

 

quand on débute, je file la métaphore de l'enfant sans te manquer de respect

on append à marcher avant d’appendre à courir,

 

c'est sûr que si tu copies-colles des morceaux de routines à droite et à gauche

tu vas dans le mur tête baissée.

 

il faut se fixer un objectif très simple pour commencer.

 

tu vas trouver TA façon d’appréhender les choses

moi je passe par l'ordre des attributs lorsque je fais dans le simple

un autre passera par le contrôle de l'étiquette

chacun sa route mais on arrive au même point.

 

efface ta routine,

repars d'une feuille blanche

les anciens combattants, comme moi, avaient un environnement hostile pour apprendre

vous, les nouveaux venus, avez l'éditeur lisp, rien que ça c'est une révolution

servez-vous-en tonnerre de Brest!

 

amicalement

 

Posté(e)

Vraiment un grand merci, vous êtes d’un grand secours.

 

Je pensais être dans la section débutant, mais il doit y avoir encore plus bas.

 

J’ai cherché avant de poser la question, pas comme d’autre, (la preuve une partie du code), mais à chaque fois c’était pour modifier l’attribut ou l’exporter.

 

Enfin bref ce n’est pas ici ou aujourd’hui que je vais trouver la réponse

 

Bonne soirée aux anciens combattants !

Posté(e)

Re,

 

Je ne pense pas que les conseils donnés soient de mauvais conseils.

T'aider à continuer dans le sens où tu as commencé serait par contre une fort mauvaise chose.

 

Ton code utilise des fonctions issues des express tools ou non renseignée (acet-insert-attrib-get ou xstrcase) là où des fonction LISP natives renseignées dans l'aide feraient très bien l'affaire.

 

Des portions de codes sont inutiles ou contradictoires :

        (Setq
           SS1 (SsGet "_X"
                (List
                   (Cons 0 "INSERT")
                   (Cons 2 bn)
                   (Cons 66 1)
                )
             )
           N (If SS1 (SsLength SS1) 0)
        )

 

puis :

 

(setq ss ss1)

(setq n 0)

 

Les variables ne sont pas localisées : des doublons vont s'ajouter à TAGL à chaque appel de la commande...

 

Commence par poser clairement ce que tu veux faire en réfléchissant à comment y arriver avant d'écrire une seule ligne de code :

Connaitre la valeur d'un attribut -> quel attribut de quel bloc

=> Comment obtenir l'entité bloc ?

=> Comment accéder aux attributs dans un bloc ?

=> Comment récupérer la valeur d'un attribut particulier ?

 

Là on pourra peut-être te guider et tu apprendras bien plus.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

coucou

 

à moins de me fourvoyer,

il me semble détecter de l'ironie dans tes propos.

 

si tu décides de prendre les choses ainsi, libre à toi

mais dis-toi quand même que je n'ai pas pris le clavier

pris le temps de taper un début d'exemple

pour me voir revenir en réponse des propos irascibles.

 

t'imagine un prof qui se prend des réflexions dans le tronche

parce que l'école c'est compliqué sans les copier-coller...

 

si tu changes d'avis, tu trouveras de l'aide ici

dans le cas contraire, bonne chance.

 

amicalement

Posté(e)

Re,

Question

quel est la difference entre :

(setq ent (car (entsel))) ;selection souris

qui donne comme valeur [surligneur] [/surligneur]et

(setq ent2 (cdr (assoc -2 (tblsearch "BLOCK" BN)))) ; selection par code

qui donne comme valeur [surligneur] [/surligneur]

 

Pourquoi des valeurs differentes ?

 

Suivant le début de code de didier

(Defun C:NGF ()

(setq BN "NGFX")

(setq ent (car (entsel))) ;selection souris

 

(setq ent2 (cdr (assoc -2 (tblsearch "BLOCK" BN)))) ; selection par code

 

(prompt "\n******* ent *****")

(princ ent)

(prompt "\n******* ent2 *****")

(princ ent2)

 

(setq valatt (cdr(assoc 1 (entget (entnext ent)))))

 

(prompt "\n******* valatt *****")

(princ valatt)

)

Posté(e)

coucou

 

le premier donne le nom de la sous-entité

qu'est l’attribut du bloc sélectionné

 

le deuxième donne le nom de l'entité

dans la définition des tables de blocs.

 

rien à voir entre les deux

 

le premier sert à "jouer" sur l'entité sélectionnée

changer la valeur de l'attribut, son calque, son style ...

 

le deuxième sert à redéfinir les qualités du bloc

(dans tout le fichier dessin)

 

sans doute que l'excellent (gile) sera plus explicite

tellement il maîtrise la théorie de la chose.

 

il serait tout de même utile que tu expliques où tu veux en venir

 

amicalement

 

 

Posté(e)

Merci pour cette réponse construtive, effectivement, en jouant avec la fonction

(setq valatt2 (cdr(assoc 2 (entget ent2)))) ou ent2 provient de tblsearch "BLOCK" je viens de voir que je n'ai que des infos sur le bloc et l'attribut, mais pas sa valeur.

 

Bref, ou je veux en venir, en faisant simple:

J'ai un bloc dans mon plan avec un attribut

Nom du bloc NGFX nom de l'attribut NGFZ

je veux récuperer la valeur de l'attribut pour l'utiliser dans mon programme.

Mais la " [surligneur] sélection[/surligneur]" de l'attribut ne doit pas se faire avec la souris, mais par le programme, puisqu'il connait le nom

Posté(e)

Bonjour ASTERIXII,

 

Le problème posé, n’est pas vraiment un souci de programmation mais plutôt un problème d’inconnue en trop ( ou d’une donnée manquante), explications :

 

Ce que je connais :

Nom du bloc NGFX nom de l'attribut NGFZ

 

Ce que je cherche :

je veux récuperer la valeur de l'attribut pour l'utiliser dans mon programme.

 

Comment je procède :

la " sélection" de l'attribut ne doit pas se faire avec la souris, mais par le programme, puisqu'il connait le nom

 

Bien tenté mais hélas ça ne suffit pas. Effectivement il connait le nom de la référence de bloc (NGFX), et dans le cas ou j’ai un seul bloc NGFX insérer dans mon dessin je peux me servir de cette donnée pour sélectionner mon bloc et extraire la valeur de l’attribut NGFZ.

 

Mais dans le cas ou j’ai plusieurs référence du bloc NGFX insérer dans mon dessin comment faire, comment cibler la valeur que je veux extraire, au mieux si il y a 5 références du bloc NGFX je peux les sélectionner et extraire les valeurs de leurs attributs respectifs soit 5 valeurs sans savoir laquelle je recherche en particulier.

 

Voilà ou on bloque pour pouvoir t’aider par la suite..

A+

 

Apprendre => Prendre => Rendre

Posté(e)

Effectivement , bonne question

 

il n'y à qu'un bloc dans le dessin.

 

Je vais plus loin dans l'explication de mon but.

 

Je recherche une methode pour memoriser une valeur (NGF) dans mon dessin, pour qu'à la prochaine ouverture du plan, je la retrouve automatiquement, et sans passer par un fichier en ecriture.

C'est pour cette raison que j'ai pensé au bloc, mais il y à peut-être une autre solution ?

Posté(e)

Re,

 

Il faut bien faire la différence entre : définition de bloc et référence de bloc.

 

Une définition de bloc (dxf : BLOCK) est un enregistrement d'un certain nombres d'entités graphiques plus, éventuellement, une ou plusieurs définitions d'attributs (dxf : ATTDEF). C'est une entité non graphique enregistrée dans le dessin dans la table des blocs. On crée des définitions de bloc avec la commande BLOC.

Quand on modifie une définition de bloc (depuis l'éditeur de bloc ou par programmation) ces modifications seront répercutées sur toutes les références à cette définition insérées dans le dessin.

 

Une référence de bloc (dxf : INSERT) est une entité graphique qui n'est, comme son nom l'indique, qu'une référence à une définition de bloc. On crée des référence de blocs avec la commande INSERER et en choisissant une définition dans la table des blocs du dessin ou en sélectionnant un fichier DWG ou encore en important une définition depuis un autres dessin (DesignCenter ou Palette). Dans les deux derniers cas, la définition du bloc est ajoutée à la table du dessin courant.

Si la définition de bloc contient des définitions d'attributs, la référence insérée contiendra des références d'attributs (dxf : ATTRIB) dont les valeurs sont les seuls objets modifiables dans une référence de bloc.

 

Les fonctions tblsearch, tblnext, tblobjname cherche dans les tables (de blocs, de calques, etc) et n'accèdent donc qu'à des objets non graphiques (enregistrements ou définitions).

 

Pour accéder aux référence de blocs, entités graphiques insérées dans les espaces objet ou papier (ces espaces sont aussi des sortes de définitions de blocs "ouvertes" comme on ouvre une définition de bloc dans l'éditeur de bloc), pour accéder aux références, donc, il faut les sélectionner avec ou sans intervention de l'utilisateur.

 

La fonction entsel permet de sélectionner une seule entité avec intervention de l'utilisateur et retourne, en cas de succès une liste contenant le nom d'entité (type ENAME) et le point cliqué (coordonnées SCU courant).

 

La fonction ssget permet de sélectionner une ou plusieurs entités avec ou sans intervention de l'utilisateur. Elle retourne un jeu de sélection (type PICKSET) qui contient, entre autres, les entités sélectionnées.

Utilisée sans intervention utilisateur, ssget soit parcourt l'intégralité des espaces (option "_X") ; soit sélectionne les entités sous le point spécifié ; soit encore fait une sélection par fenêtre ou capture polygonale en fonction des points spécifiés.

L'utilisation de filtres de sélection permet de limiter la sélection à un onglet donné, à un ou plusieurs calques, à un ou plusieurs types d'entité, etc.

 

On accède ensuite aux entités contenu dans un jeu de sélection avec la fonction ssname à laquelle il faut passer comme arguments le jeu de sélection et l'indice de l'entité (0 pour la première).

(ssname ss 0)

retourne donc le nom d'entité de la première entité contenue dans ss.

 

Quand tu as enfin obtenu le nom d'entité (ENAME) de ta référence de bloc, pour atteindre les références attributs, il faut utiliser la fonction entnext qui retourne l'entité dans la base de donnée suivant celle qui est passée en argument.

Quand on insère un bloc avec attributs dans un dessin, la référence de bloc est d'abord ajoutée à la base de données, puis chacune des références d'attributs puis un objet de type SEQEND qui indique la fin de la séquence pour une référence de bloc et ses attributs.

On utilise donc entnext dans une boucle, jusqu'à rencontrer un objet de type SEQEND ou tant que les objets sont de type ATTRIB pour récupérer tous les attributs ou en recherche un en particulier.

 

Comme tu peux le voir, Didier n'avais pas tort en disant que tu cherches peut-être à courir avant de savoir marcher, l’objectif que tu t'es donné demande déjà quelque, bonnes connaissances en LISP sachant que pour utiliser tout ça il faut aussi connaitre les instructions de base concernant les listes (d'association), les boucles while, etc.

 

Pour t'aider, je te propose une routine polyvalente qui requiert un nom d'entité (ENAME) comme argument et retourne une liste contenant une paire pointée par attribut, chaque paire étant du type : (TAG . valeur).

 

;; GetAttribs
;; Retourne une liste de paire pointées (TAG . Value) par attribut contenus dans le bloc
;;
;; Argument
;; ent : le nom d'entité (ENAME) de la référence de bloc

(defun GetAttribs (ent / elst lst)
 ;; Entité suivant celle passée en argument
 (setq ent (entnext ent))
 ;; Boucle tant que ent est de type ATTRIB
 (while (= "ATTRIB" (cdr (assoc 0 (setq elst (entget ent)))))
   ;; ajoute à la liste une paire pointée (TAG . valeur) et passe à l'entité suivante
   (setq lst (cons (cons (cdr (assoc 2 elst)) (cdr (assoc 1 elst))) lst)
  ent (entnext ent)
   )
 )
 ;; valeur de retour : la liste inversée
 (reverse lst)
)

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

coucou

 

on va s'y mettre à trois !!!

 

effectivement; il est primordial, vital, essentiel, non-négociable ...

de cibler ce qu'on veut faire,

être au moins capable de le verbaliser

l'ordi ne fera que ce qu'on lui dit de faire

 

je peux faire une routine qui travaille sur TOUS les blocs du dessin

et qui rajoute par exemple un préfixe à la valeur de l'attribut.

il faudra utiliser un "filtre de sélection" puis une boucle, tu connais ou pas ?

 

mais pour viser tel bloc et que tu ne veuilles pas le sélectionner à la souris ???

sauf à ce qu'il soit unique dans le fichier comme nous le disait VDH-Bruno, je sais pas faire.

 

je te l'ai demandé en MP, je te le re-demande en public

fais passer un fichier AVEC DES EXPLICATIONS

du style

j'ai ça avant la routine...

je veux ça après le traitement.

 

il faut reconnaître qu'on est conciliants, non ?

 

amicalement

 

 

Posté(e)

S'il n'y a qu'un seul bloc dans le dessin, utilise ssget avec l'option "_X" et un filtre avec le nom du bloc (regarde l'aide pour ssget ainsi que le lien vers les filtre en bas de page).

ssname avec l'indice 0 devrait te retourne le nom d'entité du bloc et la routine ci-dessus la valeur pour l'étiquette que tu veux.

 

Bon courage...

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Je tiens vraiment à vous remerciez.

 

J'ai enfin la solution, même si je ne la comprends pas !

j'ai regardé l’aide D’autocad sur le sujet, mais après ssget, je n’ai pas trouvé le sujet sur les filtres.

J’ai bien trouvé les codes de groupe pour SSGET X mais dans une doc de 1989 !, et j’ai pas d’explication sur (Cons 66 1 ).

Je trouvais l’ancienne doc d’autocad plus pratique !

 

Alors suivant la dernière idée de Gile j’ai (encore) recopié une partie du code du début, ou j’ai retrouvé ssget et ssname.

Je savais que la gestion des blocs était compliqué, mais pas à ce point la !

J’ai aussi trouvé mon erreur dans la gestion de la variable lst.

Bon merci encore pour votre aide.

Amicalement

 

(Defun C:NGF ()

(setq BN "NGFX") ; nom du bloc

(Setq

SS (SsGet "_X"

(List

(Cons 0 "INSERT")

(Cons 2 bn)

(Cons 66 1)

)

)

N (If SS (SsLength SS) 0)

)

 

;***********************

(setq n 0)

(repeat (sslength ss)

(setq na (ssname ss n)

lst (acet-insert-attrib-get (list na 1))

);setq

)

;**********************

(setq NGFref (nth 0 lst))

(setq NGFref (car (cdr NGFref)))

(setq NGFref (atof NGFref))

 

); fin defun

Posté(e)

Re,

 

J'ai enfin la solution

C’est le principal, c’est bien :) .

 

 

En reprenant le cheminement proposé par (gile) tu aurais également pu y arriver comme cela avec GetAttribs:

 

 (defun c:NGF ()
 (atof (cdar (GetAttribs (ssname (ssget "_X" '((2 . "NGFX"))) 0))))
)

 

 

Sinon je profite de l’occasion pour te conseiller d’archiver la réponse n°16 de (gile), cela te fera un excellent support sur les blocs. Je suis admiratif de la qualité et de la richesse de son intervention.

 

Bon courage pour la suite

A+

 

(Ps : Au passage (gile) si tu me lis je te remercie pour l’article sur les vecteurs déposé sur AcadLabs)

(Ps bis : Et merci à Didier d’être l’initiateur d’AcadLabs (site que je découvre), pour l’instant j’exploite ses ressources en espérant pouvoir l’enrichir un jour..).

 

Apprendre => Prendre => Rendre

Posté(e)

coucou

 

je te remercie, VDH-Bruno, de ces encouragements

je manque de temps étant expatrié depuis plus d'un an pour agrémenter le site

mais les interventions de 'gile) sont là pour pallier mes absences.

 

quant à ASTERIXII,

tu n'empruntes pas le bon chemin.

 

oublie DEFINITIVEMENT le copier-coller

ne serait-ce que pour sentir les erreurs que tu commets

par exemple des parenthèses manquantes ou autres joyeusetés.

il est ESSENTIEL de taper le code pour s'approprier le langage.

 

dans ton exemple tu choisis un bloc unique

alors pourquoi fais-tu une boucle ?

et pourquoi utilises-tu le acet-insert-attrib-get

 

le genre de truc qu'on ne tape jamais à la main

 

allez, bon courage à toi

 

amicalement

Posté(e)

Je ne peux qu'abonder dans le sens de Didier.

 

- Soit su tu veux apprendre et alors il faut te retrousser les manches, utiliser l'éditeur Visual LISP, faire des tests, des erreurs et refaire des tests jusqu'à comprendre tes erreurs. Si tu fais (quand même) des copier/coller, privilégie les routines (comme celles que j'ai donné ci-dessus) et décortique les (toujours dans l'éditeur) jusqu'à les comprendre et te les approprier. on apprend aussi beaucoup en lisant des codes écrits par d'autre à condition de les comprendre.

L'avantage des routines (fonctions LISP personnalisées) c'est qu'on peut les utiliser comme des fonctions LISP natives (si tant est qu'elles soient chargées) et se constituer ainsi une bibliothèque de nouvelles fonctions.

 

- Soit tu veux une solution toute faite, alors fais en la demande clairement :

"Dans mon dessin, je n'ai qu'un seul bloc nommé "NGFX" dont je veux récupérer la valeur de l'attribut dont l'étiquette est "NGFZ" sous forme de réel."

Et là, ceux qui savent pourront te répondre facilement ou ceux qui veulent apprendre trouveront un exercice qu'ils essayeront de résoudre.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Bonjour,

 

D'après ce que tu dis dans la réponse 15:

 

Je recherche une methode pour memoriser une valeur (NGF) dans mon dessin, pour qu'à la prochaine ouverture du plan, je la retrouve automatiquement, et sans passer par un fichier en ecriture.

C'est pour cette raison que j'ai pensé au bloc, mais il y à peut-être une autre solution ?

 

Je pense qu'il serait plus simple d'utiliser une variable système (USERI1-5, USERR1-5, PROJECTNAME) pour répondre à ce besoin.

Et le code pour récupérer la valeur serait également plus simple.

 

a+

_______________________________

R.A.

Développeur AutoCAD C#.net

www.danialu.fr

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !

Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant
×
×
  • Créer...

Information importante

Nous avons placé des cookies sur votre appareil pour aider à améliorer ce site. Vous pouvez choisir d’ajuster vos paramètres de cookie, sinon nous supposerons que vous êtes d’accord pour continuer. Politique de confidentialité