calendrier python latex

Créer un calendrier à l’aide de Python et de LaTeX

  • Dernière modification de la publication :4 juin 2022
  • Temps de lecture :9 min de lecture
  • Commentaires de la publication :0 commentaire

Loading

Créer un calendrier à l’aide de Python et de LaTeX (le langage de programmation) n’est pas si compliqué que cela quand on se penche sur la question sérieusement.

C’est un peu long, mais pas compliqué.

Créer un calendrier à l’aide de Python et LaTeX: quel module choisir ?

Il existe un module Python dédié aux calendriers: le bien nommé calendar.

La première fois que je m’y suis penché, c’est à dire ce jour, j’ai trouvé la documentation bien merdique… Aucun exemple n’est donné, et je n’aime pas ça car je suis obligé de lire tout ce qui est écrit, et j’étais pressé! Donc ça, c’est un mauvais point, mais peu importe!

Comme je suis motivé, je me mets à lire et m’aperçois au final que je n’ai pas à lire beaucoup. En effet, itermonthdates semble convenir à mes attentes. C’est un itérateur que l’on peut parcourir.

Créer un calendrier à l’aide de Python et LaTeX: la structure du fichier tex

Il fallait avant tout que je réfléchisse à l’apparence du calendrier que je voulais. Un truc tout simple: une grille avec le mois affiché dessous (par exemple) et les dates dans chaque coin de case, en bas à droite (par exemple).

calendrier python latex

C’est assez rudimentaire, mais c’est suffisant pour avoir une base sur laquelle travailler.

Créer un calendrier à l’aide de Python et LaTeX: la fonction Python

Je vais générer un fichier \(\LaTeX\) puis le compiler pour obtenir un PDF.

Je vais utiliser TiKZ pour la solution graphique car je suis plus à l’aise avec celle-ci qu’avec PSTricks par exemple.

Je voudrais une fonction de la forme:

>>> calendarTEX(6,2022)

Bien entendu, il faudra inclure des options pour customiser ce calendrier.

Alors voilà ce que cela donne:

from calendar import Calendar
import os.path

def calendarTEX( current_month , current_year , 
                        hauteur     = '2cm' , 
                        largeur     = '3cm' ,
                        calendarGridStyle = 'line width = 0.5pt , draw = black',
                        calendarBgStyle = 'fill = white',
                        monthStyle  = 'text = black , font = \\Huge\\bfseries', 
                        dayStyle    = 'text = black , font = \\Large\\bfseries', 
                        dayInStyle  = 'text = black , above left', 
                        dayOutStyle = 'text = gray , above left',
                        preambuleTEX= '',
                        out        = True, 
                        name        = None):
    """
    current_month : mois souhaité
    current_year  : année souhaitée
    options : dictionnaire contenant :
                            ....... (hauteur)     la hauteur des cases (par défaut : 2cm)
                            ....... (largeur)     la largeur des cases (par défaut : 3cm)
                            ....... (calendarGridStyle) le style TiKZ de la grille (traits)
                            ....... (calendarBgStyle)   le style TiKZ du fond
                            ....... (monthStyle)  le style TiKZ du mois écris en bas
                            ....... (dayStyle)    le style TiKZ dans lequel doivent être écris les jours en en-tête des colonnes
                            ....... (dayInStyle)  le style TiKZ de la date du jour
                            ....... (dayOutStyle) le style TiKZ de la date du jour si le jour est en-dehors du mois (gris par défaut)
                            ....... (preambuleTEX) l'éventuel préambule au fichier LaTeX
                            ....... (out)         (True|False) pour savoir s'il faut générer un PDF/fichier TEX
                            ....... (name)        le nom du fichier s'il faut en générer un
    """
    C = Calendar()
    nb_lines = sum(1 for _ in C.itermonthdates(current_year,current_month) ) // 7
    days = [ 'Lundi' , 'Mardi' , 'Mercredi' , 'Jeudi' , 'Vendredi' , 'Samedi' , 'Dimanche' ]
    months = [ 'janvier' , 'février' , 'mars' , 'avril' , 'mai' , 'juin' , 'juillet', 'août' , 'septembre' , 'octobre' , 'novembre' , 'décembre' ]
    
    tex =  "\\documentclass{standalone}\n"
    tex += "\\usepackage{tikz}\n"
    tex += "\\usetikzlibrary{calc}\n"
    tex += "\\newlength{\\hauteur}\n"
    tex += preambuleTEX
    tex += "\\newlength{\\largeur}\n"
    tex += "\\setlength{\\hauteur}{"+hauteur+"}\n"
    tex += "\\setlength{\\largeur}{"+largeur+"}\n"
    tex += "\\begin{document}\n"
    tex += "\\tikzset{month/.style = { "+monthStyle+"}}%\n"
    tex += "\\tikzset{day/.style   = { "+dayStyle+"}}%\n"
    tex += "\\tikzset{calendarGrid/.style   = { "+calendarGridStyle+"}}%\n"
    tex += "\\tikzset{calendarBG/.style   = { "+calendarBgStyle+"}}%\n"
    tex += "\\begin{tikzpicture}\n"
    tex += "\\node[month] at (10.5,-1) {"+months[current_month-1].upper()+" "+ str(current_year) +"};\n"
    tex += f"\\filldraw[calendarBG] (0,0) rectangle (7*\\largeur,{nb_lines}*\\hauteur);\n"
    tex += f"\\filldraw[calendarGrid] (0,0) grid[xstep = \\largeur , ystep = \\hauteur] (7*\\largeur,{nb_lines}*\\hauteur);\n"
    for d in days:
        tex += "\\node[day] at ({\\largeur/2+\\largeur*"+str(days.index(d))+"},{"+str(nb_lines)+"*\\hauteur+0.5cm}) {"+d+"};\n"

    column , line = 1, nb_lines-1

    for d in C.itermonthdates(current_year,current_month):
        if d.month != current_month:
            styleday = dayOutStyle
        else:
            styleday = dayInStyle
            
        tex += "\\node["+styleday+"] at (\\largeur*" + str(column) + " , \\hauteur*" + str(line) + " ) {"+str(d.day)+"};\n"
        
        column += 1
        if column == 8:
            column = 1
            line -= 1

    tex += "\\end{tikzpicture}\n"
    tex += "\\end{document}"
    
    if out:
        if name == None:
            file = "calendar-"+str(current_year)+str(current_month)+".tex"
        else:
            file = name + ".tex"
            
        if os.path.exists(file):
            os.remove(file)

        fichier = open(file , "x") # "x" pour la création et l'écriture
        fichier.write(tex)
        fichier.close()
        
        instructions = "pdflatex " + file
        os.system(instructions)

        readpdf = "START " + file[:-4] + ".pdf"
        os.system(readpdf)
    else:
        return tex

Les options de la fonction sont:

def calendarTEX( current_month , current_year , 
                        hauteur     = '2cm' , 
                        largeur     = '3cm' ,
                        calendarGridStyle = 'line width = 0.5pt , draw = black',
                        calendarBgStyle = 'fill = white',
                        monthStyle  = 'text = black , font = \\Huge\\bfseries', 
                        dayStyle    = 'text = black , font = \\Large\\bfseries', 
                        dayInStyle  = 'text = black , above left', 
                        dayOutStyle = 'text = gray , above left',
                        preambuleTEX= '',
                        out        = True, 
                        name        = None):
    """
    current_month : mois souhaité
    current_year  : année souhaitée
    options : dictionnaire contenant :
                            ....... (hauteur)     la hauteur des cases (par défaut : 2cm)
                            ....... (largeur)     la largeur des cases (par défaut : 3cm)
                            ....... (calendarGridStyle) le style TiKZ de la grille (traits)
                            ....... (calendarBgStyle)   le style TiKZ du fond
                            ....... (monthStyle)  le style TiKZ du mois écris en bas
                            ....... (dayStyle)    le style TiKZ dans lequel doivent être écris les jours en en-tête des colonnes
                            ....... (dayInStyle)  le style TiKZ de la date du jour
                            ....... (dayOutStyle) le style TiKZ de la date du jour si le jour est en-dehors du mois (gris par défaut)
                            ....... (preambuleTEX) l'éventuel préambule au fichier LaTeX
                            ....... (out)         (True|False) pour savoir s'il faut générer un PDF/fichier TEX
                            ....... (name)        le nom du fichier s'il faut en générer un
    """

Un exemple customisé

calendarTEX(7 , 2022 ,
            preambuleTEX = "\\usepackage{emerald}\\usetikzlibrary{fadings}\n",
            calendarGridStyle = 'line width=1pt, draw = blue, path fading = south',
            calendarBgStyle = 'line width=0pt,fill=white,draw=white',
            monthStyle  = 'text = blue!50!black , font = \\ECFJD\\Huge\\bfseries, rounded corners = 3mm, draw = blue!50!black , line width = 3pt, fill = blue!20',
            dayStyle    = 'text = green!50!black , font = \\ECFJD\\Large , rounded corners = 2mm , draw = green!50!black , fill = green!20',
            dayInStyle  = 'text = orange , above left , font = \\ECFJD',
            dayOutStyle = 'text = gray!50!orange , above left , opacity = 0.5 , font = \\ECFJD')
calendrier python tikz latex
calendarTEX(7 , 2022 ,
            preambuleTEX = "\\usepackage{emerald}\\usetikzlibrary{fadings}\n\\tikzfading[name=fade right, left color=transparent!0, right color=transparent!100]",
            calendarBgStyle = 'blue!20, path fading = fade right',
            calendarGridStyle = 'blue!50!black, line width=1pt',
            monthStyle  = 'text = blue!50!black , font = \\ECFJD\\Huge\\bfseries, rounded corners = 3mm, draw = blue!50!black , line width = 3pt, fill = blue!20, inner sep = 3mm',
            dayStyle    = 'text = green!50!black , font = \\ECFJD\\Large , rounded corners = 2mm , draw = green!50!black , fill = green!20',
            dayInStyle  = 'text = orange , above left , font = \\ECFJD',
            dayOutStyle = 'text = gray!50!orange , above left , opacity = 0.5 , font = \\ECFJD')
calendrier python latex tikz
0 0 votes
Évaluation de l'article
S’abonner
Notification pour
guest
0 Commentaires
Commentaires en ligne
Afficher tous les commentaires