Aller au contenu

[Résolu] Commande pour remplir les attributs d'un bloc à l'aide des données d'un ancien bloc.


Messages recommandés

Posté(e)

Coucou

 

je réponds au message #22

 

dans le message #11 le code contient un test :

(cond ((= att_etiq "Périmètre") (setq Perim (cdr (assoc 1 (entget ent_att))))))

qui doit bloquer car en changeant par

(cond ((= att_etiq "PERIMETRE") (setq Perim (cdr (assoc 1 (entget ent_att))))))

ça fonctionne, du moins sur ma machine...

 

amicalement

Posté(e)

didier,

 

Pour le bloc source "Info20", l'étiquette est "Périmètre".

Pour le bloc cible "Nom_Local_GHdC" l'étiquette est "PERIMETRE".

 

DenisHen,

 

En "Visual LISP", ça donnerait ça:

 

(defun c:COPATTRIB (/ source target aire perim)
 (vl-load-com)
 (if
   (and
     (setq source (car (entsel "\nSélectionnez le bloc source: ")))
     (= (vla-get-ObjectName (setq source (vlax-ename->vla-object source))) "AcDbBlockReference")
     (= (vla-get-EffectiveName source) "Info20")
     (setq target (car (entsel "\nSélectionnez le bloc cible: ")))
     (= (vla-get-ObjectName (setq target (vlax-ename->vla-object target))) "AcDbBlockReference")
     (= (vla-get-EffectiveName target) "Nom_Local_GHdC")
   )
    (progn
      (foreach att (vlax-invoke source 'GetAttributes)
        (if (= (vla-get-TagString att) "Aire")
          (setq aire (vla-get-TextString att))
        )
        (if (= (vla-get-TagString att) "Périmètre")
          (setq perim (vla-get-TextString att))
        )
      )
      (foreach att (vlax-invoke target 'GetAttributes)
        (if (= (vla-get-TagString att) "AIRE")
          (vla-put-TextString att aire)
        )
        (if (= (vla-get-TagString att) "PERIMETRE")
          (vla-put-TextString att perim)
        )
      )
    )
 )
 (princ)
)

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

Posté(e)

Coucou

 

Je pars du principe qu'on ne peut pas renseigner d'étiquette autrement qu'en majuscules, il est possible que je me trompe sur ce point et si c'est le cas merci de vos explications.

Partant de ce principe je ne comprends pas que DenisHen demande une comparaison de minuscules et accentuées qui plus est.

 

Je ne veux pas faire le tatillon à tous prix mais comme je n'aime pas diffuser de fausses informations si ce code (celui du message #11) fonctionne en l'état sur vos machines merci de me le dire, chez moi ça ne fonctionne pas tant que je n'ai pas modifié la casse dans la comparaison.

 

amiablement

Posté(e)

didier,

 

Je confirme, le code de la réponse #11 fonctionne (tout comme celui ci-dessus) à condition qu'on sélectionne bien le bloc "Info20" comme "ancien bloc" et le bloc "Nom_Local_GHdC" comme "nouveau bloc".

Le code la réponse #11 devrait effectivement vérifier la validité de l'entité sélectionnée à savoir une référence de bloc ainsi que le nom de ce bloc (ce que fait le code ci-dessus).

 

Si AutoCAD convertit automatiquement les étiquettes en majuscules, on arrive, notamment par programmation à avoir des attributs avec des étiquettes en minuscules accentuées (la preuve avec le bloc "Info20").

On notera que souvent, dans la recherche d'un attribut par étiquette on force les majuscules (avec strcase en LISP) avant la comparaison pour éviter ce genre de problème :

(= (strcase att_etiq) "PERIMETRE")

 

Par ailleurs, AutoCAD tolère aussi plusieurs attributs de même étiquette, ce qui, à mon avis, est beaucoup plus problématique...

 

 

Jbrosteaux,

 

Désolé d'avoir pollué ton sujet avec ces discussions techniques, mais cette discussion est loin d'être sans intérêt pour ceux qui apprennent ou se perfectionnent en LISP.

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

Posté(e)

Et bien c'est fort intéressant tout ce qui est dit!

Je ne considère pas que cela pollue le sujet!

Bien au contraire, ça soulève pleins de questions et de réponses.

 

Pour ma part, je n'ai pas de connaissance en programmations ... il faudrait que j’apprenne (rires forts) biggrin.gif

Vous donnez des cours? cool.gif

 

Au final, après toutes vos réflexions quel serait le bon LISP à écrire ????

 

Bonne journée

Posté(e)

Coucou

 

la seule chose que je ne faisais pas par rapport au message #11 était de ne pas chercher sur un bloc "Info20" comme "ancien bloc" et un bloc "Nom_Local_GHdC" comme "nouveau bloc".

les tests étaient faits avec "bloc1" et bloc2" dont j'avais tapé les étiquettes en minuscules accentuées aussitôt ré-écrites en majuscules sans accent par AutoCAD,

je faisais ces blocs non par programmation avec entmake mais depuis l'interface graphique

et en lançant le code il n'arrivait pas à faire la comparaison de chaîne et renvoyait nil

c'était ce test que je mettais en cause

 

il est vrai que vérifier avec STRCASE permet de se dédouaner de la saisie douteuse.

 

merci beaucoup (gile)

 

amicalement

Posté(e)

Il est vrai que dans l'espace graphique, la création d'étiquettes se fait en majuscule.

 

Mais dans la fenêtre de propriété, on peut les remplacer par des minuscule... Bug d'AutoCAD ?

 

En outre, je n'arrive pas à voir les caractères accentués mis en majuscule avec strcase, j'ai fais un petit tour dans la console :

_$ (strcase "périmètre")
"PERIMETRE"

Windows 11 / AutoCAD 2024

Sur terre, il y a 10 types de personnes, celles qui comptent en binaire et les autres (developpez.net).
Davantage d'avantages, avantagent davantage (Bobby Lapointe).
La connaissance s'accroît quand on la partage (Socrate).
Tant va la cruche à l'eau que l'habit n'amasse pas mousse avant de l'avoir tué. (Moi)

Posté(e)

Coucou

 

des fois j'ai du mal à te comprendre !!

 

que veux-tu dire par là : Mais dans la fenêtre de propriétés, on peut les remplacer par des minuscules.

moi je ne vois pas, merci de m'expliquer.

 

ensuite parlons de strcase

il est quelque peu NORMAL que les accents disparaissent car strcase transforme en majuscule

et comme ils n'ont pas les informations de l'académie française ils n'accentuent pas les majuscules***

 

donc si tu testes deux chaines, les deux en minuscules mais seulement l'une des deux accentuée et que tu passes les deux avec strcase

tu es certain de comparer quelque chose de comparable.

 

il est possible que (gile) vienne expliquer plus avant, en attendant je réponds et questionne DenisHen.

car j'ai refait le test avec le code du message#11 : ne fonctionne pas en l'état sur ma machine.

 

amicalement

 

***je suis partisan de les accentuer mais c'est un autre débat.

Posté(e)

Coucou

 

des fois j'ai du mal à te comprendre !!

 

que veux-tu dire par là : Mais dans la fenêtre de propriétés, on peut les remplacer par des minuscules.

moi je ne vois pas, merci de m'expliquer.

Si tu ouvres le bloc dans l'éditeur de bloc (_BEDIT) pour accéder à sa définition, tu peux sélectionner une définition d'attribut et renommer son étiquette dans la palette de propriétés avec des minuscules (ou des majuscules) accentuées.

 

ensuite parlons de strcase

il est quelque peu NORMAL que les accents disparaissent car strcase transforme en majuscule

et comme ils n'ont pas les informations de l'académie française ils n'accentuent pas les majuscules***

 

donc si tu testes deux chaines, les deux en minuscules mais seulement l'une des deux accentuée et que tu passes les deux avec strcase

tu es certain de comparer quelque chose de comparable.

C'est le comportement de la fonction AutoLISP strcase, mais je ne dirais pas que c'est NORMAL (mais plutôt qu'on a pu s'y habituer), car ça n'est pas vrai avec .NET par exemple :

("Périmètre").ToUpper();

retourne "PÉRIMÈTRE".

Et, curieusement en AutoLISP :

(strcase "PÉRIMÈTRE" T)

retourne "périmètre"...

Donc pourquoi le passage de minuscules en majuscules supprime les accents alors que l'inverse ne le fait pas ?

 

L'histoire de l'encodage des caractères est longue est complexe. Pour faire court et simple, au début, il n'y a qu'une norme : ASCII à 7 bits soit 128 caractères et aucune lettre accentuée.

Pour palier à ça, le codage est ensuite étendu à 8 bits (256 caractères) mais ça reste insuffisant pour coder toutes les lettres accentuées (pas seulement celles qu'on utilise français), on va donc multiplier les normes en fonctions des besoins qui diffèrent d'une langue à l'autre. Dans un premier temps toutes conservent les 128 premiers caractères mais diffèrent pour les caractères 128 à 255 suivant la norme (ANSI est une de ces norme).

Enfin, pour palier à la multiplication des normes on a créé le code Unicode dont les 256 premiers caractères sont ceux du code ANSI et les suivants pour les alphabets non latins et idéogrammes (voir ici).

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

Posté(e)

Salut,

 

Ci-dessous trois façons d'écrire ce LISP avec des techniques différentes.

Toutes trois fonctionnent chez moi et il serait étonnant que ce ne soit pas le cas ailleurs (excepté sur MAC où la technique "Visual LISP" ne peut pas fonctionner).

Toutes trois utilisent les noms d'étiquette tels que définis dans le bloc "Info20" (minuscules accentuées).

J'ai ajouté un contrôle de validité des blocs sélectionnés.

 

AutoLISP classique (entget, entnext, entmod)

(defun c:COPATTRIB (/ source target elst aire perim)
 (if
   (and
     (setq source (car (entsel "\nSélectionnez le bloc source: ")))
     (= (cdr (assoc 0 (setq elst (entget source)))) "INSERT")
     (= (cdr (assoc 2 elst)) "Info20")
     (setq target (car (entsel "\nSélectionnez le bloc cible: ")))
     (= (cdr (assoc 0 (setq elst (entget target)))) "INSERT")
     (= (cdr (assoc 2 elst)) "Nom_Local_GHdC" )
   )
    (progn
      (while
 (and
   (setq source (entnext source))
   (= (cdr (assoc 0 (setq elst (entget source)))) "ATTRIB")
 )
  (cond
    ((= (cdr (assoc 2 elst)) "Aire")
     (setq aire (cdr (assoc 1 elst)))
    )
    ((= (cdr (assoc 2 elst)) "Périmètre")
     (setq perim (cdr (assoc 1 elst)))
    )
  )
      )
      (while
 (and
   (setq target (entnext target))
   (= (cdr (assoc 0 (setq elst (entget target)))) "ATTRIB")
 )
  (cond
    ((= (cdr (assoc 2 elst)) "AIRE")
     (entmod (subst (cons 1 aire) (assoc 1 elst) elst))
    )
    ((= (cdr (assoc 2 elst)) "PERIMETRE")
     (entmod (subst (cons 1 perim) (assoc 1 elst) elst))
    )
  )
      )
    )
 )
 (princ)
)

 

Visual LISP (interface COM avec fonction vla-* et vlax-*)

(defun c:COPATTRIB (/ source target aire perim)
 (vl-load-com)
 (if
   (and
     (setq source (car (entsel "\nSélectionnez le bloc source: ")))
     (= (vla-get-ObjectName (setq source (vlax-ename->vla-object source))) "AcDbBlockReference")
     (= (vla-get-EffectiveName source) "Info20")
     (setq target (car (entsel "\nSélectionnez le bloc cible: ")))
     (= (vla-get-ObjectName (setq target (vlax-ename->vla-object target))) "AcDbBlockReference")
     (= (vla-get-EffectiveName target) "Nom_Local_GHdC")
   )
    (progn
      (foreach att (vlax-invoke source 'GetAttributes)
        (if (= (vla-get-TagString att) "Aire")
          (setq aire (vla-get-TextString att))
        )
        (if (= (vla-get-TagString att) "Périmètre")
          (setq perim (vla-get-TextString att))
        )
      )
      (foreach att (vlax-invoke target 'GetAttributes)
        (if (= (vla-get-TagString att) "AIRE")
          (vla-put-TextString att aire)
        )
        (if (= (vla-get-TagString att) "PERIMETRE")
          (vla-put-TextString att perim)
        )
      )
    )
 )
 (princ)
)

 

Fonction AutoLISP MAC (getpropertyvalue et setporpertyvalue)

(defun c:COPATTRIB (/ source target)
 (if
   (and
     (setq source (car (entsel "\nSélectionnez le bloc source: ")))
     (= (getpropertyvalue source "LocalizedName") "Référence de bloc")
     (= (getpropertyvalue (getpropertyvalue source "BlockTableRecord") "Name") "Info20")
     (setq target (car (entsel "\nSélectionnez le bloc cible: ")))
     (= (getpropertyvalue target "LocalizedName") "Référence de bloc")
     (= (getpropertyvalue (getpropertyvalue target "BlockTableRecord") "Name") "Nom_Local_GHdC")
   )
    (progn
      (setpropertyvalue target "AIRE" (getpropertyvalue source "Aire"))
      (setpropertyvalue target "PERIMETRE" (getpropertyvalue source "Périmètre"))
    )
 )
 (princ)
)

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

Posté(e)

Coucou

 

merci de ces explications

 

j'ai bien compris pour le coup des accents, je l'avais déjà remarqué d'ailleurs.

 

mais pour mettre une étiquette accentuée je n'arrive pas à reproduire

avec _bedit je mets des minuscules accentuées et ça passe

ensuite j'interroge avec AutoLisp j'obtiens quand même majuscules :

 

<Nom d'entité: 7fffdba48b0>
_$ (cdr(assoc 2 (entget (entnext ent))))
"PERIMETRE"
_$ 

 

j'ai MAP tu crois que ça change quelque chose ?

 

en même temps on a bien compris l'esprit des messages

j'arrête de dire que le message#11 ne fonctionne pas car je ne sais pas si c'est pas ma machine qui est en cause.

 

amicalement

Posté(e)

Bonjour à tous.

 

didier, je pense que le nom est plutôt "palette des propriétés" que "fenêtre des propriétés", on l'obtient en tapant "PROPRIETES", désolé pour cette confusion.

 

(gile), j'avais essayé de poser une option lors de la sélection du premier bloc "info20" qui aurait effacé cet ancien bloc, comme ça :

commande:Sélectionner l'ancien bloc [Option] : O

commande:Effacer l'ancien bloc <Oui/Non> :

. Comme je le fais souvent dans mes routines, j'efface ce qui ne me sert plus, ça a tendance à clarifie le dessin à mesure que l'on progresse dedans. Mais j'avoue avoir eu du mal et pas assez de temps...

 

Denis...

Windows 11 / AutoCAD 2024

Sur terre, il y a 10 types de personnes, celles qui comptent en binaire et les autres (developpez.net).
Davantage d'avantages, avantagent davantage (Bobby Lapointe).
La connaissance s'accroît quand on la partage (Socrate).
Tant va la cruche à l'eau que l'habit n'amasse pas mousse avant de l'avoir tué. (Moi)

Posté(e)

Coucou

 

je ne connais pas d'autres fenêtres de propriétés que celle que tu cites

(d'ailleurs il est plus facile de taper le raccourci Ctrl+1 pour l'appeler)

et c'est bien dans cette fenêtre que les étiquettes perdurent en majuscules (non accentuées)

alors que j'ai pourtant réussi par -bedit à en faire une en minuscules accentuées.

 

le sujet semble traîner en longueur mais j'aimerais quand même vérifier ou infirmer ce que je disais plus avant..

 

amicalement

 

edit :

oops ! je viens de voir qu'on parlait dans le forum 2016, je parle de MAP 2015

ne serait-ce pas la source de l'incompréhension ?

Posté(e)

Salut,

 

Avec juste un peu de logique et la syntaxe qui génèrera un affichage cohérent aussi bien en invite de commande qu'avec la saisie dynamique :

 

(initget "Oui Non")
(if (/= (getkword "\nEffacer l'ancien bloc [Oui/Non]? <Oui>: ") "Non")
 (alert "On efface !") ; remplacer par : (entdel ancienBloc)
 (alert "On n'efface pas !")
)

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

Posté(e)

Coucou

 

suite MàJ SP3 (crash windows) plus de possibilité de mettre des minuscules dans un ATTDEF via _BEDIT

par contre dans l'éditeur de bloc je peux changer dans la fenêtre de propriétés mais une fois enregistrement des modifications ça revient en majuscules.

de mieux en mieux ...

toujours MAP 2015.

 

amicalement

Posté(e)

Merci (gile) pour ton code, mais je comptais mettre ça en même temps que la sélection de l'ancien bloc.

 

Soit on sélectionne l'ancien bloc, soit on clique ou tape Option.

 

Comme si on avait :

commade:sélectionner l'ancien bloc ou [Option] :

Windows 11 / AutoCAD 2024

Sur terre, il y a 10 types de personnes, celles qui comptent en binaire et les autres (developpez.net).
Davantage d'avantages, avantagent davantage (Bobby Lapointe).
La connaissance s'accroît quand on la partage (Socrate).
Tant va la cruche à l'eau que l'habit n'amasse pas mousse avant de l'avoir tué. (Moi)

Posté(e)

Re...

 

Pffffff, j'ai cherché, j'ai cherché.. Mais rien de probant... J'ai fini par écrire un code "moyen"... Si quelques âmes charitables daignent bien me conseiller pour corriger ce petit code...:

(defun c:ChangAttribBlk (/ ValEnt Anc_bloc Nouv_bloc Aire Perim)
 (while (/= (type ent_bloc) 'LIST)
   (initget 1 "Option")
   (setq Anc_bloc (entsel "\nSélectionner l'ancien bloc ou [Option] : "))
   (cond ((= Anc_bloc "Option")
          (initget "Oui Non")
          (setq Rep (getkword
                      (strcat "\nEffacer l'ancien bloc [Oui/Non] ? <" (vlax-ldata-get "DenisH" "EffAncBlk" "Oui") ">: ")
                    ) ;_ Fin de getkword
          ) ;_ Fin de setq
          (if (= Rep "O")
            (vlax-ldata-put "DenisH" "EffAncBlk" "Oui")
            (vlax-ldata-put "DenisH" "EffAncBlk" "Non")
          ) ;_ Fin de if
         )
         (T
          (vl-catch-all-apply 'getpropertyvalue (list (car Anc_bloc) "Aire" Aire))
          (vl-catch-all-apply 'getpropertyvalue (list (car Anc_bloc) "Périmètre" Perim))
          (setq Nouv_bloc (car (entsel "\nSélectionnez le nouveau bloc : ")))
          (vl-catch-all-apply 'setpropertyvalue (list Nouv_bloc "AIRE" Aire))
          (vl-catch-all-apply 'setpropertyvalue (list Nouv_bloc "PERIMETRE" Perim))
          (if (= (vlax-ldata-get "DenisH" "EffAncBlk" "Oui") "Oui")
            (princ "\nEffacer l'ancien bloc")
            ;;(entdel Anc_bloc)
          ) ;_ Fin de if
         )
   ) ;_ Fin de cond
 ) ;_ Fin de while
 (princ)
) ;_ Fin de defun

 

Et, tout ce passe normalement... Ça ne fonctionne plus... :blink:

Windows 11 / AutoCAD 2024

Sur terre, il y a 10 types de personnes, celles qui comptent en binaire et les autres (developpez.net).
Davantage d'avantages, avantagent davantage (Bobby Lapointe).
La connaissance s'accroît quand on la partage (Socrate).
Tant va la cruche à l'eau que l'habit n'amasse pas mousse avant de l'avoir tué. (Moi)

Posté(e)
(initget "Oui Non")
(if (setq choix
   (getkword
     (strcat
       "\nEffacer l'ancien bloc [Oui/Non] ? <"
       (cond
	 ((vlax-ldata-get "DenisH" "EffAncBlk"))
	 ((vlax-ldata-put "DenisH" "EffAncBlk" "Oui")) ; <- initialisation au premier appel
       )
       ">: "
     )
   )
   )
 (vlax-ldata-put "DenisH" "EffAncBlk" choix)
 (setq choix (vlax-ldata-get "DenisH" "EffAncBlk"))
)

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

Posté(e)

Bonjour (gile), et merci de me guider...

 

Mais là, WOUAOUW... J'ai un peu de mal à comprendre l'intégration du cond dans le getword, je sais ce qu'il fait, mais je ne pourrais pas le réécrire dans un autre code... Trop d'imbrications :huh:

 

J'ai identifié mon problème, il était dans le (if (= Rep "O"), j'aurais dû écrire (if (= Rep "Oui")

 

Mais les attributs ne se copient pas et l'ancien bloc ne s’efface pas...

 

Mais ce n'est pas si grave que ça, puisque le sujet est résolu...

 

Encore merci...

Windows 11 / AutoCAD 2024

Sur terre, il y a 10 types de personnes, celles qui comptent en binaire et les autres (developpez.net).
Davantage d'avantages, avantagent davantage (Bobby Lapointe).
La connaissance s'accroît quand on la partage (Socrate).
Tant va la cruche à l'eau que l'habit n'amasse pas mousse avant de l'avoir tué. (Moi)

Invité
Répondre à ce sujet…

×   Collé en tant que texte enrichi.   Coller en tant que texte brut à la place

  Seulement 75 émoticônes maximum sont autorisées.

×   Votre lien a été automatiquement intégré.   Afficher plutôt comme un lien

×   Votre contenu précédent a été rétabli.   Vider l’éditeur

×   Vous ne pouvez pas directement coller des images. Envoyez-les depuis votre ordinateur ou insérez-les depuis une URL.

×
×
  • 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é