Aller au contenu

Messages recommandés

Posté(e)

Bonjour,

 

J'essaie d'agir dans les blocs et en meme temps apprendre le VLA.

 

Comme exercice je tente d'exploser tout les MTEXT's contenus dans les blocs

pour les transformer en texte simple.

 

je pensais pouvoir y arriver comme cela

 

 
(defun c:ExplodeMtextInBlocks (/ AcDoc bloc mt)
 (setq AcDoc (vla-get-ActiveDocument (vlax-get-acad-object)))
 (vlax-for bloc (vla-get-Blocks AcDoc)
   (vlax-for mt	bloc
     (if (= "AcDbMText" (vla-get-ObjectName mt))	  
(vl-cmdf "_explode" mt)
     )
   )
 )
 (vla-regen AcDoc acActiveViewport)
 (princ)
) 


 

mais, Horreur (pour la rime ;) )

j'obtient cette Erreur

 

; erreur: type de données incorrect ou dépassement de données: #

IAcadMText 00000000412b4188>

 

 

Posté(e)

Salut,

 

Il faut bien comprendre que Visual LISP (ou vla) est une technique pour accéder en LISP à l'environnement COM/ActiveX Automation.

Les 'objets' acquis dans cet environnement sont d'un type différent de ceux acquis avec AutoLISP, les premiers sont de type VLA-OBJECT, le seconds de type ENAME.

 

Quand tu parcours la collection de blocs avec vlax-for chaque objet (définition de bloc) est de type VLA-OBJECT. Puis quand tu parcours les composants de chaque blocs, toujours avec vlax-for, chaque entité est aussi de type VLA-OBJECT.

En faisant la même chose avec tblnext et entnext, on obtient les composant avec le type ENAME.

 

Il est possible de convertir le type de l'objet avec les fonctions vlax-vla-object->ename et vlax-ename->vla-object

 

Avec la fonction command les entités doivent être spécifiées sous la forme de ENAME (ou de jeu de sélection comme acquis avec ssget).

 

Il faut donc que tu fasses :

(if (= "AcDbMText" (vla-get-ObjectName mt))	  
 (vl-cmdf "_explode" (vlax-vla-object->ename mt))
)

 

Autre chose, quand tu fait (vlax-for bloc (vla-get-Blocks AcDoc) ...) tu parcours la collection des blocs 'au sens large', à savoir, espaces objet et papier compris qui sont aussi considérés comme des 'définitions de bloc'.

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

Posté(e)

Bonsoir,

 

Comme toi Fraid, je songe de plus en plus à m’intéresser à l’environnement COM/ActiveX Automation, au regard de certains codes que je vois circuler et qui me sont encore inaccessible (au passage j’en profite pour te remercier pour ton aide sur setenv & getenv).

 

Mais quant je lis la réponse de (gile), je me dis que je vais consolider un peu encore mes connaissance en Lisp, et en attendant collectionner les sujets comme celui-ci concernant ce thème car le palier ne me semble pas évident à franchir..

 

Cela va demander un gros investissement personnel et des heures de sommeil en moins.. (surtout que l’aide fr de la R14 ne contient pas ces chapitres), pour assimiler une philosophie qui me semble complètement différente de celle déjà entrevu..

 

Bon courage à toi

Apprendre => Prendre => Rendre

Posté(e)

Merci Bruno pour tes encouragements

 

J'ai décidé de consacrer plus de temps au développement

Jusqu'a maintenant c'etait trés sporadique (le temps de regonfler les roues de la charette)

Du coup j'oubliais trés vite :P

 

Ayant sous le nez beaucoup de code en VLA, il fallait bien que j'osasse le faire

:casstet:

 

Merci (gile) pour ces éclaircicement

Mais j'avais cherché avec vlax-vla-object->ename

que j'ai eu un mal de chien a trouvé dans l'aide

et j'obtient ce message d'erreur du meme genre

 

_explode  

 

Je commence a comprendre l'environement COM

Et le fait de travailler sur des collections entiere me motive.

Et surtout qu'ici on n'est est a bonne école ;)

Posté(e)

Et ce n'est pas la premiere fois que j'ai des problemes

a l'interieur des blocs

 

je n'arrive toujours pas a remplacer un simple texte...

 

que ce soit en Autolisp simple ou avec du VLA

 

je soupsonne une variable coquine dérriere cela...

Posté(e)

sa marche chez vous?

 

Non, la même erreur que toi...

 

Par contre j'ai modifié simplement la ligne suivante comme ceci (en mettant l'ename en liste), et là ça fonctionne.

 

(vl-cmdf "_.explode" (list (vlax-vla-object->ename mt)))

Choisissez un travail que vous aimez et vous n'aurez pas à travailler un seul jour de votre vie. - Confucius

Posté(e)

Toutes mes excuses, je n'avais pas testé dans une définition de bloc.

 

Comme la fonction vla-Explode n'est pas utilisable avec les textes multiligne, je te propose une petite entourloupe consistant à insérer le bloc contenant des mtextes en 0,0 et le décomposer. Puis, décomposer les mtextes résultant de la décomposition du bloc pour récupérer les textes simples et les copier dans la définition dans laquelle on supprime les mtextes.

 

(defun c:ExplodeMtextInBlocks (/ explodeNestedMtext hasMt)
 (vl-load-com)
 (or *acad* (setq *acad* (vlax-get-acad-object)))
 (or *acdoc* (setq *acdoc* (vla-getActiveDocument *acad*)))
 (or *blocks* (setq *blocks* (vla-get-Blocks *acdoc*)))

 ;; sous-routine locale
 (defun explodeNestedMtext (blk / name ref expl lst)
   (setq name (vla-get-Name blk))
   (vla-put-Explodable blk :vlax-true)
   ;; insérer le bloc en 0,0
   (setq
     ref (vla-InsertBlock
           (vla-get-ModelSpace *acdoc*)
           (vlax-3d-point '(0. 0. 0.))
           name
           1.
           1.
           1.
           0.
         )
   )
   ;; décomposer la référence
   (setq expl (vlax-invoke ref 'Explode))
   ;; pour chaque entité résultante, décomposer si c'est un mtext et ajouter le texte à lst
   (foreach o expl
     (if (= (vla-get-ObjectName o) "AcDbMText")
       (progn
         (vl-cmdf "_.explode" (vlax-vla-object->ename o))
         (setq txt  (vlax-ename->vla-object (entlast))
               expl (cons txt (vl-remove o expl))
               lst  (cons txt lst)
         )
       )
     )
   )
   ;; supprimer tous les mtextes de la définition
   (vlax-for o blk
     (if (= (vla-get-ObjectName o) "AcDbMText")
       (vla-delete o)
     )
   )
   ;; copier les textes dans la définition
   (vlax-invoke
     *acdoc*
     'CopyObjects
     lst
     (vla-Add *blocks* (vlax-3d-point '(0. 0. 0.)) name)
   )
   ;; supprimer la référence et les entités résultant de la décomposition
   (mapcar 'vla-Delete (cons ref expl))
 )

 ;; routine principale
 (vlax-for bloc *blocks*
   (if (= (vla-get-IsLayout bloc) :vlax-true)
     ;; traitement des mtextes dans les espaces objet et papier
     (vlax-for mt bloc
       (if (= "AcDbMText" (vla-get-ObjectName mt))
         (vl-cmdf "_.explode" (vlax-vla-object->ename mt))
       )
     )
     ;; traitement des mtextes dans les blocs
     (progn
       (setq hasMt nil)
       (vlax-for mt bloc
         (if (= "AcDbMText" (vla-get-ObjectName mt))
           (setq hasMt T)
         )
       )
       (if hasMt
         (explodeNestedMtext bloc)
       )
     )
   )
 )
 (princ)
)

 

EDIT : je n'avais pas vu la réponse de Bonuscad, beaucoup plus simple.

On dira que le code ci-dessus, peut servir d'exemple d'utilisation de vlax-invoke ... 'explode (récupération de la liste des objets résultants) et de vlax-invoke ... CopyObjects (deep cloning).

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

Posté(e)

Merci a tout les 2

 

Bonuscad

Je pensais que la variable mt était déjà une liste

En tout cas, si elle l'est, elle ne se présente pas de la bonne manière :exclam:

 

par contre cela ne fonctionne toujours pas

 

ERREUR d'application: Liste entité/point incorrecte.

Régénération du modèle.

 

(gile)

je ne m'attendais pas a devoir tourner du c_l pour réaliser une chose aussi "simple"

Trés formateur ton code!

J'aime beaucoup la partie qui colle un objet dans une définition de bloc ;)

En plus sa marche

Posté(e)

Premiere question

 

Pourquoi les variables servant à récupérer les collections (*acad*) sont elles globales et est ce obligatoire?

 

2)

 

Pourquoi la Fonction explodeNestedMtext est elle déclaré comme une variable locale?

 

Merci

 

PS: tu as oublié un tiré entre get et ActiveDocument ligne 4

Posté(e)

Pourquoi les variables servant à récupérer les collections (*acad*) sont elles globales et est ce obligatoire?

 

Ce n'est pas obligatoire, c'est juste une habitude. Chez moi, ces variables et quelques autres (*layers*, *utility*, ...) sont initialisées dans chaque nouveau document, ça permet d'écrire rapidement des expressions pour les tester. Il faut juste que je n'oublie pas d'ajouter ces initialisations quand je publie un code*.

L'avantage ne réside pas uniquement dans le fait qu'elles soient globales, mais aussi dans l'expression (or ...) qui évite d'évaluer la suivante et de créer une nouvelle instance de ces objets.

 

Pourquoi la Fonction explodeNestedMtext est elle déclaré comme une variable locale?

Là non plus, rien d'obligatoire, mais quand une fonction ne sert pas ailleurs que dans une la fonction qui l'appelle, la déclarer localement est un moyen d'éviter les conflits au cas où une autre définition de fonction aurait le même nom.

 

*C'est aussi pour ça que je ne me suis pas rendu compte de la faute dans "vla-getActiveDocument".

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

Posté(e)

par contre cela ne fonctionne toujours pas

 

Exact ! :(

 

L'explication de ma suggestion foireuse...

 

Je sais que explode attend une liste de la même forme que pourrait retourner (entsel) -> liste de ename et point de sélection.

 

Donc dans mon essai de déboguage j'avais essayé:

(vl-cmdf "_.explode" (list (vlax-vla-object->ename mt) (getpoint)))

J'ai donc sélectionné le Mtext durant le déroulement du code et cela à fonctionné. J'ai donc enlever le (getpoint) fais un U dans le dessin (certainement mon erreur, car la liste à du être conservé en mémoire), rechargé le code et retenté et cela à fonctionné.

 

En refaisant le test ce soir effectivement cela ne fonctionne pas.

 

Et là je me rend compte qu'il n'est pas évident d'obtenir un tel point sans sélection manuelle pour corriger ton code, pourtant la solution simple pour explode serait bien celle ci.

 

Désolé.

Choisissez un travail que vous aimez et vous n'aurez pas à travailler un seul jour de votre vie. - Confucius

Posté(e)

Et là je me rend compte qu'il n'est pas évident d'obtenir un tel point sans sélection manuelle pour corriger ton code, pourtant la solution simple pour explode serait bien celle ci.

 

D'un autre côté, je crains qu'on ne puisse invoquer les commandes (via command ou vl-cmdf) que dans l'éditeur (espace objet ou papier) et que ça ne soit pas possible à l'intérieur d'une définition de bloc.

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

Posté(e)

C'est ce que j'aime dans le lisp

C'est l'aventure

Jamais rien de certain

Toujours en expérimentation

 

Je me suis donc penché sur vlax-invoke

qui, soit dit en passant a l'air plutôt obsolète et remplacée par vlax-invoke-method

 

Y a t'il une liste des méthodes et leur arguments

car je n'ai rien trouvé dans l'aide.

 

Faut il pour cela parcourir les ressources dans Visual Studio?

Ou faire une sorte de dump? :casstet:

 

Si cela ce trouve c'est devant mon nez :P

Posté(e)

Je me suis donc penché sur vlax-invoke

qui, soit dit en passant a l'air plutôt obsolète et remplacée par vlax-invoke-method

 

vlax-invoke (comme vlax-get et vlax-put) n'est toujours pas encore obsolète et présente, à mon avis un avantage sur vlax-invoke-method (ou vla-*) c'est qu'il prend et/ou retourne des listes LISP au lieu de variants.

Voir ce sujet

 

Y a t'il une liste des méthodes et leur arguments

car je n'ai rien trouvé dans l'aide.

 

Les objets, propriétés et méthodes COM se trouvent dans la rubrique ActiveX and VBA Reference de l'aide aux développeurs jusqu'à la version 2010 (elle ont disparues de la calamiteuse aide 2011)*.

Il faut adapter la syntaxe VBA à Visual LISP, mais ce n'est pas bien difficile.

En général on ajoute vla- pour les méthodes et vla-get- ou vla-put- pour les propriétés et on passe en premier argument l'objet auquel s'applique la méthode ou la propriété (ou vlax-invoke(-method), vlax-get(-property), vlax-put(-property), puis l'objet, puis la méthode ou la propriété, puis les éventuels arguments).

Les fonction vlax-* sont renseignées dans AutoLISP Reference.

 

* Je me suis mis un raccourci sur mon bureau qui pointe vers le dossier d'aide de 2010 pour pouvoir l'utiliser avec 2011. Si tu n'as plus de versions d'AutoCAD antérieures à 2011, je peux t'envoyer ce dossier.

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

Posté(e)

je pensais bien que c'etait devant moi

 

je te remercie mais j'ai une collection d'aide assez bien fournie

 

c'est dans l'Autolisp reference de 2004

 

This function was known as vlax-invoke prior to AutoCAD 2000.

 

Je me sert de 2011 que depuis 1 semaine (je n'avais pas eu le temps de l'installer)

 

et c'est vrais que leur aide sur le net est LAMENTABLE

 

sinon j'utilise de moins en moins les raccourcis sur le bureau

 

J'utilise un logiciel d'arbres heuristiques Freemind

 

http://www.01net.com/telecharger/windows/Loisirs/education_et_scolarite/fiches/34923.html

 

qui permet d'accedé a tes documents tout aussi facilement

je le conseil, je le trouve terrible

cela permet de mettre a plat toute sorte de projet

et quand on a le cerveau qui coule par les oreilles, c'est bien pratique.

 

En tout cas je te remercie encore pour cette leçon

 

a bientot

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é