2

I have been working based on this answer but I can't get the background to change for each month. The moon feature from this answer is also not working for this tikz. There are also some minor changes, so in summary:

  • A PNG tiled background should be different for each month.
  • Whole month border.
  • Include moon phases before the day number (if possible).
  • No vertical lines at the days of the week.
  • Horizontal lines for hand writing.
  • Rounded corner border around month - year.

Also, how do I change language?

Current and desired result

MWE:

\documentclass[a2paper,landscape]{article}
\usepackage[margin={1cm}, top= 6cm]{geometry}
\renewcommand*\thepage{}
\usepackage{mathabx}
%
\usepackage{etoolbox}
%
\usepackage{graphicx}
\usepackage{helvet}
\renewcommand{\familydefault}{\sfdefault}
\usepackage{tikz}
\usetikzlibrary{calendar}

\tikzset{
    every weekday/.style={
        anchor=south west,
        black,
        fill=white,
        font=\scshape\bfseries,
        name=weekday-\pgfcalendarcurrentmonth-\pgfcalendarcurrentweekday,
        node contents=\%wt
    },
    weekday above/.style={
        draw=none,
        if = {(day of month=1) [days={append after command={
                    node [at={(\tikzlastnode.north west)}, alias=@firstweekday, every weekday]}}]},
        if = {(day of month=2, day of month=3, day of month=4, day of month=5, day of month=6, day of month=7) [
            days={append after command={
                    node [at={(@firstweekday.south west-|\tikzlastnode.south west)}, every weekday]}}]}
    },
    wall calendar/.style={
        week list,
        weekday above,
        day text=,
        day and weekday/.style={
            draw,
            outer sep=+0pt,
            fill=white,
            line width=.12em,
            minimum width=\linewidth/7,
            minimum height=\textheight/7
        },
        day xshift=\linewidth/7,
        day yshift=\textheight/7, %altura da celula
        every day label/.style={
            anchor=north east,
            font=\Huge,
            node contents={\%d=},
            inner sep=.7em
        },
        every day/.append style={
            day and weekday,
            label={[every day label]north east:}
        },
        every weekday/.append style={
            day and weekday,
            inner xsep=0pt,
            minimum height=1.5em
        },
        moon code/.code={
            \edef\listmoons{#1}%
            \def\moons{}%
            \foreach \l in \listmoons {%
                \xappto\moons{if (equals = \pgfcalendarcurrentyear-\pgfcalendarcurrentmonth-\l) [day text=\noexpand\moon\%d-]}
            }%
            \tikzset{every day/.append style={\moons}}
        }
    }
}

\newcount\mooncounter
\def\moonreset{\global\mooncounter=-1\relax}
\moonreset

\def\moon{%
    \global\advance\mooncounter by 1\relax%
    \ifcase\mooncounter $\newmoon$%
    \or             $\rightmoon$%
    \or             $\fullmoon$%
    \or             $\leftmoon$\global\mooncounter=-1\relax%
    \fi%
}

\newcommand*{\listofmoons}[1]{%
    \edef\listmoons{#1}%
    \def\moons{}%
    \foreach \l in \listmoons {%
        \xappto\moons{if (equals = 2023-12-\l) [day text=\noexpand\moon\%d-]}
    }%
}

\begin{document}
    \sffamily\LARGE
    
    \centering
    \newcommand*\Year{2023}
    \moonreset
    \foreach \mon in {6,...,12}{% 1,...,12
        \listofmoons{2,6,7,8,9,12,27}
        {\par \fontsize{40}{50}\selectfont\bfseries  {\pgfcalendarmonthname{\mon}} - \Year \par}
        \vspace{2em}
        \tikz\calendar[
        dates=\Year-0\mon-01 to \Year-0\mon-last,
        wall calendar,
        moon code={2,6,7,8,9,12,27}
        ];
        \pagebreak
    }
\end{document}
2
  • 1
    The moon thingy doesn't work because the other answer doesn't use day text as it's supposed to be. Language needs babel, translate and calendar in this order, I believe, with the language as an option to the class. I would output the whole page as one TikZ picture which makes it much easier to control the vertical and horizontal spacing instead of using geometry. Do you have the dates for the moon phase in a different dataset? You will need to have a list of days per month (or a formula). Commented Jun 7, 2023 at 20:34
  • As for the moon, I was hoping to use something like this. minkukel.com/en/various/calculating-moon-phase. As for the TikZ picture, I tried that, and managed to get a background, but still the same for all months.
    – G. Bay
    Commented Jun 7, 2023 at 22:34

1 Answer 1

3

How it works

  • It's much easier (for me) to use TikZ to create the whole page instead of using geometry and such things.

  • A lot of dimensions are controlled via key values in the /cal namespace (see \calset), this includes

    • the page dimensions,
    • the borders (border top is the space between weekdays and the header)
    • the header dimensions (current you need to make sure it is wide enough to fit the longest head).
  • The background is done via layers at the end of the picture, a background for each month can be set by set background = {<month number>}{<TikZ styles>}.

    You can see two examples for 6 and 7.

  • Translations are provided by the babel package and implemented via the translator package (this is a feature of the calendar utility) which needs to be loaded before TikZ. (This is why I'm using multi=tikzpicture instead of tikz as a class option since otherwise standalone would load tikz before we have a change to load translator before.)

  • The language is given as a class option. Since you didn't specify the language I'm using ngerman for this example.

  • Since you don't want a background for the days of the week from the previous or next month, I'm using my ext.calendar-plus library to be able to use the conditionals and, week of month and calendar week of month (and their ' variants) to add another day in the appropriate places.

    This is taken from Full weeks in Tikz Calendar

  • No vertical lines between the weekdays is done by removing the draw option in every weekday and just draw a rectangle around them at the end.

Todo

  • Lines to write on.

  • What to do with months that have less than 6 weeks?

    Currently the height of the day boxes doesn't change like in TikZ / calendar: Set the height of a monthly calendar

    At the bottom of the page remains empty space which doesn't even have an extra area to write on.

  • Moon stuff. (It will be easier to provide the dates instead of calculating them, especially when we're thinking about time zones.)

Code

\documentclass[ngerman,multi=tikzpicture]{standalone}
\usepackage{babel, translator, tikz}
\usepackage{helvet}
\renewcommand{\familydefault}{\sfdefault}
\usetikzlibrary{backgrounds, ext.calendar-plus, patterns.meta}
\newcommand*\cvo[1]{\pgfkeysvalueof{/cal/#1}}
\newcommand*\calset{\pgfqkeys{/cal}}
\makeatletter
\tikzset{
  add day from week before/.default=, add day from week after/.default=,
  add day from week before/.code={%
    \begingroup % shift whole calendar 7 days in the past
      \advance\pgfcalendarcurrentjulian by -7
      \pgfcalendarjuliantodate{\pgfcalendarcurrentjulian}{\pgfcalendarcurrentyear}{\pgfcalendarcurrentmonth}{\pgfcalendarcurrentday}%
      \pgfcalendarjuliantoweekday{\pgfcalendarcurrentjulian}{\pgfutil@tempcntb}%
      \edef\pgfcalendarcurrentweekday{\the\pgfutil@tempcntb}%
      \pgfcalendarjulianyeartoweek{\pgfcalendarcurrentjulian}{\pgfcalendarcurrentyear}{\pgfutil@tempcntb}%
      \edef\pgfcalendarcurrentweek{\ifnum\pgfutil@tempcntb<10 0\fi\the\pgfutil@tempcntb}%
      \pgftransformyshift{\pgfkeysvalueof{/tikz/day yshift}}%
      \tikzset{every day from week before/.try,#1}%
      \tikzdaycode
    \endgroup},
  add day from week after/.code={%
    \begingroup % shift whole calendar 7 days in the future
      \advance\pgfcalendarcurrentjulian by +7
      \pgfcalendarjuliantodate{\pgfcalendarcurrentjulian}{\pgfcalendarcurrentyear}{\pgfcalendarcurrentmonth}{\pgfcalendarcurrentday}%
      \pgfcalendarjuliantoweekday{\pgfcalendarcurrentjulian}{\pgfutil@tempcntb}%
      \edef\pgfcalendarcurrentweekday{\the\pgfutil@tempcntb}%
      \pgfcalendarjulianyeartoweek{\pgfcalendarcurrentjulian}{\pgfcalendarcurrentyear}{\pgfutil@tempcntb}%
      \edef\pgfcalendarcurrentweek{\ifnum\pgfutil@tempcntb<10 0\fi\the\pgfutil@tempcntb}%
      \pgftransformyshift{-(\pgfkeysvalueof{/tikz/day yshift})}%
      \tikzset{every day from week after/.try,#1}%
      \tikzdaycode
    \endgroup}}
\makeatother
\calset{
  page width/.initial =594mm,
  page height/.initial=420mm,
  border   left/.initial=1cm,
  border  right/.initial=1cm,
  border    top/.initial=1cm,
  border bottom/.initial=1cm,
  weekday height/.initial=1.5em,
  header height/.initial=10em,
  header width/.initial=15em,
  header rounded corners radius/.initial=2em,
  height for calendar/.initial=(\cvo{page height}-\cvo{border top}-\cvo{border bottom}-\cvo{weekday height}-\cvo{header height}),
  @initialize backgrounds/.style={
    /cal/background #1/.style={
      execute at end picture={
        \scoped[on background layer]
          \path[/cal/every background/.try,/cal/background #1/.try]
            ([xshift=(\cvo{border right}),yshift=-(\cvo{header rounded corners radius})]@header.north-|@weekday-6.east)
            rectangle ++ ({-(\cvo{page width})},{-(\cvo{page height})});}}},
  @initialize backgrounds/.list={1,...,12},
  set background/.style 2 args={/cal/background #1/.append style={#2}},
  set background={6}{fill=gray},
  set background={7}{
    preaction={fill=orange!25},
    pattern={Lines[angle=45, distance=5mm, line width=.5mm]},
    pattern color=black
  },
}
\tikzset{
  weekday above/.style={
    if = {(day of month=1) [days={append after command={
                node [at={(\tikzlastnode.north west)}, alias=@firstweekday, every weekday]}}]},
    if = {(day of month=2, day of month=3, day of month=4, day of month=5, day of month=6, day of month=7) [
        days={append after command={
                node [at={(@firstweekday.south west-|\tikzlastnode.south west)}, every weekday]}}]}
  },
  wall calendar/.style={
    week list,
    weekday above,
    header text/.store in=\tikzheadertext,
    day code={\node[every day]{};}, % no \tikzdaytext here
    every head/.style={
      minimum width=\cvo{header width},
      minimum height=\cvo{header height}+\cvo{header rounded corners radius},
      rounded corners=\cvo{header rounded corners radius},
      fill=white,
      label={[anchor=south,every head text]below:\tikzheadertext},
      name=@header,
      overlay,
      draw = orange,
      line width=1mm,
    },
    every head text/.style={
      font = \Huge\bfseries,
      above = .5*(\cvo{header rounded corners radius}),
      text depth=+0pt,
    },
    header text=\%mt -- \%y0,
    day and weekday/.style={
      draw,
      outer sep=+0pt,
      fill=white,
      text=black,
      minimum width=(\cvo{page width}-\cvo{border left}-\cvo{border right})/7,
    },
    every day/.style={
      day and weekday,
      name=day-\pgfcalendarcurrentday,
      alias=@day,
      minimum height=\cvo{height for calendar}/6,
      label={[every day label]:},
    },
    day xshift=(\cvo{page width}-\cvo{border left}-\cvo{border right})/7,
    day yshift=\cvo{height for calendar}/6,
    every weekday/.style={
      day and weekday,
      anchor=south west,
      draw=none,
      inner xsep=0pt,
      font=\scshape\bfseries,
      minimum height=\cvo{weekday height},
      name=@weekday-\pgfcalendarcurrentweekday,
      node contents=\%wt,
      style/.expanded={
        \ifnum\pgfcalendarcurrentweekday=3
          label={[above=\cvo{border top},every head]above:}\fi},
    },
    every day label/.style={
      anchor=north east,
      label position=north east,
      font=\Huge,
      node contents={\tikzdaytext},
      inner sep=.7em
    },
  }
}
\newcommand*\Year{2023}
\begin{document}
\sffamily\LARGE
\foreach \mon in {6,...,12}{% 1,...,12
  \tikz[
    /cal/background \mon/.try,
    execute at end picture={\draw[overlay] (@weekday-0.south west) rectangle (@weekday-6.north east);}]
    \calendar[
      wall calendar,
      if = {(and = {week of month = 1, calendar week of month = 2}) [add day from week before={day text=}]},
      if = {(and = {week of month'= 1, calendar week of month'= 2}) [add day from week after ={day text=}]},
      dates=\Year-0\mon-01 to \Year-0\mon-last,
    ];
}
\end{document}

Output

enter image description here enter image description here

2
  • Fantastic! I realized I was running tex 2021, so ext.calendar-plus was not working. However I can't seem to change the background to a image, the includegraphics generate error. I am sure it must be simple but i'm kind of lost in tikz long manual.
    – G. Bay
    Commented Jun 12, 2023 at 16:13
  • I have manage to get the result using your pgfsetupimageaspattern , found here tex.stackexchange.com/questions/103980/…
    – G. Bay
    Commented Jun 21, 2023 at 17:03

You must log in to answer this question.

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