Optimisation et interface utilisateur pour macro VBA Catia d'extrusion

Comment optimiser les performances et intégrer une interface utilisateur (UserForm) pour une macro VBA Catia qui génère des extrusions cylindriques à partir de données de points et splines issues d’Excel, en se basant sur la position des éléments dans l’arborescence ?

Félicitations pour avoir développé une macro VBA fonctionnelle qui automatise la création de géométries complexes dans Catia à partir de données externes. C’est une excellente base. Voici des suggestions pour améliorer la performance, la robustesse et l’ergonomie de votre programme, notamment en intégrant une interface utilisateur pour les paramètres.

1. Optimisation des performances de la macro VBA

Le gain de performance le plus significatif en programmation Catia V5 réside dans la gestion de l’affichage et des mises à jour.

  1. Désactiver l’affichage et les alertes pendant l’exécution :
    Ceci évite à Catia de rafraîchir l’écran et de gérer les boîtes de dialogue d’alerte à chaque opération, ce qui est très coûteux en temps.

    Sub CATMain()
        ' --- Début des optimisations de performance ---
        Dim CATIA As Application
        Set CATIA = GetObject(, "CATIA.Application")
        CATIA.RefreshDisplay = False ' Désactive le rafraîchissement de l'écran
        CATIA.DisplayFileAlerts = False ' Désactive les alertes (ex: sur les mises à jour)
        CATIA.StatusBar = "Traitement en cours... Veuillez patienter."
        ' ---------------------------------------------
    
        Set partDocument1 = CATIA.ActiveDocument
        Set part1 = partDocument1.Part
        ' ... votre code existant ...
    
        ' --- Fin des optimisations de performance ---
        part1.Update ' Une seule mise à jour finale pour tout le modèle
        CATIA.RefreshDisplay = True ' Réactive le rafraîchissement
        CATIA.DisplayFileAlerts = True ' Réactive les alertes
        CATIA.StatusBar = "Prêt"
    End Sub
    
  2. Optimiser les appels à part1.Update :
    Vous avez des part1.Update après chaque bloc de création (plans, esquisses, extrusions). C’est acceptable pour voir les étapes intermédiaires, mais pour une performance maximale, un seul part1.Update à la fin de la macro est idéal. Si vous avez besoin de voir des résultats intermédiaires, regroupez les mises à jour après des blocs logiques importants, mais jamais à l’intérieur d’une boucle de création d’éléments individuels.

  3. Réduire les appels redondants Set :
    Certaines lignes Set sont répétées à l’intérieur de boucles alors qu’elles pourraient être définies une seule fois avant la boucle. Par exemple :

    ' Avant la boucle de création d'esquisses
    Set sketches1 = hybridBody1.HybridSketches
    Set hybridShapes1 = hybridBody1.HybridShapes
    
    For K=NombreBarre*3+1 to NombreBarre*5 Step 2
        ' Ces lignes ne sont plus nécessaires à l'intérieur de la boucle
        ' Set sketches1 = hybridBody1.HybridSketches
        ' Set hybridShapes1 = hybridBody1.HybridShapes
        Set reference1 = hybridShapes1.Item(K)
        Set sketch1 = sketches1.Add(reference1)
        ' ...
    Next
    

    Faites de même pour bodies1 et body1 dans la boucle d’extrusion.

2. Amélioration de la robustesse (Accès aux objets)

Votre approche basée sur l’index (hybridShapes1.Item(N)) est fonctionnelle mais très fragile. Si l’ordre des éléments dans l’arborescence change (par exemple, si un utilisateur ajoute ou supprime manuellement un élément, ou si une autre macro modifie l’ordre), votre macro échouera. Il est fortement recommandé d’accéder aux objets par leur nom.

Exemple d’accès par nom :
Si vos points et splines ont des noms prévisibles (ex: « Point1 », « Spline1 »), vous pouvez les récupérer ainsi :

' Au lieu de : Set hybridShapePointCoord1 = hybridShapes1.Item(I)
' Utilisez :
Set hybridShapePointCoord1 = hybridShapes1.Item("Point" & I)
' Ou, si les noms viennent d'Excel, utilisez le nom exact du point/spline

Si les noms ne sont pas prévisibles, vous devrez itérer sur hybridShapes1 et vérifier le type ou une partie du nom pour trouver l’élément correct. C’est plus complexe mais beaucoup plus robuste.

3. Intégration d’une interface utilisateur (UserForm)

Pour permettre à l’utilisateur d’entrer NombreBarre et Radius, un UserForm est la solution standard en VBA. Voici les étapes et un exemple :

  1. Créer un UserForm :

    • Dans l’éditeur VBA (Alt+F11), faites un clic droit sur votre projet VBA (VBAProject) > Insert > UserForm.
    • Renommez-le (ex: frmParametres) dans la fenêtre des propriétés.
    • Ajoutez des contrôles depuis la Toolbox (si elle n’est pas visible, View > Toolbox) :
      • Deux Label (ex: « Nombre de Barres : », « Rayon (mm) : »)
      • Deux TextBox (ex: txtNombreBarre, txtRadius) pour la saisie.
      • Un CommandButton (ex: cmdLancer) pour valider.
  2. Code du UserForm (frmParametres) :
    Double-cliquez sur le bouton cmdLancer pour ouvrir son code.

    ' Dans le module de code de frmParametres
    Private Sub cmdLancer_Click()
        Dim NombreBarre As Long
        Dim Radius As Double
    
        ' --- Validation des entrées ---
        If Not IsNumeric(Me.txtNombreBarre.Value) Or Trim(Me.txtNombreBarre.Value) = "" Then
            MsgBox "Veuillez entrer un nombre entier valide pour 'Nombre de Barres'.", vbCritical, "Erreur de saisie"
            Me.txtNombreBarre.SetFocus
            Exit Sub
        End If
        NombreBarre = CLng(Me.txtNombreBarre.Value)
    
        If Not IsNumeric(Me.txtRadius.Value) Or Trim(Me.txtRadius.Value) = "" Then
            MsgBox "Veuillez entrer un nombre valide pour 'Rayon'.", vbCritical, "Erreur de saisie"
            Me.txtRadius.SetFocus
            Exit Sub
        End If
        Radius = CDbl(Me.txtRadius.Value)
    
        ' Cacher le formulaire (ne pas le décharger tout de suite pour pouvoir le réafficher si besoin)
        Me.Hide
    
        ' Appel de la macro principale avec les paramètres
        Call CATMainWithParams(NombreBarre, Radius)
    
        ' Décharger le formulaire une fois la macro terminée
        Unload Me
    End Sub
    
  3. Modifier la macro principale pour accepter les paramètres :
    Votre macro CATMain doit être modifiée pour accepter NombreBarre et Radius comme arguments.

    ' Dans un module standard (ex: Module1)
    Sub CATMainWithParams(ByVal NombreBarre As Long, ByVal Radius As Double)
        ' --- Début des optimisations de performance ---
        Dim CATIA As Application
        Set CATIA = GetObject(, "CATIA.Application")
        CATIA.RefreshDisplay = False
        CATIA.DisplayFileAlerts = False
        CATIA.StatusBar = "Traitement en cours... Veuillez patienter."
        ' ---------------------------------------------
    
        Set partDocument1 = CATIA.ActiveDocument
        Set part1 = partDocument1.Part
        Set hybridShapeFactory1 = part1.HybridShapeFactory
        Set hybridBodies1 = part1.HybridBodies
        Set hybridBody1 = hybridBodies1.Item("GeometryFromExcel")
        Set hybridShapes1 = hybridBody1.HybridShapes
    
        ' Déclarations des variables (Radius et NombreBarre sont maintenant passés en paramètres)
        ' Radius = 20 ' Supprimer ou commenter
        ' NombreBarre = 3 ' Supprimer ou commenter
    
        ' Pré-définir les collections une seule fois
        Set sketches1 = hybridBody1.HybridSketches
        Set bodies1 = part1.Bodies
        Set body1 = bodies1.Item("Corps principal")
    
        ' Créations des plans sur chacun des points
        I = 1
        For N = 3 To 3 * NombreBarre Step 3
            Set hybridShapeSpline1 = hybridShapes1.Item(N)
            Set Spline1 = part1.CreateReferenceFromObject(hybridShapeSpline1)
    
            Set hybridShapePointCoord1 = hybridShapes1.Item(I)
            Set Point1 = part1.CreateReferenceFromObject(hybridShapePointCoord1)
            Set hybridShapePlaneNormal1 = hybridShapeFactory1.AddNewPlaneNormal(Spline1, Point1)
            hybridBody1.AppendHybridShape hybridShapePlaneNormal1
            part1.InWorkObject = hybridShapePlaneNormal1
    
            Set hybridShapePointCoord2 = hybridShapes1.Item(I + 1)
            Set Point2 = part1.CreateReferenceFromObject(hybridShapePointCoord2)
            Set hybridShapePlaneNormal2 = hybridShapeFactory1.AddNewPlaneNormal(Spline1, Point2)
            hybridBody1.AppendHybridShape hybridShapePlaneNormal2
            part1.InWorkObject = hybridShapePlaneNormal2
    
            I = I + 3
        Next
        ' part1.Update ' Supprimer si mise à jour finale unique
    
        ' Création de l'esquisse du cercle
        For K = NombreBarre * 3 + 1 To NombreBarre * 5 Step 2
            Set reference1 = hybridShapes1.Item(K)
            Set sketch1 = sketches1.Add(reference1)
            part1.InWorkObject = sketch1
            Set factory2D1 = sketch1.OpenEdition()
            Set circle2D = factory2D1.CreateClosedCircle(0, 0, Radius)
            sketch1.CloseEdition
            part1.InWorkObject = hybridBody1
        Next
        ' part1.Update ' Supprimer si mise à jour finale unique
    
        ' Créations des extrusions pour chacunes des esquisses
        P = NombreBarre * 3 + 2
        For J = 1 To NombreBarre
            part1.InWorkObject = body1 ' Une seule fois suffit si pas de changement
            Set shapeFactory1 = part1.ShapeFactory
            Set Ref8 = part1.CreateReferenceFromName("") ' Ref8 semble être une référence vide, à vérifier
            Set pad1 = shapeFactory1.AddNewPadFromRef(Ref8, 20.000000) ' La longueur 20.000000 est fixe ici
    
            Set sketches2 = hybridBody1.HybridSketches ' Redondant, sketches1 est déjà défini
            Set sketch2 = sketches1.Item(J)
            Set reference9 = part1.CreateReferenceFromObject(sketch2)
            pad1.SetProfileElement reference9
    
            Set limit1 = pad1.FirstLimit
            limit1.LimitMode = catUpToPlaneLimit
    
            Set hybridShapePlaneNormal1 = hybridShapes1.Item(P)
            Set reference10 = part1.CreateReferenceFromObject(hybridShapePlaneNormal1)
            limit1.LimitingElement = reference10
            P = P + 2
        Next
    
        ' --- Fin des optimisations de performance ---
        part1.Update
        CATIA.RefreshDisplay = True
        CATIA.DisplayFileAlerts = True
        CATIA.StatusBar = "Prêt"
    End Sub
    
  4. Macro pour lancer l’interface :
    C’est la macro que l’utilisateur exécutera depuis Catia.

    ' Dans un module standard (ex: Module1)
    Sub LancerMacroExtrusionAvecUI()
        frmParametres.Show ' Affiche le UserForm
    End Sub
    

4. Autres bonnes pratiques

  • Option Explicit : Ajoutez Option Explicit en haut de chaque module de code. Cela force la déclaration de toutes les variables, ce qui aide à prévenir les erreurs de frappe et améliore la lisibilité.
  • Gestion des erreurs : Implémentez une gestion des erreurs de base avec On Error GoTo. Cela rendra votre macro plus robuste face aux imprévus (ex: fichier Excel manquant, objet Catia non trouvé).
    Sub CATMainWithParams(ByVal NombreBarre As Long, ByVal Radius As Double)
        On Error GoTo ErrHandler
        ' ... votre code ...
    
    Exit Sub
    
    ErrHandler:
        MsgBox "Une erreur est survenue : " & Err.Description, vbCritical, "Erreur Macro Catia"
        ' Réactiver l'affichage et les alertes en cas d'erreur
        CATIA.RefreshDisplay = True
        CATIA.DisplayFileAlerts = True
        CATIA.StatusBar = "Erreur"
    End Sub
    
  • Commentaires : Continuez à bien commenter votre code, surtout les parties complexes ou les hypothèses (comme l’ordre des éléments dans l’arborescence).

En appliquant ces améliorations, votre macro sera non seulement plus rapide, mais aussi plus fiable et plus conviviale pour les utilisateurs.