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 :
- Ouvrir l’éditeur VBA dans AutoCAD : Tapez
VBAIDEdans la ligne de commande AutoCAD et appuyez sur Entrée, ou utilisezALT+F11. - 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. - Coller le code : Copiez l’intégralité du code VBA ci-dessus et collez-le dans la fenêtre du module vide.
- 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
VBARUNdans la ligne de commande et appuyez sur Entrée. - Dans la boîte de dialogue ‹ Macros ›, sélectionnez
MOPet 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 :
- Charger le LISP : Tapez
APPLOADdans la ligne de commande AutoCAD, naviguez jusqu’au fichier.lspque vous aurez créé en copiant le code ci-dessus, puis cliquez sur ‹ Charger ›. - Exécuter la commande : Tapez
SolidVolume-Area2Field(ouSVAF) dans la ligne de commande et appuyez sur Entrée. - 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.