Exporter volumes solides 3D AutoCAD par calque et couleur vers Excel (VBA)

Comment exporter les volumes de solides 3D AutoCAD (AcDb3dSolid) vers un fichier Excel, en regroupant les données par calque et en incluant la couleur des solides, sachant que la fonction native ‹ Extraire des données › ne permet pas d’obtenir directement le volume ?

L’extraction des volumes de solides 3D AutoCAD vers un tableau structuré par calque et couleur dans Excel est une demande fréquente qui n’est pas directement couverte par la fonction native ‹ Extraire des données › pour les propriétés volumiques. Deux approches principales peuvent être utilisées : une macro VBA pour une exportation directe vers Excel, et une routine LISP pour la création de champs dynamiques dans le dessin.

1. Solution Principale : Exportation vers Excel via une Macro VBA

Cette méthode permet d’itérer sur les objets de votre dessin et d’exporter leurs propriétés (y compris le volume des solides 3D) vers une feuille de calcul Excel active. Elle est idéale pour générer des métrés ou des listes quantitatives.

Prérequis :

  • Un fichier Excel doit être ouvert et actif avant d’exécuter la macro.
  • La macro est conçue pour les objets de base (lignes, polylignes, cercles, arcs, solides 3D, régions, références de blocs simples) et ne gère pas l’extraction des données de blocs imbriqués pour le volume.

Code VBA :

Sub MOP()

Dim xlApp As Object

On Error GoTo fin

Set xlApp = GetObject(, "Excel.Application")

Dim strRep As String

Dim strTest As String

Dim i As Long

Dim Haut As Double

Dim PNum As Integer

Dim oObj As AcadObject

Dim oLay As AcadObject

Dim sLay As String

Dim ssObj As AcadSelectionSet

Dim sType As String

Dim sValue As String

Dim pBase As Variant

Dim oTmp As Acad3DSolid

With xlApp.ActiveSheet

.Cells(2, 1) = "N°"

.Cells(2, 2) = "Layer"

.Cells(2, 3) = "color"

.Cells(2, 4) = "Handle"

.Cells(2, 5) = "ObjectName"

.Cells(2, 6) = "x0"

.Cells(2, 7) = "y0"

.Cells(2, 8) = "z0"

.Cells(2, 9) = "Length/Volume"

.Cells(2, 10) = "Area/Rayon"

PNum = 3

On Error Resume Next

For Each oObj In ThisDrawing.ModelSpace

sLay = oObj.Layer

Set oLay = ThisDrawing.Layers(sLay)

If (Not oLay.Freeze) And (Not oLay.Lock) Then

.Cells(PNum, 1) = PNum

.Cells(PNum, 2) = oObj.Layer

.Cells(PNum, 3) = oObj.color

.Cells(PNum, 4) = "_" & oObj.Handle

.Cells(PNum, 5) = oObj.ObjectName

If oObj.ObjectName = "AcDbPolyline" Then

.Cells(PNum, 6) = oObj.Coordinate(0)(0)

.Cells(PNum, 7) = oObj.Coordinate(0)(1)

.Cells(PNum, 8) = oObj.Coordinate(0)(2)

.Cells(PNum, 9) = oObj.Length

.Cells(PNum, 10) = oObj.Area

End If

If oObj.ObjectName = "AcDbLine" Then

pBase = oObj.StartPoint

.Cells(PNum, 6) = pBase(0)

.Cells(PNum, 7) = pBase(1)

.Cells(PNum, 8) = pBase(2)

.Cells(PNum, 9) = oObj.Length

.Cells(PNum, 10) = ""

End If

If oObj.ObjectName = "AcDbCircle" Then

pBase = oObj.Center

.Cells(PNum, 6) = pBase(0)

.Cells(PNum, 7) = pBase(1)

.Cells(PNum, 8) = pBase(2)

.Cells(PNum, 9) = oObj.Circumference

.Cells(PNum, 10) = oObj.Radius

End If

If oObj.ObjectName = "AcDbArc" Then

pBase = oObj.Center

.Cells(PNum, 6) = pBase(0)

.Cells(PNum, 7) = pBase(1)

.Cells(PNum, 8) = pBase(2)

.Cells(PNum, 9) = oObj.ArcLength

.Cells(PNum, 10) = oObj.Radius

End If

If oObj.ObjectName = "AcDb3dSolid" Then

pBase = oObj.Position

.Cells(PNum, 6) = pBase(0)

.Cells(PNum, 7) = pBase(1)

.Cells(PNum, 8) = pBase(2)

.Cells(PNum, 9) = oObj.Volume

.Cells(PNum, 10) = oObj.Area

End If

If oObj.ObjectName = "AcDbRegion" Then

Set oTmp = oObj

pBase = oObj.Position

.Cells(PNum, 6) = "" 'pBase(0)

.Cells(PNum, 7) = "" 'pBase(1)

.Cells(PNum, 8) = "" 'pBase(2)

.Cells(PNum, 9) = oObj.Perimeter

.Cells(PNum, 10) = oObj.Area

End If

If oObj.ObjectName = "AcDbBlockReference" Then

pBase = oObj.InsertionPoint

.Cells(PNum, 6) = pBase(0)

.Cells(PNum, 7) = pBase(1)

.Cells(PNum, 8) = pBase(2)

.Cells(PNum, 9) = oObj.EffectiveName

.Cells(PNum, 10) = ""

End If

PNum = PNum + 1

End If

Next oObj

End With

Exit Sub

fin:

MsgBox "Un fichier excel doit être ouvert", vbExclamation

End Sub

Procédure d’Utilisation :

  1. Ouvrir l’éditeur VBA dans AutoCAD : Tapez VBAIDE dans la ligne de commande AutoCAD et appuyez sur Entrée, ou utilisez ALT+F11.
  2. Insérer un nouveau module : Dans la fenêtre de l’éditeur VBA (VBA Project), faites un clic droit sur VBAProject (votre_dessin.dwg) > Insertion > Module.
  3. Coller le code : Copiez l’intégralité du code VBA ci-dessus et collez-le dans la fenêtre du module vide.
  4. Exécuter la macro :
    • Assurez-vous qu’un fichier Excel est ouvert et que la feuille sur laquelle vous souhaitez exporter est active.
    • Retournez dans AutoCAD.
    • Tapez VBARUN dans la ligne de commande et appuyez sur Entrée.
    • Dans la boîte de dialogue ‹ Macros ›, sélectionnez MOP et cliquez sur ‹ Exécuter ›.

Explication des Données Exportées :
La macro génère un tableau Excel avec les colonnes suivantes :

  • N° : Numéro de ligne.
  • Layer : Nom du calque de l’objet.
  • Color : Code couleur AutoCAD de l’objet.
  • Handle : Identifiant unique de l’objet dans le dessin.
  • ObjectName : Type d’objet AutoCAD (ex: AcDb3dSolid, AcDbPolyline).
  • x0, y0, z0 : Coordonnées X, Y, Z du point de base/insertion de l’objet (pour les solides 3D, c’est oObj.Position).
  • Length/Volume : Longueur pour les lignes/polylignes/arcs, Volume pour les solides 3D, Périmètre pour les régions.
  • Area/Rayon : Surface pour les polylignes/régions/solides 3D, Rayon pour les cercles/arcs.

Note sur la colonne Z0 et les limites de contour :
La colonne z0 dans cette macro correspond à la coordonnée Z du point de base (oObj.Position ou InsertionPoint). Si vous avez besoin des limites de la boîte englobante (Bounding Box) d’un solide (par exemple, Limite inférieure Z ou Limite supérieure Z comme affiché par la commande LISTE), cela nécessiterait une modification de la macro pour utiliser la méthode vla-GetBoundingBox sur l’objet Acad3DSolid et extraire les valeurs Z des points ll (lower-left) et ur (upper-right).

2. Solution Alternative : Création de Champs Dynamiques dans le Dessin (LISP)

Cette approche ne génère pas directement un fichier Excel, mais crée des objets texte (MText) dans votre dessin, dont le contenu est un champ dynamique lié au volume ou à la surface d’un solide 3D. Ces champs se mettent à jour automatiquement si le solide est modifié.

Code LISP :

(vl-load-com)
(defun c:SolidVolume-Area2Field ( / js obj AcDoc Space nw_style pt htx rtx unit_key unit_draw n dxf_cod lremov k_mod ename ll ur nw_obj)
 (princ "\nSélectionnez un solide.")
 (while
 (null
 (setq js
 (ssget "_+.:E:S"
 (list
 '(0 . "3DSOLID")
 (cons 67 (if (eq (getvar "CVPORT") 1) 1 0))
 (cons 410 (if (eq (getvar "CVPORT") 1) (getvar "CTAB") "Model"))
 )
 )
 )
 )
 (princ "\nCe n'est pas un objet solide valable pour cette fonction!")
 )
 (initget 6)
 (setq htx (getdist (getvar "VIEWCTR") (strcat "\nSpécifiez la hauteur du champ <" (rtos (getvar "TEXTSIZE")) ">: ")))
 (if htx (setvar "TEXTSIZE" htx))
 (if (not (setq rtx (getorient (getvar "VIEWCTR") "\nSpécifiez l'orientation du champ <0.0>: "))) (setq rtx 0.0))
 (setq
 AcDoc (vla-get-ActiveDocument (vlax-get-acad-object))
 Space
 (if (= 1 (getvar "CVPORT"))
 (vla-get-PaperSpace AcDoc)
 (vla-get-ModelSpace AcDoc)
 )
 )
 (cond
 ((null (tblsearch "LAYER" "Id-Volumes"))
 (vlax-put (vla-add (vla-get-layers AcDoc) "Id-Volumes") 'color 96)
 )
 )
 (cond
 ((null (tblsearch "STYLE" "Romand-Field"))
 (setq nw_style (vla-add (vla-get-textstyles AcDoc) "Romand-Field"))
 (mapcar
 '(lambda (pr val)
 (vlax-put nw_style pr val)
 )
 (list 'FontFile 'Height 'ObliqueAngle 'Width 'TextGenerationFlag)
 (list "romand.shx" 0.0 (/ (* 15.0 pi) 180) 1.0 0.0)
 )
 )
 )
 (if (or (eq (getvar "USERS5") "") (not (eq (substr (getvar "USERS5") 1 2) "qz")))
 (progn
 (initget "KM ME CM MM")
 (if (not (setq unit_key (getkword "\nDessin réalisé en [KM/ME/CM/MM] <ME>: ")))
 (setq unit_key "ME")
 )
 (cond
 ((eq unit_key "KM")
 (setq unit_draw 1000000)
 )
 ((eq unit_key "ME")
 (setq unit_draw 1000 unit_key "M")
 )
 ((eq unit_draw 10)
 (setq unit_draw 10)
 )
 ((eq unit_draw 1)
 (setq unit_draw 1)
 )
 )
 (setvar "USERS5" (strcat "qz" (itoa unit_draw)))
 )
 (progn
 (setq unit_draw (atoi (substr (getvar "USERS5") 3)))
 (cond
 ((eq unit_draw 1000000)
 (setq unit_key "KM")
 )
 ((eq unit_draw 1000)
 (setq unit_key "M")
 )
 ((eq unit_draw 10)
 (setq unit_key "CM")
 )
 ((eq unit_draw 1)
 (setq unit_key "MM")
 )
 )
 )
 )
 (initget "Unique Multiple _Single Multiple")
 (if (eq (getkword "\nSélection filtrée [Unique/Multiple]<M>: ") "Single")
 (setq n -1)
 (setq
 dxf_cod (entget (ssname js 0))
 js
 (ssget "_X" 
 (foreach m (foreach n dxf_cod (if (not (member (car n) '(0 67 410 8 6 62 48 420 70))) (setq lremov (cons (car n) lremov))))
 (setq dxf_cod (vl-remove (assoc m dxf_cod) dxf_cod))
 )
 )
 n -1
 )
 )
 (initget "Volume Surface _Volume Area")
 (setq k_mod (getkword "\nMesurer [Volume/Surface] <Volume> : "))
 (if (not k_mod) (setq k_mod "Volume"))
 (repeat (sslength js)
 (setq
 obj (ssname js (setq n (1+ n)))
 ename (vlax-ename->vla-object obj)
 )
 (vla-GetBoundingBox ename 'll 'ur)
 (setq
 ll (safearray-value ll)
 ur (safearray-value ur)
 pt (mapcar '* (mapcar '+ ll ur) '(0.5 0.5 0.5))
 nw_obj
 (vla-addMtext Space
 (vlax-3d-point pt)
 0.0
 (strcat
 "%<\\AcObjProp.16.2 Object(%<\\_ObjId "
 (itoa (vla-get-ObjectID ename))
 ">%)."
 k_mod
 " \\f \"%lu2%pr2%ps["
 (if (eq k_mod "Volume") "V=," "S=,")
 (strcase unit_key T)
 (if (eq k_mod "Volume") "\\\U+00B3]\">%" "²]\">%")
 )
 )
 )
 (mapcar
 '(lambda (pr val)
 (vlax-put nw_obj pr val)
 )
 (list 'AttachmentPoint 'Height 'DrawingDirection 'InsertionPoint 'StyleName 'Layer 'Rotation)
 (list 5 (getvar "TEXTSIZE") 5 pt "Romand-Field" "Id-Volumes" rtx)
 )
 )
 (prin1)
)

Procédure d’Utilisation :

  1. Charger le LISP : Tapez APPLOAD dans la ligne de commande AutoCAD, naviguez jusqu’au fichier .lsp que vous aurez créé en copiant le code ci-dessus, puis cliquez sur ‹ Charger ›.
  2. Exécuter la commande : Tapez SolidVolume-Area2Field (ou SVAF) dans la ligne de commande et appuyez sur Entrée.
  3. Suivre les invites : Le programme vous demandera de sélectionner un solide, de spécifier la hauteur et l’orientation du texte, les unités du dessin, et si vous voulez mesurer le volume ou la surface.

Avantages et Limitations :

  • Avantages : Crée des étiquettes dynamiques directement dans le dessin, qui se mettent à jour automatiquement. Utile pour la visualisation directe des quantités.
  • Limitations : Ne génère pas de rapport Excel directement. Nécessite une étape supplémentaire si un tableau est requis (par exemple, en utilisant la fonction ‹ Extraire des données › sur les MText générés, mais cela ne regroupera pas par calque/couleur des solides d’origine de manière native).

Bonnes Pratiques et Conseils Supplémentaires :

  • Unités du Dessin : Assurez-vous que les unités de votre dessin AutoCAD sont correctement définies pour que les volumes et surfaces soient calculés avec précision.
  • Personnalisation : Les deux scripts peuvent être personnalisés pour inclure d’autres propriétés, filtrer des objets spécifiques, ou modifier le format de sortie. Pour des besoins complexes, le développement en .NET (C# ou VB.NET) offre une flexibilité et une robustesse supérieures à VBA et LISP pour interagir avec l’API AutoCAD et Excel.
  • Gestion des Calques et Couleurs : Une fois les données exportées dans Excel via la macro VBA, vous pouvez facilement utiliser les fonctions de tri, de filtrage et de tableau croisé dynamique d’Excel pour regrouper les volumes par calque et couleur, et obtenir des totaux ou des sous-totaux.