Un calendrier perpétuel en AutoLISP

:sparkles: Bonjour à tous, en ce 1er janvier 2026 m’est venue l’idée de faire créer à l’intelligence artificielle Gemini Pro un petit programme AutoLISP qui dessinerait un calendrier annuel. Pourquoi pas? :winking_face_with_tongue:

C’est un moyen de voir comment se débrouille Gemini version Pro pour créer un petit programme AutoLISP. Et ça pourra peut-être donner des idées à certains pour créer ce type de petite routine facilement.

Voilà donc ci-dessous le résultat partiel d’une copie d’écran du calendrier pour l’année 2026. Inutile de dire, et vous l’avez certainement vu au premier coup d’œil, que ce programme est très perfectible. Largeur de colonnes, affichage des numéros de jour, aux intersections, enfin des petites améliorations qu’on pourrait faire sans doute très facilement. Mais ce qui m’intéressait de voir, c’est le principe général de fonctionnement, surtout l’exactitude du calendrier. Je n’ai pas testé ce calendrier pour les années bissextiles, mais Gemini me certifie que ça fonctionnera, à voir, comme dit l’autre. :grinning_face:

Je vous donne ci-dessous le code assez brut de décoffrage (sans modification) :

[!Note]
L’algorithme de Sakamoto est une méthode simple, rapide et purement arithmétique permettant de déterminer le jour de la semaine correspondant à une date donnée dans le calendrier grégorien. Il est particulièrement apprécié en informatique car il évite les calculs complexes ou les conversions de calendrier (comme vous, je n’en avais jamais entendu parler :grinning_face_with_smiling_eyes:).

;;; COMMANDE : CALENDRIER
;;; DESCRIPTION : Génère un calendrier perpétuel sous forme de Tableau AutoCAD
;;;               Inclut une colonne pour les jours de la semaine.
;;; AUTEUR : Assistant Gemini
;;; DATE : 2026
;;; ==========================================================================

(defun c:CALENDRIER (/ *error* doc ms year pt tableObj rowHeight colWidth 
                       months daysOfWeek daysInMonth startDay currentDayOfWeek 
                       numDays d weekIndex rowIndex colIndex titleRow headerRow dataStartRow
                       totalRows totalCols numDataRows i)

  ;; Gestion des erreurs
  (defun *error* (msg)
    (if (and msg (not (wcmatch (strcase msg) "*CANCEL*,*QUIT*,*BREAK*")))
      (princ (strcat "\nErreur: " msg))
    )
    (princ)
  )

  ;; Chargement des extensions Visual LISP
  (vl-load-com)
  (setq doc (vla-get-ActiveDocument (vlax-get-acad-object)))
  (setq ms (vla-get-ModelSpace doc))

  ;; --------------------------------------------------------------------------
  ;; 1. SAISIE UTILISATEUR
  ;; --------------------------------------------------------------------------
  (initget 6)
  (setq year (getint "\nEntrez l'année (ex: 2024) : "))
  (if (not year) (setq year 2024))

  (setq pt (getpoint "\nPoint d'insertion du calendrier : "))
  (if (not pt) (exit))

  ;; --------------------------------------------------------------------------
  ;; 2. FONCTIONS DE CALCUL
  ;; --------------------------------------------------------------------------

  (defun is-leap-year (y)
    (if (or (and (= (rem y 4) 0) (/= (rem y 100) 0)) (= (rem y 400) 0)) T nil)
  )

  (defun get-days-in-month (m y)
    (cond
      ((member m '(1 3 5 7 8 10 12)) 31)
      ((member m '(4 6 9 11)) 30)
      ((= m 2) (if (is-leap-year y) 29 28))
    )
  )

  ;; Algorithme de Sakamoto pour le jour de la semaine
  ;; 0=Lundi, 1=Mardi... 6=Dimanche
  (defun get-weekday (d m y / t-list)
    (setq t-list '(0 3 2 5 0 3 5 1 4 6 2 4))
    (if (< m 3) (setq y (1- y)))
    (rem (+ y (fix (/ y 4)) (- (fix (/ y 100))) (fix (/ y 400)) (nth (1- m) t-list) d -1) 7)
  )

  ;; --------------------------------------------------------------------------
  ;; 3. CONFIGURATION DU TABLEAU
  ;; --------------------------------------------------------------------------
  
  (setq rowHeight 8.0)
  (setq colWidth 25.0)
  (setq months '("JANVIER" "FÉVRIER" "MARS" "AVRIL" "MAI" "JUIN" 
                 "JUILLET" "AOÛT" "SEPTEMBRE" "OCTOBRE" "NOVEMBRE" "DÉCEMBRE"))
  (setq daysOfWeek '("Lundi" "Mardi" "Mercredi" "Jeudi" "Vendredi" "Samedi" "Dimanche"))

  (setq numDataRows 42) 
  (setq totalRows (+ 2 numDataRows))
  (setq totalCols 13)

  ;; Création du tableau
  (setq tableObj (vla-AddTable ms (vlax-3d-point pt) totalRows totalCols rowHeight colWidth))
  
  ;; Forcer la régénération des propriétés pour éviter les types nil
  (vla-put-RegenerateTableSuppressed tableObj :vlax-true)

  ;; --------------------------------------------------------------------------
  ;; 4. REMPLISSAGE
  ;; --------------------------------------------------------------------------

  ;; A. Titre
  (vla-SetText tableObj 0 0 (strcat "CALENDRIER PERPÉTUEL " (itoa year)))

  ;; B. Entêtes colonnes
  (vla-SetText tableObj 1 0 "JOURS")
  (setq i 0)
  (foreach m months
    (vla-SetText tableObj 1 (1+ i) m)
    (vla-SetCellAlignment tableObj 1 (1+ i) 5)
    (setq i (1+ i))
  )

  ;; C. Colonne des Jours (Entêtes de lignes)
  (setq i 0)
  (while (< i numDataRows)
    (vla-SetText tableObj (+ 2 i) 0 (nth (rem i 7) daysOfWeek))
    (vla-SetCellAlignment tableObj (+ 2 i) 0 4)
    (setq i (1+ i))
  )

  ;; D. Remplissage des numéros
  (setq colIndex 1)
  (while (<= colIndex 12)
    (setq mDays (get-days-in-month colIndex year))
    (setq d 1)
    
    ;; Calcul du jour de la semaine pour le 1er du mois (0=Lun, 6=Dim)
    (setq firstDayWeekday (get-weekday 1 colIndex year))
    
    (while (<= d mDays)
      ;; Calcul de la ligne cible :
      ;; 2 (offset titre/entête) + firstDayWeekday (décalage du début du mois) + (d - 1)
      (setq targetRow (+ 2 firstDayWeekday (1- d)))
      
      ;; Vérification de sécurité
      (if (< targetRow totalRows)
        (progn
          (vla-SetText tableObj targetRow colIndex (itoa d))
          (vla-SetCellAlignment tableObj targetRow colIndex 5)
        )
      )
      (setq d (1+ d))
    )
    (setq colIndex (1+ colIndex))
  )

  (vla-put-RegenerateTableSuppressed tableObj :vlax-false)
  (vla-Update tableObj)
  (princ (strcat "\nCalendrier " (itoa year) " généré avec succès."))
  (princ)
)

(princ "\nCommande chargée. Tapez CALENDRIER.")
(princ)
  • Super!
  • OK
  • Bof
  • Y en a vraiment qu’on rien à f…
0 votant

C’est super amusant !
Mais est-ce le code « brut » de Gemini Pro ? Ou a-t-il été « mise en forme » ?
En tous cas, je le garde, je m’en inspirerais pour mes futurs tableaux…

1 « J'aime »

C’est le code brut sans aucune modification.

1 « J'aime »

Très bien fait : gestion des erreurs, nommage « compréhensible » des variables, commentaires…
Je suis stupéfaits ! !
Et quelle était la demande à Gemini Pro ? Ca tenait en une ligne ou un pavé ?

Voici ici dessous le prompt initial qui n’a pas fonctionné tout de suite, j’ai dû envoyer deux ou trois autres prompts pour corriger ce qui ne fonctionnait pas la première fois (en mode canvas[1], c’est la procédure, ici nous ne parlons pas d’une génération d’image, mais du développement d’une application) mais en gros si j’avais travaillé un peu plus le prompt initial je pense que ça aurait pu fonctionner tout de suite.

[!Note]
Je vous déconseille de taper, de saisir vocalement, un prompt trop court, trop généraliste, pour développer une application. Ça peut suffire pour une image, mais pas pour une application.

Un conseil, quand vous envoyez un prompt pour faire une application, faites-le toujours générer lui-même par une intelligence artificielle. J’ai pris l’habitude de générer mes prompts par ChatGPT.

Donc en fait la procédure est la suivante:
Vous allez dans ChatGPT. Moi je fais cela par saisie vocale parce que ça va plus vite. Je lui raconte un peu dans le désordre tout ce que je veux faire. Je lui dis génère moi un prompt pour Google Gemini Pro qui va me créer un calendrier, en AutoLISP, blablabla, blablabla. ChatGPT vous sort le prompt correct et vous fournissez ça à Gemini Pro…

Voici le prompt initial généré par ChatGPT (en terme de développement classique, on appelle cela un cahier des charges):

Tu es un expert AutoLISP et AutoCAD®.

Écris un programme AutoLISP entièrement fonctionnel pour AutoCAD® qui crée automatiquement un CALENDRIER PERPÉTUEL sous forme de TABLEAU AutoCAD®.

Contraintes et spécifications obligatoires

1. Structure générale du tableau

  • Le calendrier doit être créé avec la commande AutoCAD® TABLE via AutoLISP.
  • Le tableau doit comporter 12 colonnes correspondant aux mois de l’année.
  • L’ordre des colonnes doit être : janvier, février, mars, avril, mai, juin, juillet, août, septembre, octobre, novembre, décembre.
  • Les noms des mois doivent être écrits en français, sans abréviation.

2. Lignes du tableau

  • Les lignes représentent les jours de la semaine, dans cet ordre exact :
    • lundi
    • mardi
    • mercredi
    • jeudi
    • vendredi
    • samedi
    • dimanche
  • Ce bloc de 7 lignes doit être répété verticalement autant de fois que nécessaire pour couvrir le nombre maximal de semaines possibles dans une année (calendrier perpétuel).
  • Prévoir suffisamment de lignes pour couvrir tous les cas possibles (années commençant n’importe quel jour).

3. Contenu des cellules

  • À chaque intersection ligne/colonne, inscrire le numéro du jour du mois correspondant.
  • Le calendrier doit être perpétuel : le calcul des jours doit fonctionner pour n’importe quelle année.
  • Le programme doit demander à l’utilisateur de saisir l’année (ex : 2024).
  • Le calcul des jours doit respecter :
    • les années bissextiles
    • le nombre réel de jours par mois
    • le jour réel de début de l’année (lundi → dimanche)

4. Aspects techniques

  • Le code doit être entièrement en AutoLISP (compatible AutoCAD® standard).
  • Utiliser des fonctions claires et bien structurées.
  • Ajouter des commentaires explicatifs dans le code.
  • Ne pas utiliser de bibliothèques externes.
  • Le tableau doit être inséré à un point demandé à l’utilisateur.

5. Résultat attendu

  • À l’exécution de la commande AutoLISP, l’utilisateur :
    • saisit une année
    • clique un point d’insertion
  • AutoCAD® génère automatiquement le tableau du calendrier perpétuel complet pour l’année choisie.

  1. Le mode Canvas de Gemini est une interface de travail conçue pour aller au-delà d’un simple échange de messages. C’est un espace de travail séparé (souvent une fenêtre qui s’ouvre à droite de la discussion) dédié à la création et à l’édition de contenu long. ↩︎

1 « J'aime »