AutoLISP : le guide complet — Chapitre 16 / 16

Interopérabilité ActiveX

AutoLISP, via les extensions Visual LISP, peut communiquer avec n'importe quelle application supportant ActiveX/COM (Component Object Model). L'exemple le plus courant est l'interaction avec Microsoft Excel pour exporter des données ou générer des rapports, mais le même principe s'applique à Word, Outlook, ou toute autre application exposant une interface COM.

Important : la communication ActiveX ne fonctionne que sous Windows. Les versions d'AutoCAD pour Mac ne supportent pas Visual LISP ActiveX.

Le modèle COM en bref

Le modèle COM repose sur trois concepts :

  • Objets : des entités logicielles qui exposent des fonctionnalités (un classeur Excel, une feuille de calcul, une cellule)
  • Propriétés : des valeurs qu'on peut lire ou modifier sur un objet (la valeur d'une cellule, la visibilité de l'application)
  • Méthodes : des actions qu'on peut exécuter sur un objet (ajouter un classeur, enregistrer un fichier)

Depuis AutoLISP, on manipule ces objets avec les fonctions vlax-*.

Les fonctions clés

Fonction Rôle
vlax-get-or-create-object Se connecter à une application (la lance si nécessaire)
vlax-get-object Se connecter à une application déjà en cours d'exécution
vlax-get-property Lire une propriété d'un objet COM
vlax-put-property Modifier une propriété d'un objet COM
vlax-invoke-method Appeler une méthode d'un objet COM
vlax-release-object Libérer un objet COM (évite les fuites mémoire)

Se connecter à une application

;; Lancer Excel (ou se connecter à une instance existante)
(setq excel (vlax-get-or-create-object "Excel.Application"))

;; Se connecter uniquement si Excel est déjà ouvert (retourne nil sinon)
(setq excel (vlax-get-object "Excel.Application"))

Les noms d'application COM courants :

Application Identifiant COM
Microsoft Excel "Excel.Application"
Microsoft Word "Word.Application"
Microsoft Outlook "Outlook.Application"

Les applications COM exposent une hiérarchie d'objets. Pour Excel, la chaîne est : ApplicationWorkbooksWorkbookWorksheetsWorksheetCellsCell. On navigue d'un niveau à l'autre avec vlax-get-property :

(setq classeurs (vlax-get-property excel 'Workbooks))
(setq classeur (vlax-invoke-method classeurs 'Add))
(setq feuille (vlax-get-property classeur 'ActiveSheet))

Simplifier les accès aux cellules

Le code pour écrire dans une cellule Excel est assez verbeux avec les fonctions vlax-* brutes. On peut le factoriser dans des fonctions utilitaires :

(defun ecrire-cellule (feuille ligne colonne valeur / cellule)
  (setq cellule
    (vlax-get-property
      (vlax-get-property feuille 'Cells)
      'Item ligne colonne
    )
  )
  (vlax-put-property cellule 'Value valeur)
)

(defun lire-cellule (feuille ligne colonne / cellule)
  (setq cellule
    (vlax-get-property
      (vlax-get-property feuille 'Cells)
      'Item ligne colonne
    )
  )
  (vlax-get-property cellule 'Value)
)

Utilisation :

(ecrire-cellule feuille 1 1 "N°")
(ecrire-cellule feuille 1 2 "Longueur")
(ecrire-cellule feuille 2 1 1)
(ecrire-cellule feuille 2 2 42.5)

(lire-cellule feuille 2 2)  ; → 42.5

Exemple complet : exporter un métré vers Excel

Ce programme sélectionne toutes les lignes du dessin, calcule leur longueur totale et exporte le détail dans une feuille Excel :

(defun c:metre-excel (/ jeu index entite donnees point-depart point-arrivee
                        longueur excel classeurs classeur feuille
                        ligne-excel longueur-totale)
  ;; Sélectionner toutes les lignes
  (setq jeu (ssget "_X" '((0 . "LINE"))))

  (if (null jeu)
    (progn (princ "\nAucune ligne trouvée.") (princ) (exit))
  )

  ;; Lancer Excel (ou se connecter à une instance existante)
  (setq excel (vlax-get-or-create-object "Excel.Application"))

  ;; Rendre Excel visible
  (vlax-put-property excel 'Visible :vlax-true)

  ;; Créer un nouveau classeur
  (setq classeurs (vlax-get-property excel 'Workbooks))
  (setq classeur (vlax-invoke-method classeurs 'Add))
  (setq feuille (vlax-get-property classeur 'ActiveSheet))

  ;; Écrire les en-têtes
  (ecrire-cellule feuille 1 1 "N°")
  (ecrire-cellule feuille 1 2 "X1")
  (ecrire-cellule feuille 1 3 "Y1")
  (ecrire-cellule feuille 1 4 "X2")
  (ecrire-cellule feuille 1 5 "Y2")
  (ecrire-cellule feuille 1 6 "Longueur")

  ;; Parcourir les lignes du dessin
  (setq index 0)
  (setq ligne-excel 2)
  (setq longueur-totale 0.0)

  (repeat (sslength jeu)
    (setq entite (ssname jeu index))
    (setq donnees (entget entite))
    (setq point-depart (cdr (assoc 10 donnees)))
    (setq point-arrivee (cdr (assoc 11 donnees)))

    ;; Calculer la longueur
    (setq longueur (distance point-depart point-arrivee))
    (setq longueur-totale (+ longueur-totale longueur))

    ;; Écrire dans Excel
    (ecrire-cellule feuille ligne-excel 1 (1+ index))
    (ecrire-cellule feuille ligne-excel 2 (nth 0 point-depart))
    (ecrire-cellule feuille ligne-excel 3 (nth 1 point-depart))
    (ecrire-cellule feuille ligne-excel 4 (nth 0 point-arrivee))
    (ecrire-cellule feuille ligne-excel 5 (nth 1 point-arrivee))
    (ecrire-cellule feuille ligne-excel 6 longueur)

    (setq index (1+ index))
    (setq ligne-excel (1+ ligne-excel))
  )

  ;; Écrire le total
  (ecrire-cellule feuille ligne-excel 5 "TOTAL")
  (ecrire-cellule feuille ligne-excel 6 longueur-totale)

  ;; Ajuster la largeur des colonnes
  (vlax-invoke-method
    (vlax-get-property
      (vlax-get-property feuille 'UsedRange)
      'Columns)
    'AutoFit
  )

  (princ (strcat "\n" (itoa (sslength jeu)) " ligne(s) exportée(s) vers Excel."))
  (princ (strcat "\nLongueur totale : " (rtos longueur-totale 2 2)))

  ;; Libérer les objets COM
  (vlax-release-object feuille)
  (vlax-release-object classeur)
  (vlax-release-object classeurs)
  ;; Ne pas libérer excel pour laisser l'utilisateur consulter le résultat

  (princ)
)

Remarque : cet exemple utilise la fonction ecrire-cellule définie plus haut. En pratique, vous la placeriez dans un fichier utilitaire chargé avant votre programme principal.

Libérer les objets COM

Chaque appel à vlax-get-property ou vlax-invoke-method qui retourne un objet COM alloue de la mémoire. Si vous ne libérez pas ces objets, la mémoire n'est jamais récupérée — c'est une fuite mémoire.

La règle est simple : libérez les objets COM dans l'ordre inverse de leur création :

;; Création : excel → classeurs → classeur → feuille
;; Libération : feuille → classeur → classeurs → excel

(vlax-release-object feuille)
(vlax-release-object classeur)
(vlax-release-object classeurs)
(vlax-release-object excel)

Si vous ne libérez pas l'objet excel, l'instance d'Excel restera en mémoire même après la fermeture de sa fenêtre (visible dans le Gestionnaire des tâches).

Bonne pratique : dans un programme de production, encadrez votre code ActiveX dans un gestionnaire d'erreur *error* (vu au chapitre 11) pour garantir la libération des objets COM même en cas d'interruption.

Accéder au modèle objet d'AutoCAD

L'interopérabilité ActiveX ne sert pas qu'à piloter des applications externes. AutoCAD lui-même expose un modèle objet COM que vous pouvez manipuler depuis AutoLISP. C'est une alternative aux fonctions entmake/entmod :

;; Accéder au document courant
(setq document (vla-get-ActiveDocument (vlax-get-acad-object)))

;; Accéder à l'espace modèle
(setq espace-modele (vla-get-ModelSpace document))

;; Créer un cercle via ActiveX
(setq centre (vlax-3d-point 50.0 50.0 0.0))
(setq cercle (vla-AddCircle espace-modele centre 25.0))

;; Modifier ses propriétés
(vla-put-Color cercle acRed)
(vla-put-Layer cercle "Construction")

Les fonctions vla-* sont des raccourcis générés automatiquement par Visual LISP pour les objets AutoCAD. Elles sont équivalentes à vlax-get-property / vlax-put-property / vlax-invoke-method mais avec une syntaxe plus concise.

Résumé

Concept Fonction Description
Lancer une application vlax-get-or-create-object Se connecte ou lance l'application
Application existante vlax-get-object Se connecte uniquement si déjà lancée
Lire une propriété vlax-get-property Récupère la valeur d'une propriété COM
Modifier une propriété vlax-put-property Change la valeur d'une propriété COM
Appeler une méthode vlax-invoke-method Exécute une action sur un objet COM
Libérer un objet vlax-release-object Libère la mémoire allouée pour l'objet
Objet AutoCAD vlax-get-acad-object Accède à l'application AutoCAD elle-même
Point 3D pour ActiveX vlax-3d-point Crée un variant point 3D pour les méthodes vla-*

Conclusion du tutoriel

Félicitations ! Vous avez parcouru l'ensemble d'AutoLISP, depuis votre première expression (alert "Bonjour !") jusqu'à l'interopérabilité avec des applications externes. Voici un résumé de votre parcours :

  1. Introduction — Les origines de LISP et le choix d'Autodesk
  2. Premiers pas — La ligne de commande et alert
  3. Syntaxe — La notation préfixée et les parenthèses
  4. Mathématiques — Les opérations de calcul
  5. Variablessetq et les types de données
  6. Fonctionsdefun et les commandes c:
  7. Contrôleif, cond, while et repeat
  8. Listes — La structure de données fondamentale
  9. Interagir avec le dessincommand, entmake et entmod
  10. Lire et écrire des fichiersopen, read-line, write-line, findfile
  11. Gestion des erreurs*error* et la restauration d'état
  12. Symboles et lambda — La programmation fonctionnelle
  13. Données étendues et dictionnaires — Xdata, xrecords et handles
  14. Les reactors — Surveiller et réagir aux événements
  15. Interopérabilité ActiveX — Piloter Excel et le modèle objet d'AutoCAD

Vous avez maintenant les bases solides pour commencer à écrire vos propres scripts AutoLISP. La prochaine étape ? Ouvrez AutoCAD, identifiez une tâche répétitive dans votre travail quotidien, et essayez de l'automatiser. C'est en pratiquant qu'on apprend le mieux.


Coup de pouce Besoin d'un développement AutoCAD (AutoLISP, ObjectARX, .NET, VBA) ? Contactez-moi pour un devis gratuit.