Aller au contenu

Organiser les archives


Messages recommandés

Posté(e)

Bonjour

 

Voila, j'ai un petit besoin qui sera, je l'espère, un bon défis pour les programmeurs sous Autocad

 

Je dispose de plusieurs milliers de dessin autocad (archives de plusieurs années de travaux topographiques) classés pas dossiers numéroté et je souhaite avoir un idée d'ensemble sur leurs emplacement respectifs

Je cherche donc une macro (vba de préférence) qui puisse scanner les répertoires (et sous-répertoire) de se renseigner sur le contenu des fichiers DWG et d'y récupérer les coordonnées du point central

Un ficher texte sera généré qui comportera un tableau dans lequel se trouvera le nom du dossier, les différents fichiers DWG (s'il en existe plusieurs); les coordonnées du centre de chaque dessin

 

J'espère que je me suis bien expliqué et que la tache aura intéressé le plus de monde

Posté(e)

En fait j'ai juste besoin de savoir la situation approximative du dessin

Si tu veux, je propose de faire le zoom à l'étendu et d'extraire les coordonnées du point central de l'écran... ce n'est qu'une proposition mais les coordonnées de n"importe quel objet du dessin me suffiront dans la plupart des cas

Posté(e)

@ Christian

 

Bon début! :)

Est-ce qu'il est nécessaire d'ouvrir le dessin pour pourvoir utiliser ces deux variables?

je rappelle qu'il s'agit de plusieurs milliers de fichiers :casstet:

Posté(e)

Dans la mesure où les dessins n'ont pas forcément été enregistrés en zoom étendu et dans le SCG, ça me paraît indispensable d'ouvrir chaque dessin et d'effectuer ces opérations avant de récupérer la valeur des variables mentionnées par rebcao.

 

C'est faisable en script + lisp, mais ça moulinerait probablement quelques heures...

 

Peut-être qu'en VB ou autre langage il serait possible d'effectuer ces tâche un peu plus rapidement dans une instance AutoCAD "invisible", mais je ne m'y connais pas assez dans ces langages pour l'affirmer.

Posté(e)

Salut,

 

Il est possible d'utiliser l'ActiveX ObectDBX en Visual LISP ou VBA ou la méthode Database.ReadDwgFile en .NET pour accéder à la base de donnée d'un dessin fermé, mais ces méthodes ne permettent pas d'accéder à l'éditeur d'AutoCAD donc de lancer des commandes ou d'interroger des variables système.

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

Posté(e)

Merci de l'info (gile) :)

 

Donc a priori pas le choix, il faut ouvrir chaque dessin...

 

Je pense que si j'étais dans ton cas je passerais par un simple script, qui exécuterait pour chaque dessin à traiter les actions suivantes :

- ouvrir le dessin

- zoom étendu

- passer dans le SCG

- lancer un petit lisp qui aurait pour mission de lire un certains nombre de variables (dwgprefix, dwgname, viewctr, viewsize et/ou extmin - extmax, ...) et d'aller les écrire dans un fichier texte donné

- fermer le dessin.

Posté(e)

Re,

 

Il est possible de faire quelque chose sans utiliser les variables système.

 

Je donne une procédure envisageable en VBA (puisque cela semble être le souhait malgré le choix du forum).

 

- Créer un fichier texte ouvert en écriture.

- Créer une instance d'ObjectDBX.AxDbDocument.

- Ouvrir chaque fichier avec cette instance.

- Parcourir l'espace objet du dessin.

- Affecter les valeurs des points MinPoint et MaxPoint de l'emprise de la première entité (méthode GetBoundingBox) à deux variables.

- Pour chaque entité suivante exécuter GetBoundingBox et modifier les valeurs des deux variables si les coordonnées retournées par GetBoundingBox sont inférieures ou supérieures à celles des variables.

- Quand tout l'espace objet aura été scanné, les valeurs des variables seront égales à celles des variables système EXTMIN et EXTMAX, faire la moyenne de ces deux point et l'écrire dans le fichier texte.

- Quand tous les DWG auront été traités, supprimer l'instance d'ObjectDBX et libérer les ressources.

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

Posté(e)

Merci les gars pour toutes vos suggestions

J'aurai préféré une solution toute prête mais bon, je vois qu'il faut mettre la main dans la pâte :D

Je vais donc essayer de faire un peu de programmation lisp ou vba (que je maitrise mieux) peu importe si ça devra tourner toute la nuit, l'essentiel est d'avoir un résultat correct

J'espère que j'aurai un peu de temps d'ici là je vous mettrai au courant si ça marche

Posté(e)

Je te propose un LISP qui devrait faire ce que tu veux.

 

Attention, même si ça devrait être beaucoup plus rapide qu'avec un script, le traitement risque de prendre un peu de temps si tu as beaucoup de fichiers.

 

Mode d'emploi :

- charger les routines dans un dessin vierge (seuls les fichier fermés seront traités)

- lancer la commande ARCHIVE

- spécifier le nom du fichier .csv de sortie (lisible avec Excel ou OpenOffice ou le bloc-note).

- choisir le répertoire racine des répertoires à traiter.

 

Le nom de chaque fichier en cours de traitement s'affiche sur la ligne commande.

 

Essaye d'abord avec un dossier qui ne contient pas trop de fichiers et sous dossiers.

 

;; DirBox (Patrick_35)
;; retourne le chemin complet du dossier spécifé
;;
;; Arguments
;; Message : le méssage à afficher dans la boite de dialogue
;; Chemin : le chemin du répertoire source
;; Drapeau : la somme des codes binaires suivants
;;
;; Valeur du Drapeau
;; 0 = Valeur par défaut
;; 1 = BIF_RETURNONLYFSDIRS = Seulement les fichiers système
;; 2 = BIF_DONTGOBELOWDOMAIN = Interdit d'explorer en dehors du domaine
;; 4 = BIF_STATUSTEXT = Inclure un secteur de statut. La fonction de rappel de service peut placer le texte de statut en envoyant des messages à la zone de dialogue. Ce drapeau n'est pas soutenu quand BIF_NEWDIALOGSTYLE est indiqué.
;; 8 = BIF_RETURNFSANCESTORS = Seulement les sous Dossiers
;; 16 = BIF_EDITBOX = Inclure une commande d'édition dans la zone de dialogue
;; 32 = BIF_VALIDATE = Verifie si l'utilisateur dactylographie un nom inadmissible dans la boîte d'édition
;; 512 = BIF_NONEWFOLDERBUTTON = Ne pas inclure le bouton Créer un nouveau dossier
;; 4096 = BIF_BROWSEFORCOMPUTER = Autorise à parcourir le réseau
;; 8192 = BIF_BROWSEFORPRINTER = Seulement le choix d'une imprimante
;; 16384 = BIF_BROWSEINCLUDEFILES = Montre tout
;; = BIF_BROWSEINCLUDEURLS = Montrer les raccourcis, Les drapeaux BIF_USENEWUI et de BIF_BROWSEINCLUDEFILES doivent également être placés
;; = BIF_NEWDIALOGSTYLE = Employer la nouvelle interface utilisateur
;; = BIF_NOTRANSLATETARGETS = Quand l'article choisi est un raccourci, renvoyer le PIDL du raccourci lui-même plutôt que sa cible.
;; = BIF_SHAREABLE = Peut montrer les ressources en commun sur les systèmes à distance. Le drapeau de BIF_NEWDIALOGSTYLE doit également être placé.
;; = BIF_UAHINT = Une fois combiné avec BIF_NEWDIALOGSTYLE, ajoute un conseil d'utilisation à la zone de dialogue au lieu de la boîte d'édition. BIF_EDITBOX dépasse ce drapeau.
;; = BIF_USENEWUI = Employer la nouvelle interface utilisateur, y compris une boîte d'édition
(defun DirBox (Message Chemin Drapeau / rep sh)
 (setq sh (vlax-create-object "Shell.Application"))
 (if (setq
rep (vlax-invoke sh 'browseforfolder 0 Message Drapeau Chemin)
     )
   (setq rep (vlax-get-property (vlax-get-property rep 'self) 'path))
   (setq rep nil)
 )
 (vlax-release-object sh)
 rep
)

;; gc:GetDrawingExtents
;; Affecte aux symboles les points inférieur gauche et supérieur droit de l'étendue du dessin
;;
;; Arguments
;; doc : le document à traiter (vla-object)
;; _outputExtMinSym : un symbole quoté auquel sera affecté la valeur du point inférieur gauche
;; _outputExtMaxSym : un symbole quoté auquel sera affecté la valeur du point supérieur droit
(defun gc:GetDrawingExtents (doc _outputExtMinSym _outputExtMaxSym / tmpMinPt tmpMaxPt)
 (vlax-for o (vla-get-ModelSpace doc)
   (or
     (vl-catch-all-error-p (vl-catch-all-apply 'vla-GetBoundingBox (list o 'tmpMinPt 'tmpMaxPt)))
     (if (eval _outputExtMinSym)
(progn
  (set _outputExtMinSym
       (mapcar 'min (eval _outputExtMinSym) (vlax-safearray->list tmpMinPt))
  )
  (set _outputExtMaxSym
       (mapcar 'max (eval _outputExtMaxSym) (vlax-safearray->list tmpMaxPt))
  )
)
(progn
  (set _outputExtMinSym (vlax-safearray->list tmpMinPt))
  (set _outputExtMaxSym (vlax-safearray->list tmpMaxPt))
)
     )
   )
 )
)

;; gc:Getfiles
;; Retourne la liste du (ou des) fichier(s) spécifié(s) dans le dossier (ou disque) et ses sous dossiers
;;
;; Arguments
;; dir : le chemin complet de répertoire racine pour la recherche
;; pat : un modèle pour le type de fichier (accepte les caractères génériques)
(defun gc:GetFiles (dir pat)
 (apply 'append
 (cons (if (vl-directory-files dir pat)
	 (mapcar (function (lambda (x) (strcat dir "\\" x)))
		 (vl-directory-files dir pat)
	 )
       )
       (mapcar (function (lambda (x) (gc:GetFiles (strcat dir "\\" x) pat)))
	       (vl-remove ".."
			  (vl-remove "." (vl-directory-files dir nil -1))
	       )
       )
 )
 )
)

;; gc:GetAxDbDoc
;; Accéder à un dessin fermé
;; Retourne un objet IAxDbDocument si le document est trouve
;; nil si le document n'a pu être trouvé ou s'il est ouvert
;;
;; Argument :
;; Le chemin complet du fichier
(defun gc:GetAxDbDoc (filename / axdbdoc release)
 (setq	axdbdoc
 (vlax-create-object
   (if (	     "ObjectDBX.AxDbDocument"
     (strcat "ObjectDBX.AxDbDocument." (itoa release))
   )
 )
 )
 (if (vl-catch-all-apply
'vla-open
(list axdbdoc filename)
     )
   (not (vlax-release-object axdbdoc))
   axdbdoc
 )
)

;; gc:lst2str
;; Concatène une liste et un séparateur en une chaine
;;
;; Arguments
;; lst : la liste à transformer en chaine
;; sep : le séparateur
(defun gc:lst2str (lst sep)
 (if (cdr lst)
   (strcat (vl-princ-to-string (car lst))
    sep
    (gc:lst2str (cdr lst) sep)
   )
   (vl-princ-to-string (car lst))
 )
)

;; ARCHIVE
;; Inscrit dans un fichier CSV les coordonnées du centre de l'étendue
;; du dessin pour chaque dessin du répertoire et des sous-répertoires

(defun c:ARCHIVE (/ *error* filename dirname len sep file doc minpt maxpt)
 (vl-load-com)
 (defun *error* (msg)
   (and msg
 (or (= msg "Fonction annulée")
     (princ (strcat "Erreur: " msg))
 )
   )
   (and file (close file))
   (vl-catch-all-apply 'vlax-release-object (list doc))
   (princ)
 )
 (if
   (and
     (setq filename (getfiled "Spécifiez le ficher d'extraction" (getvar 'dwgprefix) "csv" 1))
     (setq dirname (DirBox "Spécifier le dossier à traiter" "" 512))
   )
    (progn
      (setq len  (1+ (strlen dirname))
     sep  (vl-registry-read "HKEY_CURRENT_USER\\Control Panel\\International" "sList")
     file (open filename "w")
      )
      (write-line (strcat dirname sep "X" sep "Y" sep "Z") file)
      (foreach	f (gc:GetFiles dirname "*.dwg")
 (print f)
 (if (setq doc (gc:GetAxDbDoc f))
   (progn
     (setq minpt nil
	   maxpt nil
     )
     (gc:GetDrawingExtents doc 'minpt 'maxpt)
     (write-line
       (strcat
	 (strcat "." (substr f len))
	 sep
	 (gc:lst2str (mapcar (function (lambda (x1 x2) (/ (+ x1 x2) 2))) minpt maxpt) sep)
       )
       file
     )
     (vlax-release-object doc)
   )
 )
      )
    )
 )
 (*error* nil)
)

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

Posté(e)

Super intéressant ! :o

 

De mon côté j'ai testé "à l'ancienne" avec un script qui effectue sur chaque dessin les opérations suivantes :

 

_tilemode 1
_ucs _w
_zoom _e
(setq chemin (getvar "dwgprefix"))
(setq fichier (getvar "dwgname"))
(setq centre (getvar "viewctr"))
(setq basgauche (getvar "extmin"))
(setq hautdroite (getvar "extmax"))
(setq fichiercsv (open "c:/temp/test.csv" "a"))
(write-line (strcat chemin fichier ";" (rtos (car centre) 2 2) ";" (rtos (cadr centre) 2 2) ";" (rtos (car basgauche) 2 2) ";" (rtos (cadr basgauche) 2 2) ";" (rtos (car hautdroite) 2 2) ";" (rtos (cadr hautdroite) 2 2)) fichiercsv)
(close fichiercsv)
_close
_y

 

J'ai testé les 2 méthodes sur 7 fichiers (pas assez, mais bon...) assez gros (19.2Mo au total) pour voir s'il y a une différence de rapidité significative, et après plusieurs essais je conclue que ton lisp est un poil plus rapide : 28-30s, contre 30-32s pour le script. :)

 

Edit: quand j'active les smileys, le message ne s'affiche pas correctement...

 

 

[Edité le 22/2/2011 par bryce]

Posté(e)

Le LISP devrait faire la différence sur un nombre plus important de fichiers.

 

Le script est plus rapide pour récupérer les données mais c'est l'ouverture de chaque fichier qui prendra du temps.

 

Avec ObjectDBX, on n'ouvre pas les fichiers dans AutoCAD, mais il faut parcourir tout l'espace objet pour récupérer l'emprise de chaque entité (et dans ce cas c'est plus le nombre d'entités que le "poids" du fichier qui intervient).

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

Posté(e)

@ (gile)

 

Merci beaucoup c'est plus que je n'espérai!

Cela fait longtemps que je voulez apprendre le LISP, avec votre routine je m'y forcerai

Il a fallu tout de même changer son nom car la commande "archive" existe déjà chez moi

Je l'ai testé sur un petit répertoire et ça marche à merveille... j'attends la nuit pour la lancer sur le gros volume car je ne sais pas combien de temps ça va prendre et s'il est possible de l'arrêter en cours de route

 

D'ici là (et avec votre permission) je me permet de l'étudier et d'y effectuer quelques améliorations (de forme et non de fond)

:D

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é