AutoLISP : le guide complet — Chapitre 16 / 17

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.