3

I'm drawing a row of 3 to ~10 consecutive days with arbitrary starting date. I need to draw a line from the first box (above) to the last one but if a month shift happens that line must stop to -last and a new line (with new color) must start from yyyy-mm-01 up to the last day of the row. The code must take care of month name placement too.

here is how i want it looks like : enter image description here

here is my mwe:

\documentclass{beamer}

\mode<presentation> {\usetheme{metropolis}}

\newlength{\slw}\setlength{\slw}{160mm}
\newlength{\slh}\setlength{\slh}{90mm}
\geometry{verbose,papersize={\slw,\slh},hmargin=5mm}

\usepackage{fontsize,fix-cm,verbatim}
\usepackage{tikz}
\usetikzlibrary{calc,calendar}

\tikzset{
  my calendar/.style={
    day list right,
    day code={
      \node (daybox) [anchor=base, font=\Large,
        text width=18mm-2*(\pgfkeysvalueof{/pgf/inner xsep}),
        align=right, text depth=.25ex, text height = 15mm, rounded corners=3mm, draw,
        very thick] {\tikzdaytext};,
      \node at (daybox) [anchor=center, text depth=.25ex, text height=1.5ex]
        {\textbf{\daytext{\pgfcalendarcurrentweekday}}};
%\draw node[anchor = west, gray]{\pgfcalendarweekdayname{\pgfcalendarcurrentweekday}
    },
    month label above right,
    month xshift=2mm, month yshift=0mm,
    day xshift=18mm+2mm,
    day yshift=15mm+2mm,
  },
  use shortest/.style={
    day text=\number\%d0\relax},
}

\def\pgfcalendarmonthname#1{%
  \ifcase#1\or
  janvier\or février\or mars\or avril\or mai\or juin\or
  juillet\or août\or septembre\or octobre\or décembre\fi}


\def\daytext#1{%
  \ifcase#1
  lundi\or mardi\or mercredi\or jeudi\or
  vendredi\or samedi\or dimanche\fi}

\begin{document}
\begin{frame}{calendrier de la semaine}
  \begin{tikzpicture}
    \calendar 
      [my calendar, use shortest] (moncal) [
   dates=\year-\month-\day+7 to \year-\month-\day+13];
  \end{tikzpicture}

\end{frame}
\end{document}

1 Answer 1

4

Let's give each daybox an alias: today. The first daybox of the calendar and/or the recent first day of the month gets the alias day1. (That way, we're not dependent on \pgfcalendarsuggestedname.)

At the end of the calendar (equals=\pgfcalendarendiso) and/or at the end of a month (end of month=1) a line is drawn between day1 and today. (And with the next day, the name day1 gets overwritten by a new daybox for the next line to be drawn.)

This line is setup in such a way that it draws a line from somewhere around day1.north west to today.north east while adding an every month node to it. In addition, the key month line \pgfcalendarcurrentmonth is tried. You can define them manually: month line 01/.style={green} or via the month colors key which takes a list of colors and assigns them to the appropriate month line XX keys.


In the code below, the day number and the weekday name is implemented as a label to just a rectangular node without any text. This allows placing these labels in the corners and using the inner seps to adjust the padding to the box. No need to mess around with text height and depth now.

With the node contents key even the text of the labels can be made easily customizable by PGFKeys.


Unfortunately, the translator interface between PGFCalendar and the selected language is broken in beamer, we'll be using your custom redefinitions of \pgfcalendarmonthname and \pgfcalendarweekdayname. Unless you want calendars in different language, this should be the easiest approach.

Since you want to use polyglossia, I've added it here with the option french but there's no interaction with the PGFCalendar module anymore, anyway. But it's a good idea to include this anyway since we might find incompatibilities with it. The babel TikZ library is not necessary here.

Code

% !TeX TS-program = lualatex
\documentclass[french]{beamer}
\usepackage{polyglossia}
\mode<presentation> {\usetheme{metropolis}}

\newlength{\slw}\setlength{\slw}{160mm}
\newlength{\slh}\setlength{\slh}{90mm}
\geometry{verbose,papersize={\slw,\slh},hmargin=5mm}

\usepackage{fontsize, fix-cm, verbatim}
\usepackage{tikz}
\usetikzlibrary{calendar}

\definecolor{oct}{RGB}{128,128,0}
\definecolor{nov}{RGB}{255,0,255}
\tikzset{
  my calendar/.style={
    day list right,
    % Every day ist just a day box.
    % Its size should be in relation to day xshift or vice versa
    day code={\node[every daybox]{};},
    every daybox/.style={
      minimum width=18mm,
      minimum height=.25ex+15mm+.6666em,
      draw, very thick, rounded corners=3mm,
      name=\pgfcalendarsuggestedname,
      alias=today,
      label={[every day]\tikzdaytext},
      label={[every weekday]north west:\%wt},
    },% the day and the weekday are labels in relation to that daybox
    every day/.style={
      label position=south east, anchor=south east, node font=\Large,
      inner sep=+.5em},
    every weekday/.style={
      label position=north west, anchor=north west, node font=\bfseries,
      inner ysep=+.5em, inner xsep=+.3em},
    every month/.style={at end, above left, inner xsep=+0pt},
    month xshift=2mm,  month yshift=0mm,
    day xshift=18mm+2mm, day yshift=15mm+2mm,
    month line/.style={
      draw, line cap=round, line width=1ex,
      month line \pgfcalendarcurrentmonth/.try,
      to path={([shift={(1ex,1.5ex)}]\tikztostart.north west)
            -- ([shift={(-1ex,1.5ex)}]\tikztotarget.north east) \tikztonodes},
      every to/.append style={edge node={node[every month]{\%mt}}},
    },
    execute at begin day scope={%
      % if it's the first day of the calendar or the first day of the month:
      % remember that daybox as day1
      \ifdate{equals=\pgfcalendarbeginiso}{% first day of calendar?
        \tikzset{every daybox/.append style={alias=day1}}%
      }{%
        \ifdate{day of month=1}{% first day of month?
          \tikzset{every daybox/.append style={alias=day1}}%
        }{}%
      }%
    },
    execute after day scope={%
      % if it's the last day of a month or the last day of the calendar:
      % draw a line to day1
      \ifdate{end of month=1}{% last day of month?
        \draw[month line] (day1) to (today);
      }{%
        \ifdate{equals=\pgfcalendarendiso}{% or even last day of calendar?
          \draw[month line] (day1) to (today);
        }{}%
      }%
    }
  },
  use shortest/.style={day text=\number\%d0\relax},
  %%%
  month colors/.style={
    /utils/exec=\def\pgfmathcounter{0},
    @month colors/.list={#1}},
  @month colors/.code={%
    \edef\pgfmathcounter{\ifnum\pgfinteval{\pgfmathcounter+1}<10 0\fi\pgfinteval{\pgfmathcounter+1}}%
    \tikzset{month line \pgfmathcounter/.append style={color=#1}}},
 }

\renewcommand*\pgfcalendarmonthname[1]{%
  \ifcase#1\or janvier\or février\or mars\or avril\or mai\or juin\or
               juillet\or août\or septembre\or octobre\or novembre\or décembre\fi}
\renewcommand*\pgfcalendarweekdayname[1]{%
  \ifcase#1 lundi\or mardi\or mercredi\or
            jeudi\or vendredi\or samedi\or dimanche\fi}

\begin{document}
\begin{frame}{calendrier de la semaine}
\begin{tikzpicture}[month colors={,,,,,,,,,oct,nov,}]
  \calendar (moncal) [my calendar, use shortest, dates=2023-10-31 to 2023-10-31+6];
\end{tikzpicture}
\end{frame}
\end{document}

Output

enter image description here

9
  • The translations should come automatic but with beamer we apparently need \translate. Commented Oct 24, 2023 at 14:38
  • Didn't realize the second month name is at the left end. Will need to adjust this in a future update. Commented Oct 24, 2023 at 23:08
  • it's fine on the right. I have not tested the code yet. Commented Oct 25, 2023 at 8:50
  • I've never used babel as it was recommended to use polyglossia for devanagari script. Can you change? when you say that the daybox gets the alias day1, actually you meant that You give that alias to it, similarly to today. I mention it because it led me to some confusion. Commented Oct 25, 2023 at 16:21
  • @user1850133 I've changed the code to use polyglossia and dropped the translation aspect, it's not working properly with beamer anyway. Yes, I give each daybox node an alias today so I can use that name to always reference the last daybox. And the absolute first daybox and then every first of the month is given the alias day1. Commented Oct 25, 2023 at 16:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .