Aller au contenu

renvoyer la plus grande valeur d'un attribut d'une sélection de bloc


asptt9

Messages recommandés

Bonjour,

 

Je suis novice en lisp et j'essaye de comprendre tant bien que mal mais ça fait un moment que je me penche sur le sujet et là je suis bloqué. J'aurais donc besoin d'aide car j'ai vu qu'il y avait des maîtres dans l'art du lisp ici.

 

Voici mon problème:

 

J'ai défini une sélection de blocs qui ne sont pas forcément identiques (par exemple j'ai dans ma sélection 15 blocs "A" ,douze blocs "B" et 3 blocs "C")

Tous ces blocs possèdent leur premier attribut identique, à savoir l'étiquette NUMGEOREF.

J'aimerais savoir comment faire en lisp pour tester toutes les valeurs de ce premier attribut afficher la plus grande à l'écran.

 

J'espère que j'ai été assez clair parce que je ne vois pas trop comment l'expliquer autrement.

 

Merci par avance de votre aide.

Lien vers le commentaire
Partager sur d’autres sites

Bonjour asptt9,

 

Je suis loin d'être un maître, mais voici un petit bricalage qui devrait correspondre à ta demande.

(defun c:asptt9	(/ entbloc ent numgeoref n)
 (setq ss1 (ssget (list '(0 . "INSERT"))))
 (setq	n 0
numgeoref -1e99
 )
 (repeat (sslength ss1)
   (progn (setq entbloc (ssname ss1 n)
	 ent	 (entnext entbloc)
   )
   (while (/= (cdr (assoc 0 (entget ent))) "SEQEND")
     (if (and (= (cdr (assoc 0 (entget ent))) "ATTRIB")
	      (= (cdr (assoc 2 (entget ent))) "NUMGEOREF")
	 )
       (setq numgeoref (max numgeoref (read (cdr (assoc 1 (entget ent))))))
     )
     (setq ent (entnext ent))
   )
   (setq n (1+ n))
   )
 )
 (alert (rtos numgeoref))
 (princ)
)

Olivier

Lien vers le commentaire
Partager sur d’autres sites

Salut

 

Ma petite contribution

(defun c:maxat(/ doc ent lst sel)
 (setq doc (vla-get-activedocument (vlax-get-acad-object)))
 (vla-startundomark doc)
 (and (ssget (list (cons 0 "insert") (cons 66 1)))
   (progn
     (vlax-for ent (setq sel (vla-get-activeselectionset doc))
(setq lst (cons (vla-get-textstring (car (vlax-invoke ent 'getattributes))) lst))
     )
     (vla-delete sel)
     (alert (strcat "La valeur max est : " (car (vl-sort lst '>))))
   )
 )
 (vla-endundomark doc)
 (princ)
)

 

@+

Les Lisps de Patrick

Le but n'est pas toujours placé pour être atteint, mais pour servir de point de mire.

Joseph Joubert, 1754-1824

Lien vers le commentaire
Partager sur d’autres sites

Merci beaucoup -Olivier- et Patrick_35 pour vos réponses et aussi pour la rapidité dont vous avez fait preuve.

Le programme d'-Olivier- répond totalement à mes attentes. Par contre, j'ai fait un test sur ton lisp Patrick_35 et ton programme ne me renvoie pas la plus grande valeur de l'attribut à chaque fois. Peut-être que je n'ai pas été assez clair dans mon énoncé. Enfin toujours est-il que vous m'avez retiré une belle épine du pied et je vous en remercie.

Lien vers le commentaire
Partager sur d’autres sites

Merci beaucoup -Olivier- et Patrick_35 pour vos réponses et aussi pour la rapidité dont vous avez fait preuve.

Le programme d'-Olivier- répond totalement à mes attentes. Par contre, j'ai fait un test sur ton lisp Patrick_35 et ton programme ne me renvoie pas la plus grande valeur de l'attribut à chaque fois. Peut-être que je n'ai pas été assez clair dans mon énoncé. Enfin toujours est-il que vous m'avez retiré une belle épine du pied et je vous en remercie.

Le lisp fait un tri, si tu as par exemple 07 au lieu de 7, c'est le zéro qui prime (ex: 0 02 07 1 2 21 22 3 4).

L'avantage du lisp est qu'il fonctionne aussi sur de l'aphanumérique.

 

@+

Les Lisps de Patrick

Le but n'est pas toujours placé pour être atteint, mais pour servir de point de mire.

Joseph Joubert, 1754-1824

Lien vers le commentaire
Partager sur d’autres sites

Ah ok c'est donc pour ça, du coup ça ne m'arrange pas vu que j'ai que des nombres entier dans mon attribut.

Par contre je viens de rencontrer un problème avec le lisp d' -Olivier- qui ne se pose peut-être pas avec le tiens. J'ai l'impression que quand un attribut n'est pas renseigné parmi ma sélection le programme ne fonctionne pas étant donné qu'il n'y a pas de chiffre à l'intérieur. Peut-être pouvez vous me donner une petite piste pour que j'essaye de corriger ce problème tout seul.Je vais pas monopoliser tout votre temps...Merci par avance.

Lien vers le commentaire
Partager sur d’autres sites

Bonjour,

Effectivement en y repensant ce matin je me suis rendu compte que cela allait poser problème mais comme Patrick_35 avait fait sa propre réponse...

 

Pour t'aider je vais ajouter des commentaires :

 

 

(defun c:asptt9	(/ entbloc ent numgeoref n) ;lance la fonction asptt9
 (setq ss1 (ssget (list '(0 . "INSERT")))) ;créé une sélection des blocs et l'enregistre dans la variable ss1
 (setq	n 0 ;enregistre la valeur 0 dans la variable n
numgeoref -1e99 ;enregistre la valeur -1e99 dans la variable numgeoref
 )
 (repeat (sslength ss1) ;répète autant de fois qu'il y a de blocs dans la sélection
   (progn (setq entbloc (ssname ss1 n) ;enregistre le code de la nième entité de la sélection ss1 dans la variable entbloc
	 ent	 (entnext entbloc) ;passe le code de l'entité suivante dans la variable ent
	 ;les codes suivant correspondent aux objets imbriqués dans le bloc en question
   )
   (while (/= (cdr (assoc 0 (entget ent))) "SEQEND") ;répète jusqu'à l'objet sequend dernier objet d'un bloc
     (if ;si
       (and (= (cdr (assoc 0 (entget ent))) "ATTRIB") ; l'objet est et un attribut...
	      (= (cdr (assoc 2 (entget ent))) "NUMGEOREF"); et que son étiquette est numgeoref
	      ; ligne à ajouter pour vérifier que l'étiquette n'est pas vide (voir les codes dxf dans l'aide)
	 )
       (setq numgeoref (max numgeoref (read (cdr (assoc 1 (entget ent))))))
       ;enregistre la valeur la plus grande entre l'ancienne valeur de numgeoref et la nouvelle
     ); termine la boucle while
     (setq ent (entnext ent)) ; passe au bloc suivant
   )
   (setq n (1+ n)) ;ajoute 1 à n
   )
 )
 (alert (rtos numgeoref)) ; affiche la valeur
 ;il manque une condition pour vérifier que numgeoref n'est plus à sa valeur initiale (-1e99)
 (princ)
)

 

S'il tu as des questions...

Olivier

Lien vers le commentaire
Partager sur d’autres sites

Merci de m'avoir décrypté un peu ton programme ça m'aide à mieux comprendre.

Si je ne me trompe pas le code dxf pour la valeur d'un attribut de bloc est le 3.

J'ai donc rajouté une ligne au programme, ce qui donne:

 

(defun c:asptt9 (/ entbloc ent numgeoref n) ;lance la fonction asptt9

(setq ss1 (ssget (list '(0 . "INSERT")))) ;créé une sélection des blocs et l'enregistre dans la variable ss1

(setq n 0 ;enregistre la valeur 0 dans la variable n

numgeoref -1e99 ;enregistre la valeur -1e99 dans la variable numgeoref

)

(repeat (sslength ss1) ;répète autant de fois qu'il y a de blocs dans la sélection

(progn (setq entbloc (ssname ss1 n) ;enregistre le code de la nième entité de la sélection ss1 dans la variable entbloc

ent (entnext entbloc) ;passe le code de l'entité suivante dans la variable ent

;les codes suivant correspondent aux objets imbriqués dans le bloc en question

)

(while (/= (cdr (assoc 0 (entget ent))) "SEQEND") ;répète jusqu'à l'objet sequend dernier objet d'un bloc

(if ;si

(and (= (cdr (assoc 0 (entget ent))) "ATTRIB") ; l'objet est et un attribut...

(= (cdr (assoc 2 (entget ent))) "NUMGEOREF"); et que son étiquette est numgeoref

(/= (cdr (assoc 3 (entget ent))) nil); et que la valeur de l'attribut n'est pas vide

)

(setq numgeoref (max numgeoref (read (cdr (assoc 1 (entget ent))))))

;enregistre la valeur la plus grande entre l'ancienne valeur de numgeoref et la nouvelle

); termine la boucle while

(setq ent (entnext ent)) ; passe au bloc suivant

)

(setq n (1+ n)) ;ajoute 1 à n

)

)

(alert (rtos numgeoref)) ; affiche la valeur

;il manque une condition pour vérifier que numgeoref n'est plus à sa valeur initiale (-1e99)

(princ)

)

 

 

Le problème c'est que ça me renvoie toujours la valeur de numgeoref qu'on lui a donné au départ (-1exp99),je n'arrive pas à voir pourquoi.

Je pense que c'est pour cela qu'il faut rajouter la condition à la fin mais si cette condition n'est pas remplie ça ne m'affichera pas la valeur donc je suis un peu bloqué....please help

Lien vers le commentaire
Partager sur d’autres sites

Pour qu'il fonctionne qu'avec des entiers

(defun c:maxat(/ doc ent lst sel)
 (setq doc (vla-get-activedocument (vlax-get-acad-object)))
 (vla-startundomark doc)
 (and (ssget (list (cons 0 "insert") (cons 66 1)))
   (progn
     (vlax-for ent (setq sel (vla-get-activeselectionset doc))
       (setq lst (cons (atoi (vla-get-textstring (car (vlax-invoke ent 'getattributes)))) lst))
     )
     (vla-delete sel)
     (alert (strcat "La valeur max est : " (itoa (apply 'max lst))))
   )
 )
 (vla-endundomark doc)
 (princ)
)

 

Pour le lisp d'olivier, tu remplaces

(setq numgeoref (max numgeoref (read (cdr (assoc 1 (entget ent))))))

par

(if (> (atoi (cdr (assoc 1 (entget ent)))) numgeoref)
 (setq numgeoref (atoi (cdr (assoc 1 (entget ent)))))
)

 

ps : le lisp ne fonctionne qu'avec l'etiquette NUMGEOREF

 

@+

Les Lisps de Patrick

Le but n'est pas toujours placé pour être atteint, mais pour servir de point de mire.

Joseph Joubert, 1754-1824

Lien vers le commentaire
Partager sur d’autres sites

Si tu vérifie dans les codes dxf tu veras que le code 3 correspond au tranche de texte au delà de 250 caractères. Pour les textes simples, c'est le code 1 Valeur par défaut (chaîne). Le nombre 12 sous forme de chaîne s'écrit "12" un texte vide sera donc écrit "".

Comme tu l'a compris, il te restera a ajouter une condition à l'affichage de la valeur.

Du type : Si numgeoref = -1e99 alors pas de valeur valide trouvée sinon affichage de la valeur.

 

Olivier

PS : Grillé par Patrick ;)

Lien vers le commentaire
Partager sur d’autres sites

Merci beaucoup à tous les deux.

Vos deux lisp fonctionnent à merveille et me permette de gagner un temps énorme.

Je vais essayer de les analyser pour comprendre comment ils fonctionne...ça m'évitera peut-être de vous embêter la prochaine fois.

En tout cas un grand merci pour votre aide.

Lien vers le commentaire
Partager sur d’autres sites

Bonjour,

Désolé de vous re-déranger...

En fait j'aimerais que le programme inclus l'éventualité qu'il n'y ai aucun élément de présent dans le jeu de sélection et si c'est le cas mettre une variable à 1.

J'ai essayé avec

 

(if (= (length ss1) 0)

(progn

(setq numgeoref 0)

)

)

 

mais ça ne marche pas...

pourriez vous m'aider s'il vous plaît.

Lien vers le commentaire
Partager sur d’autres sites

Bonsoir,

- Pour connaître le nombre d'élément d'une sélection, il faut utiliser la fonction sslength et non length qui s'utilise pour une liste.

- Tu as mis ta condition à l'envers.

Je traduis :

Si le nombre d'éléments de la sélection est nul alors tu continu le programme sinon tu ne fait rien.

Il te faut donc inverser donc avec /=

On obtient donc (/= (sslength ss1) 0) ou plus simplement (/= ss1 nil).

Pour éviter le prog, tu peux mettre le if et sa condition avant le repeat.

- Enfin tu complèter le lisp en mettant une petite alerte du type "pas de blocs avec attribut dans la sélection" en tant que sinon.

 

Bon courage ;)

Olivier

Lien vers le commentaire
Partager sur d’autres sites

Bonjour à vous et merci encore.

En fait, au final j'ai utilisé ton programme -olivier- pour incrémenter la valeur de numgeoref au moment de l'insertion de mes blocs. Je l'ai donc utiliser comme sous programme et avec l'aide que vous avez pu m'apporter

ça a l'air de bien fonctionner. Voici le sous programme:

 

(defun derniernumero (/ entbloc ent numgeoref n)

(setq ss1 (ssget (list '(0 . "INSERT"))))

(setq n 0

numgeoref 0

)

(if (/= ss1 nil)

(progn

(repeat (sslength ss1)

(progn (setq entbloc (ssname ss1 n)

ent (entnext entbloc)

)

(while (/= (cdr (assoc 0 (entget ent))) "SEQEND")

(if ;si

(and (= (cdr (assoc 0 (entget ent))) "ATTRIB")

(= (cdr (assoc 2 (entget ent))) "NUMGEOREF")

(/= (cdr (assoc 1 (entget ent))) "")

)

(if (> (atoi (cdr (assoc 1 (entget ent)))) numgeoref)

(setq numgeoref (atoi (cdr (assoc 1 (entget ent)))))

)

 

)

(setq ent (entnext ent))

)

(setq n (1+ n))

)

)

)

(progn

(setq numgeoref 0)

)

)

 

(setq numgeoref2 (1+ numgeoref))

 

(setq ss1 nil)

 

(princ)

)

 

Ce programme ne me permet plus d'afficher la valeur du plus grand numgeoref mais me permet d'incrémenter directement à l'insertion de mon bloc. Si vous voyez des erreurs n'hésitez pas à m'en faire part même si au final je n'ai quasiment rien modifié au programme d'-Olivier-

 

Encore merci à vous.

Lien vers le commentaire
Partager sur d’autres sites

Peut-être y a t-il moyen de l'améliorer avec une temporisation au moment du choix de la sélection afin que je n'ai pas à intervenir même si elle est vide. Je m'explique : avant de lancer ce programme ma sélection est déjà faite donc le ssget détecte la sélection en cours et la valide. Mais quand je n'ai aucune sélection en cours, le ssget me donne la main pour faire ma sélection. Or si il n'y a aucun objet sélectionné avant c'est que je n'en veut aucun. Donc j'aimerais que le programme sache que quand aucun objet n'est sélectionné il valide la sélection vide au lieu de me donner la main pour choisir (ce qui m'oblige à intervenir manuellement pour valider la sélection vide).

 

Est-ce faisable?

Existe t-il des commande de temporisation pour dire par exemple si aucune sélection n'est faite au bout de 0.01 seconde valider valider la sélection vide?

 

Avez-vous une piste?

Lien vers le commentaire
Partager sur d’autres sites

Bonsoir,

 

A ma connaissance, il n'est pas possible d'intégrer de la temporisation en lisp, en revanche si tu veux que le programme tienne compte que des objets préselectionnés, regarde la fonction sssetfirst.

 

A tu regardé les différents programmes d'incrémentation de (gile). Encore merci à lui :)

Olivier

Lien vers le commentaire
Partager sur d’autres sites

Peut-être y a t-il moyen de l'améliorer avec une temporisation au moment du choix de la sélection afin que je n'ai pas à intervenir même si elle est vide. Je m'explique : avant de lancer ce programme ma sélection est déjà faite donc le ssget détecte la sélection en cours et la valide. Mais quand je n'ai aucune sélection en cours, le ssget me donne la main pour faire ma sélection. Or si il n'y a aucun objet sélectionné avant c'est que je n'en veut aucun. Donc j'aimerais que le programme sache que quand aucun objet n'est sélectionné il valide la sélection vide au lieu de me donner la main pour choisir (ce qui m'oblige à intervenir manuellement pour valider la sélection vide).

 

Est-ce faisable?

Existe t-il des commande de temporisation pour dire par exemple si aucune sélection n'est faite au bout de 0.01 seconde valider valider la sélection vide?

 

Avez-vous une piste?

 

Regarde la fonction ssgetfirst :

 

(if (setq ss (cadr (ssgetfirst))) ;_ récupérer la sélection courante
 (progn
   ;; faire ce qu'il y a faire avec la sélection active (variable ss)
 )
 (progn
   ;; faire ce qu'il y a à faire s'il ny a pas de sélection active
 )
)

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

Lien vers le commentaire
Partager sur d’autres sites

Bonjour,

 

Merci pour ce tuyau!

Grâce à votre aide j'ai réussi à créer mon premier lisp et surtout à comprendre son fonctionnement, ce qui est le plus important je pense. Au final le sous programme donne ceci:

 

(defun derniernumero (/ entbloc ent numgeoref n numgeoref2 ss)

(if (setq ss (cadr (ssgetfirst)))

(progn

(setq ss1 (ssget (list '(0 . "INSERT"))))

(setq n 0

numgeoref 0

)

(if (/= ss1 nil)

(progn

(repeat (sslength ss1)

(progn (setq entbloc (ssname ss1 n)

ent (entnext entbloc)

)

(while (/= (cdr (assoc 0 (entget ent))) "SEQEND")

(if

(and (= (cdr (assoc 0 (entget ent))) "ATTRIB")

(= (cdr (assoc 2 (entget ent))) "NUMGEOREF")

(/= (cdr (assoc 1 (entget ent))) "")

)

(if (> (atoi (cdr (assoc 1 (entget ent)))) numgeoref)

(setq numgeoref (atoi (cdr (assoc 1 (entget ent)))))

)

 

)

(setq ent (entnext ent))

)

(setq n (1+ n))

)

)

)

(progn

(setq numgeoref 0)

)

)

)

(progn

(setq numgeoref 0)

)

)

 

 

 

(setq numgeoref2 (1+ numgeoref))

 

(setq ss1 nil)

 

(princ)

)

 

Je vais maintenant essayer de le recréer par moi-même histoire de voir si je suis capable de le faire tout seul après toute vos explications.

 

Un grand merci à tous!

Lien vers le commentaire
Partager sur d’autres sites

Bonjour,

 

Au lieu de (ssgetfirst), tu peux aussi utiliser (ssget "_I"), qui retourne nil s'il n'y a aucune sélection active:

 

(defun derniernumero (/ ss n numgeoref ent entlist )
 (setq numgeoref 0)
 (if (setq ss (ssget "_I" '((0 . "INSERT")(66 . 1)) ) ) ; sélection des blocs avec attributs dans la sélection active (retourne nil si aucune sélection active)
   (progn
     (setq n 0)
     (repeat (sslength ss)
       (setq ent (entnext (ssname ss n)))
       (while (= (cdr (assoc 0 (setq entlist (entget ent)))) "ATTRIB") 
         (if (= (cdr (assoc 2 entlist)) "NUMGEOREF")
           (setq numgeoref (max numgeoref (atoi (cdr (assoc 1 entlist)))))
         )
         (setq ent (entnext ent))
       ) ; while
       (setq n (1+ n))
     ) ; repeat
   ) ; progn
 ) ; if ss
 (setq ss nil
       numgeoref (1+ numgeoref) ; valeur retournée par la fonction
 )
)

Lien vers le commentaire
Partager sur d’autres sites

Merci à tous pour vos réponses,

je pense avoir à peu près compris le fonctionnement de ce lisp.

Je vais essayer de le recréer par moi même afin d'apprendre un peu le fonctionnement de visual lisp mais ce n'est pas gagné.

Lien vers le commentaire
Partager sur d’autres sites

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é