Aller au contenu

Lire la valeur d'un attribut de bloc


Messages recommandés

Posté(e)

Bonjour à tous

J'utilise depuis longtemps AutoCAD et je me lance dans le LISP quelques temps 😬.

Je trouve énormément d'aide sur ce forum et je profite de ma demande pour remercier tout le monde 😄.

Malheureusement là je me heurte à un problème que je ne comprend pas et je ne trouve pas la solution malgré toutes mes recherches.

 

Le but final de mon script est de changer le facteur de largeur des attribut donc la valeurs (le texte affiché) correspond au texte entré en argument du script.

J'arrive à changer le facteur de largeur d'attribut sans problème mais je suis incapable de récupérer la valeur de l'attribut...😶.

Quand j'utilise la fonction "vla-get-TextString" je lis la valeur par défaut et non la valeur actuelle.

Idem si j'utilise "vla-put-TextString", je modifie uniquement la valeur par défaut et non la valeur actuelle.

(defun test ($text / blocks bo eo ao)
	;;$text : Étiquette de l'attribut
	(vl-load-com)
	(setq blocks (vla-get-Blocks (vla-get-ActiveDocument (vlax-get-acad-object))))
	(vlax-for bo blocks
		(vlax-for eo bo
			(if (and(= (vla-get-ObjectName eo) "AcDbAttributeDefinition")
					(= (vla-get-TagString eo) $text)
					) ; end of and
				(progn
					;(vla-put-ScaleFactor eo 1)
					(princ "Étiquette : ")
					(princ (vla-get-tagString eo))
					(princ " - Valeur : ")
					(princ (vla-get-TextString eo))
					(terpri)
				)
			)
		)
	)
)

Auriez-vous une idée d'où pourrait venir l'erreur ???

Je vous remercie d'avance pour votre aide.

 

Posté(e)

Coucou,

Je ne maîtrise pas vraiment le Visual LISP mais je pense que cela vient du fait que tu utilises la définition de bloc, et non la référence de bloc.
Donc pour une définition de bloc tu ne peux accéder/modifier que les valeurs par défaut des attributs. Je suppose que ton but est de modifier les références et non les définitions donc pour cela tu dois faire un jeu de sélection (ou une sélection manuelle) avec tes blocs.
En LISP, tu as les fonctions (ssget) et (entsel) pour récupérer un jeu de sélection ou un nom d'entité. Je ne connais pas l'équivalent en Visual LISP s'il y en a un, donc il faut penser à faire une conversion (vlax-ename->vla-object) pour utiliser le bon type d'argument dans tes fonctions Visual LISP.

Bisous,
Luna

Posté(e)

Merci beaucoup @Luna pour ta réponse et l'explication.

Merci aussi pour la différence entre Visual LISP et LISP.
Je ne comprenais pas pourquoi certaines fonctions étaient écrites avec "vla" devant 🤦‍♂️.

Malheureusement le but de ce LISP est d'être utilisé dans un script SCR pour appliquer la modification dans un certains nombre de fichiers DWG.
Je ne peux donc pas utiliser la sélection manuelle (ou alors il faudra cliquer sur le bloc à chaque page 🤔).

Je pense que tout pourrait être géré en LISP mais je n'ai pas assez de connaissance pour le programmer pour le moment 😥.

Je vais continuer de creuser.

OrionLG

Posté(e)

Merci pour le conseil et pour l'accueil.
Je vais faire ça.

Le jeu de sélection me parle, je l'avais oublié.
😃Je vais refaire le script en LISP (et non VLISP) et repartir sur de bonnes bases

Cordialement

Posté(e)

@OrionLG, il n'y a pas besoin de ré-écrire en LISP ou Visual LISP, on peut mixer les deux et les deux sont des langages fonctionnels. La seule différence vient du fait que le Visual LISP est dérivé du Visual Basic donc la logique de programmation diffère étant donné que le Visual Basic est un langage de programmation orienté objet.

Pour que le script fonctionne correctement il faudra ouvrir les .dwg donc je pense que la fonction (ssget) peut marcher correctement avec l'option "_X" et un filtre sur les blocs. Petite question : tes blocs sont-ils dynamiques ? Si c'est le cas il faudra faire le tri des blocs en post-sélection sinon le tri se fera via la sélection.

Je te conseille de te familiariser avec le langage qui te semble le plus cohérent, donc si tu as appris via le Visual LISP autant continuer ainsi. Si tu as besoin d'aide, le forum est là, et les sites de formations AutoLISP sont très nombreux (comme te l'a proposé didier par exemple).
Il est fortement conseillé de commencer avec des programmes simples et de décortiquer les étapes complexes en une suite d'étapes simples. 🙂

Bisous,
Luna

  • 4 semaines après...
Posté(e)

Bonjour à tous.
Merci beaucoup @Luna pour ton retour.
Je ne l'avais pas vu 😥 car j'étais en arrêt quelques temps.
En fait je préfère le LISP. J'avais copié une routine en Visual LISP sans trop avoir saisir la différence.
Mais je préfère continuer en LISP (même si j'aime beaucoup le VB... mais pas pour le moment pour AutoCAD).

Je viens de finir mon script en LISP et il fonctionne...normalement.
Je me suis aidé de l'excellent script "REPSTRING" que nous utilisons très souvent.

Pour répondre à ta question, les blocs ne sont pas dynamiques.
J'ai en effet opté pour l'option "ssget", bien vu 👍.

Ci-joint le code. Ça pourra peu-être servir à d'autres.
Il faut encore que je l'optimise je pense mais il est fonctionnel

(defun ChangLargAttrib (string factor)
	(setq ss (ssget "X" (list (cons 0 "INSERT"))))
	; Si ss non nil
	(if ss									
		(progn
			(repeat (sslength ss)				; Répéter autant de fois que d'entités dans ss
				(setq ent (ssname ss 0))		; ent = nom de l'entité
				(setq en (entget ent))			; en = liste DXF de l'entité
				(setq etype (cdr (Assoc 0 en)))	; etype = Type d'entité (INSERT dans le cas présent)	*** À supprimer ***
						(if (assoc 66 en)		; Test si la variable 66 (Drapeau "entité suivent") est à 1
							(progn
								(setq textattrib (entnext ent))
								(while (= (cdr (assoc 0 (entget textattrib))) "attrib")	; test si entité est un attribut
									(setq suben (entget textattrib))			; suben = liste dxf de l'attribut
									(setq stg (cdr (assoc 1 suben)))	
									(if (= stg string)
										(progn
											(setq fact (cdr (assoc 41 suben)))
											(entmod (subst (cons 41 factor) (assoc 41 suben) suben))
										)
									)
									(setq textattrib (entnext textattrib))
								)
								(entupd ent)
							)
						)
				(ssdel ent ss)
			)
		)
	)
)


(defun c:ChLargAttrib ()
(SETQ STRING (GETSTRING T "\nTEXTE À REDIMENSIONNER : "))
(SETQ FACTOR (GETREAL "\nFACTEUR DE LARGEUR : "))
(ChangLargAttrib STRING FACTOR)
)

 

L'avantage est qu'on peut l'exécuter via un script .scr du genre :

OUVRIR
"chemin du fichier"
ChLargAttrib Texte_à_modifier
0.9 ; Nouveau facteur
_qsave
FERMER
OUVRIR
"chemin du fichier"
ChLargAttrib Texte_à_modifier
0.9 ; Nouveau facteur
_qsave
FERMER

Merci encore pour votre aide.

Amicalement
OrionLG

Posté(e)

Coucou,

il y a 9 minutes, OrionLG a dit :
(if (assoc 66 en)

Pour info tu n'as pas besoin de cette ligne si tu l'intègres directement dans ton filtre de sélection (cela permettra à ton programme d'aller plus vite également), comme ci-dessous :

(setq ss (ssget "_X" '((0 . "INSERT") (66 . 1))))

Tu peux même trier tes blocs en fonction de leur nom. Car actuellement tous tes blocs possédant des attributs sont modifiés mais si tu veux ne modifier que certaines définition de blocs, tu peux filtrer suivant le code DXF 2 comme suit :

(setq ss (ssget "_X" '((0 . "INSERT") (66 . 1) (2 . "NomBloc1,NomBloc2,NomBloc3"))))

Il faut savoir que les wild-card characters sont autorisés dans la liste des filtres de sélection autrement dit tu peux avoir un filtre comme ceci pour ton code DXF 2 :

(setq ss (ssget "_X" '((0 . "INSERT") (66 . 1) (2 . "*Bloc*"))))

Ici, tous les blocs dont leur nom contient la chaîne "Bloc" sont pris en compte. Si tu désires spécifier le nom via une variable, la fonction ' (= (quote)) ne fonctionne plus et il te faudra utiliser la fonction (list) et (cons) comme ceci :

(setq var1 "NomBloc1,TCPoint*,*Bloc*" ss (ssget "_X" (list '(0 . "INSERT") '(66 . 1) (cons 2 var1))))

Je te conseille également de déclarer tes variables localement pour ne pas être emmerdé plus tard ! Je te conseille le site de (gile) et didier concernant ce point pour mieux comprendre le fonctionnement et le pourquoi.

il y a 22 minutes, OrionLG a dit :
(defun c:ChLargAttrib ()

Bisous,
Luna

 

 

Posté(e)

Coucou 😃

Merci encore pour ton retour.

En effet, ça va plus vite en intégrant (66 . 1) dans le filtre 😄👍

Malheureusement le nom des blocs où il faut changer les facteurs de largeur ne sont pas toujours identiques.
Je les scanne donc tous. Mais ça va vite car on n'a jamais énormément d'entités.

Par contre je garde précieusement tes conseils pour un prochain script.
J'en ai un en cours où ils me seront utiles.

Concernant la déclaration des variables je vais creuser ça.
J'ai découvert la dernière fois le site de @didier.
Et j'ai depuis un moment à côté de moi en papier et sur mon PC l'excellent PDF "Introduction à AutoLISP" de @(gile) ainsi que ses scripts 😄.

OrionLG

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é