Annonces

Les forums de la communauté Autodesk ont un nouveau look. Pour en savoir plus sur ce qui a changé, consultez le tableau des annonces de la communauté.

AutoCAD Map : Lisp pour Rechercher/remplacer dans des données d'objets

Y.AUBRY
Advisor

AutoCAD Map : Lisp pour Rechercher/remplacer dans des données d'objets

Y.AUBRY
Advisor
Advisor

Bonjour,

 

Auriez-vous a disposition un lisp pour rechercher/remplacer des informations dans des données d'objets sous AutoCAD Map?

 

Par avance merci.

A+ Yoan

Yoan AUBRY

EESignature

0 J'aime
Répondre
Solutions acceptées (1)
812 Visites
14 Réponses
Replies (14)

_gile
Mentor
Mentor

Salut,

 

AutoCAD MAP possède de nombreuses fonctions LISP spécifiques dont plusieurs pour le gestion des données d'objet (ade_od*).

Personnellement je ne connais pas AutoCAD MAP mais @CADaSchtroumpf devrait certainement pouvoir t'en dire plus.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Y.AUBRY
Advisor
Advisor

Bonjour @_gile,

 

Je connaissais cette bibliothèque de référence des commandes AutoLISP pour Map mais malheureusement je n'ai pas assez de connaissances en la matière pour pouvoir développer une application complète en lisp.

 

Je cherchais surtout à savoir si quelque-chose existait déjà à ce niveau là.

Si ce n'est pas le cas, je me lancerais (dès que j'aurai un peu plus de temps) dans une application .NET traitant le sujet.

 

Merci tout de même pour ces informations.

 

Bonne journée et à bientôt.

A+ Yoan

Yoan AUBRY

EESignature

0 J'aime

O_Eckmann
Mentor
Mentor

Bonjour @Y.AUBRY ,

 

Depuis mon plug-in, il y a les fonction ODOUT pour exporter les données d'objets en fichier TXT tabulé que l'on peut modifier sous Excel, puis ODIN pour mettre à jour les données du DWG depuis le fichier TXT modifié.

Ce n'est pas direct, mais ça devrait faire le boulot.

 

Sinon tu as les outils d'Alexander : https://forums.autodesk.com/t5/autocad-map-3d-forum/additions-for-object-data/m-p/7548282 

 

Olivier

Olivier Eckmann

EESignature

Y.AUBRY
Advisor
Advisor

Bonjour @O_Eckmann ,

 

Oui, je sais, j'utilise tout les jours ton plugin qui marche à merveille... 

 

Pour explication, j'ai des codes chambres, poteaux (etc...) que je récupère sur SIG en ligne (de mon client).

 

Cependant, certaines chambres (...) n'ont pas forcément été créées dans leur base SIG donc j'affecte un code temporaire.

Le problème c'est que dans chaque infrastructure d'accueil, câble, etc... ce code chambre de départ ou d'arrivée est présent. Donc lorsque mon client me redonne le bon nommage, je dois mettre à jour ce champ dans l'ensemble des tables... Ce qui ce fait, mais de manière un peu fastidieuse...

 

Je cherchais donc à savoir s'il était possible de faire un rechercher remplacer dans toutes les tables d'un seul coup.

 

A+ Yoan

Yoan AUBRY

EESignature

0 J'aime

CADaSchtroumpf
Advisor
Advisor

@Y.AUBRY  a écrit :

Bonjour @O_Eckmann ,

 

Oui, je sais, j'utilise tout les jours ton plugin qui marche à merveille... 

 

Pour explication, j'ai des codes chambres, poteaux (etc...) que je récupère sur SIG en ligne (de mon client).

 

Cependant, certaines chambres (...) n'ont pas forcément été créées dans leur base SIG donc j'affecte un code temporaire.

Le problème c'est que dans chaque infrastructure d'accueil, câble, etc... ce code chambre de départ ou d'arrivée est présent. Donc lorsque mon client me redonne le bon nommage, je dois mettre à jour ce champ dans l'ensemble des tables... Ce qui ce fait, mais de manière un peu fastidieuse...

 

Je cherchais donc à savoir s'il était possible de faire un rechercher remplacer dans toutes les tables d'un seul coup.

 

A+ Yoan


Je suis pas sur d'avoir tout compris la problématique.

Si tu as un code temporaire, il me semble que la fonction MQSELECT d'Olivier te permet de trouver/sélectionner tout les objets concernés par ce code. Dès lors dans le panneau de propriétés, tu peux leur affecter la nouvelle valeur.

Mais un extrait du DWG de ce que tu possède et de ce que tu récupère de ton client aiderais à comprendre ce que tu veux faire.

0 J'aime

Y.AUBRY
Advisor
Advisor

Bonjour @CADaSchtroumpf ,

 

Ci-joint un lien pour télécharger un fichier exemple : https://we.tl/t-06ElLDNxjK

 

Chaque bloc dynamique PA a un pa_codeext associé qui est généré lors de la migration des informations du funiculaire vers le bloc PA (code vb.net généré en interne).

Dans l'exemple ci-dessous le pa_codeext 22147/10010 est récupéré depuis l'information "CHB_22147_22_010" et du propriétaire du point d'accueil "MEGALIS" = 1 

YAUBRY_1-1661937556243.png

 

On retrouve ce code dans les données d'objets tr_pacoex1 (ou tr_pacoex2) des polylignes représentant les tranchées

Dans le cas ci-dessous la polyligne concernée part du bloc PA ayant pour pa_codeext 22147/10010 et à plusieurs destinations possibles 22147/10042 , 22147/31326 et 22147/32448 car c'est une tranchée commune

 

YAUBRY_2-1661937732877.png

 

En utilisant l'outil MQSELECT paramétré de la sorte

YAUBRY_3-1661938157539.png

 

j'obtiens bien une sélection

YAUBRY_4-1661938211099.png

mais les valeurs n'étant pas toujours les même je ne peux pas modifier directement mes valeurs...

 

L'utilisation de OD Out puis OD In par contre me permet de faire ce rechercher remplacer dans Excel.

 

Cependant je cherchais un moyen de pouvoir le faire directement dans AutoCAD :

Le but étant que ma valeur soit recherchée puis modifiée dans le champ pa_codeext de la table t_pontaccueil du bloc dynamique PA et dans l'ensemble champs tr_pacoex1 et tr_pacoex2 de la table t_tranchee des polylignes. (dans cet exemple)

 

A+ Yoan

Yoan AUBRY

EESignature

0 J'aime

CADaSchtroumpf
Advisor
Advisor
Solution acceptée

Bon a essayer d'abord en test voir si cela fait le job car j'ai monté le code assez rapidement...

Pour améliorer la rapidité je te conseille de filtrer les objets intéressés avant d'utiliser la routine.

Exemple Qselect en créant une nouvelle sélection des polylignes sur le calque "TRANCHEE"

Relancer Qselect en ajoutant la sélection les blocs sur le calque "POINT_ACCUEIL"

Lancer la routine, choisir les tables sur lesquelles tu veux faire une recherche (Ctrl+Click pour en prendre plusieurs)

Choisir les champs concernés (seul les champ de type caractère seront listé) idem que ci-dessus (Ctrl+Click)

Donner la chaine originelle puis la chaine de remplacement

 

; str2lst
;; Transforme un chaine avec séparateur en liste de chaines
;;
;; Arguments
;; str : la chaine à transformer en liste
;; sep : le séparateur
;;
;; Exemples
;; (str2lst "a b c" " ") -> ("a" "b" "c")
;; (str2lst "1,2,3" ",") -> ("1" "2" "3")
(defun str2lst (str sep / pos)
  (if (setq pos (vl-string-search sep str))
    (cons
      (substr str 1 pos)
      (str2lst (substr str (+ (strlen sep) pos 1)) sep)
    )
    (list str)
  )
)
;; ListBox (gile)
;; Boite de dialogue permettant un ou plusieurs choix dans une liste
;;
;; Arguments
;; title : le titre de la boite de dialogue (chaîne)
;; msg ; message (chaîne), "" ou nil pour aucun
;; keylab : une liste d'association du type ((key1 . label1) (key2 . label2) ...)
;; flag : 0 = liste déroulante
;; 1 = liste choix unique
;; 2 = liste choix multipes
;;
;; Retour : la clé de l'option (flag = 0 ou 1) ou la liste des clés des options (flag = 2)
;;
;; Exemple d'utilisation
;; (listbox "Présentation" "Choisir une présentation" (mapcar 'cons (layoutlist) (layoutlist)) 1)
(defun ListBox (title msg keylab flag / tmp file dcl_id choice)
  (setq
    tmp (vl-filename-mktemp "tmp.dcl")
    file (open tmp "w")
  )
  (write-line
    (strcat "ListBox:dialog{label=\"" title "\";")
    file
  )
  (if (and msg (/= msg ""))
    (write-line (strcat ":text{label=\"" msg "\";}") file)
  )
  (write-line
    (cond
      ((= 0 flag) "spacer;:popup_list{key=\"lst\";")
      ((= 1 flag) "spacer;:list_box{key=\"lst\";")
      (T "spacer;:list_box{key=\"lst\";multiple_select=true;")
    )
    file
  )
  (write-line "}spacer;ok_cancel;}" file)
  (close file)
  (setq dcl_id (load_dialog tmp))
  (if (not (new_dialog "ListBox" dcl_id))
    (exit)
  )
  (start_list "lst")
  (mapcar 'add_list (mapcar 'cdr keylab))
  (end_list)
  (action_tile
    "accept"
    "(or (= (get_tile \"lst\") \"\")
      (if (= 2 flag)
        (progn
          (foreach n (str2lst (get_tile \"lst\") \" \")
            (setq choice (cons (nth (atoi n) (mapcar 'car keylab)) choice))
          )
          (setq choice (reverse choice))
        )
        (setq choice (nth (atoi (get_tile \"lst\")) (mapcar 'car keylab)))
      )
    )
    (done_dialog)"
  )
  (start_dialog)
  (unload_dialog dcl_id)
  (vl-file-delete tmp)
  choice
)
(defun c:change_string_IN_OD ( / sel_tbl def_tbl l_field lsel_field str_ori str_new js n ent)
  (setq sel_tbl (listbox "Donnée d'objet" "Choisir les tables de données d'objet où faire une recherche" (mapcar 'cons (ade_odtablelist) (ade_odtablelist)) 2))
  (cond
    (sel_tbl
      (foreach e sel_tbl
        (setq
          def_tbl (ade_odtabledefn e)
          field (mapcar 'cdr (mapcar '(lambda (x) (assoc "ColName" x)) (cdaddr def_tbl)))
        )
        (mapcar
          '(lambda (x)
            (if (eq (cdr (assoc "ColType" (assoc (cons "ColName" x) (cdaddr def_tbl)))) "Character")
              (setq l_field (cons x l_field))
            )
          )
          field
        )
      )
      (setq lsel_field (listbox "Champ de donnée" "Choisir les champs de donnée où effectuer la recherche" (mapcar 'cons l_field l_field) 2))
      (cond
        (lsel_field
          (setq
            str_ori (getstring "\nChaine de caractères à remplacer?:" )
            str_new (getstring "\nNouvelle chaine de caractères de remplacement?:" )
          )
          (setq js (ssget));(ssget "_X")
          (cond
            (js
              (repeat (setq n (sslength js))
                (setq ent (ssname js (setq n (1- n))))
                (foreach i sel_tbl
                  (foreach j lsel_field
                    (if
                      (and
                        (member i (ade_odgettables ent))
                        (member j (mapcar 'cdr (mapcar '(lambda (x) (assoc "ColName" x)) (cdaddr (ade_odtabledefn i)))))
                      )
                      (if (wcmatch (ade_odgetfield ent i j 0) (strcat "*" str_ori "*"))
                        (ade_odsetfield ent i j 0 (vl-string-subst str_new str_ori (ade_odgetfield ent i j 0)))
                      )
                    )
                  )
                )
              )
            )
          )
        )
      )
    )
  )
  (prin1)
)

 

Y.AUBRY
Advisor
Advisor

@CADaSchtroumpf ,

 

Tout d'abord un grand merci d'avoir pris le temps de faire une routine spécialement pour moi.

Je regarderai ça dès demain matin à tête reposée...

 

Bonne soirée

Yoan

Yoan AUBRY

EESignature

0 J'aime

Y.AUBRY
Advisor
Advisor

Bonjour @CADaSchtroumpf ,

 

Un grand merci, ca marche très bien et va me permettre de gagner beaucoup de temps en cas de reprise.

 

Petite question subsidiaire (sans trop d'intérêt) : Y a-t-il un moyen d'utiliser un autre jeu de caractère (UTF-8, Windows-1252/WinLatin 1) dans les lisps (ou à charger ailleurs?) pour que les caractères spéciaux (accents, etc...) soient pris en compte lors de l'affichage?

YAUBRY_0-1662013256522.png

 

A+ Yoan

Yoan AUBRY

EESignature

0 J'aime

CADaSchtroumpf
Advisor
Advisor

Ravi que ça fonctionne correctement.

Mais je tiens à préciser que la chaîne à rechercher doit être assez conséquente/distincte, en effet une chaîne de longueur trop courte et pas assez significative pourrait effectuer des changements non voulus dans les champs.

Donc à utiliser avec précaution...

0 J'aime

CADaSchtroumpf
Advisor
Advisor

@Y.AUBRY  a écrit :

Bonjour @CADaSchtroumpf ,

 

Un grand merci, ca marche très bien et va me permettre de gagner beaucoup de temps en cas de reprise.

 

Petite question subsidiaire (sans trop d'intérêt) : Y a-t-il un moyen d'utiliser un autre jeu de caractère (UTF-8, Windows-1252/WinLatin 1) dans les lisps (ou à charger ailleurs?) pour que les caractères spéciaux (accents, etc...) soient pris en compte lors de l'affichage?

YAUBRY_0-1662013256522.png

 

A+ Yoan


Généralement quand je fais un copier-coller depuis un forum d'un code lisp dans le bloc note (j'utilise Notepad2), je met le codage en ANSI et non UFT-8 et je n'ai pas de problème avec l'accentuation.

braudpat
Mentor
Mentor

Hello @CADaSchtroumpf 

 

Superbe routine sur les ODs comme d'habitude ... Merci !

 

RAPPEL: seule la 1ère occurence de la chaine trouvee est remplacée ce qui me convient bien !

 

Bon WE, La Sante, Bye, Patrice

 

Patrice ( Supporting Troops ) - Autodesk Expert Elite
If you are happy with my answer please mark "Accept as Solution" and if very happy please give me a Kudos (Felicitations) - Thanks

Patrice BRAUD

EESignature


0 J'aime

Y.AUBRY
Advisor
Advisor

Bonjour, 

 

Par rapport à l'encodage ANSI au lieu d'UTF-8.

 

Personnellement j'utilise Notepad++.

 

La solution pour passer en ANSI par défaut sur NotePad++ est la suivante.

 

Onglets "Paramètres", "Préférences", "Nouveau document"

YAUBRY_0-1662358483329.png

et modifier l'encodage par défaut en ANSI (et j'en ai profité pour basculer le langage par défaut en "Visual Basic" car c'est celui que j'utilise le plus)

YAUBRY_1-1662358632306.png

 

A+ Yoan

 

Yoan AUBRY

EESignature

braudpat
Mentor
Mentor

Hello @Y.AUBRY 

 

Merci pour ce rappel important Mr Yoan ++

 

Au fait sur ce Sujet , j ai essaye de rassembler les Routines Lisp vitales pour les ODs (Object Data) de ACAD MAP et ACAD CIVIL :

https://georezo.net/forum/viewtopic.php?id=44248

 

Bonne semaine, La Sante, Bye, Patrice

Patrice ( Supporting Troops ) - Autodesk Expert Elite
If you are happy with my answer please mark "Accept as Solution" and if very happy please give me a Kudos (Felicitations) - Thanks

Patrice BRAUD

EESignature


0 J'aime