13

I am trying to create my own A5 pages with weekly calendar format similar to the standard Moleskine or Leuchtturm weekly calendars (see left part of attached image) in order to make my own calendar for my A5 Atoma notebook but with birthdays of friends added automatically.

System: Windows, MiKTeX

It seems, that it should be possible with TikZ (http://www.texample.net/tikz/examples/feature/calendar-library/), however, I could not find an example matching my desired style.

Do you have any hints, tips, suggestions how to start?

Thanks in advance, Michael

wanted calendar layout

4
  • Welcome to TeX.SX! You can have a look at our starter guide to familiarize yourself further with our format. Your question is interesting, and the issue is challenging... but as it is, your question leaves all the effort to our community, even typing the essentials of a TeX document such as \documentclass{}...\begin{document} etc.
    – ebosi
    Oct 10, 2016 at 13:14
  • 2
    You could improve your question by showing what you've tried by adding a minimal working example (MWE) that more users can copy/paste onto their systems to work on. This will also lead to one (or many) more narrowed question(s), that is easier (and thus more likely) to be solved !
    – ebosi
    Oct 10, 2016 at 13:15
  • Dear Ebo, thanks for your valuable comments and sorry for my late reply (I have been on vacation for the last three weeks). I was aware, that my question is lacking any own effort from my side, my hope was, that there maybe was a anybody who did it already. Apparently, this is not the case, so I will try to add a MWE as soon as possible. As the self made calendar was so far only a rough spare time idea, this will probably take some time as I am not very familiar wit LaTeX, and not at all with tikz. Anyhow, thanks again for your comments and yes, now it is up to me to add some MWE here...
    – mbb
    Oct 31, 2016 at 10:18
  • Note that I've updated my answer.
    – ebosi
    Jan 2, 2017 at 14:28

1 Answer 1

12

Disclaimer: This is not a fully functional solution (yet). It is intended to be updated.

Below is an answer that produces a PDF with one week per page, for one year, starting with the week containing January, 1st. However, it does not implement (yet) the automatic adding of kin's birthdays. It does not support leap years neither.

Working principle
Each week is generated as a single tikzpicture. The body of the document is simply a loop calling the macro that creates such tikzpicture as many times as needed. (Note that the option tikz given to \documentclass{standalone} creates a new page for each picture.)

As input to the code, you manually set:

  • the year you want to generate the calendar for,
  • the day of January, 1st (Monday, or Tuesday, etc.)
  • how many weeks contains this year,
  • and what is ISO week's date of January 1st.

Then it is all about counters, as detailed in code below.

Code

\documentclass[tikz]{standalone}% Does not support leap years.

%% Load needed packages
\usepackage{lmodern}
\usepackage{tikz}
    \usetikzlibrary{positioning}
\usepackage{ifthen}

%% Create needed conters  
    \newcounter{ThisYear}
    \newcounter{NewYearsDay}
    \newcounter{NewYearsWeek}
    \newcounter{NumberOfWeeksThisYear}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% SET VARIABLES HERE                                         %

% Year number you want to generate the calendar for:
    \setcounter{ThisYear}{2017}             

% Which day is the January, 1st? (1 for Monday, 2 for Tuesday, etc.)
    \setcounter{NewYearsDay}{7}

% Which week does January, 1st belongs to?
    % Choose 52 (sometimes 53) or 1. Week 1 is not necessary the week of Jan, 1st; but *it is the week of Jan, 4th.*)
    \setcounter{NewYearsWeek}{52}

% How many weeks this year? (Choose 52 or 53, appropriately)
    \setcounter{NumberOfWeeksThisYear}{52}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Let's begin with messy stuff

    % If Jan, 1st is not on Week #1...
    \ifthenelse{\value{NewYearsWeek}>51}{
        \addtocounter{ThisYear}{-1}         % start calendar with the last week of the previous year
        \stepcounter{NumberOfWeeksThisYear} % increase amount of weeks to generate
    }{}

    % Following counter is the backbone of the calendar generation.
    \newcounter{NDOYnumber}             %% Nth Day Of the Year: 1 for Jan, 1st; 2 for Jan, 2nd; etc.
        % Set the first day of the calendar (i.e. Monday of the first generated week)
        \ifthenelse{\value{NewYearsDay}=1}{
            % Monday = Jan, 1st
            \setcounter{NDOYnumber}{1}
        }{
            % Monday belongs to previous year
            \setcounter{NDOYnumber}{367}
            \addtocounter{NDOYnumber}{-\value{NewYearsDay}}
        }

    % Store day's quantieme (1 for Jan, 1st & Feb, 1st, etc.; 17 for Jan, 17th, Feb, 17th, etc.)
    \newcounter{NDOYquantieme}

    % Store day's month number (1 for Jan, 2 for Feb, etc.)
    \newcounter{NDOYmonthnumber}

    % Internal counter
    \newcounter{tempNDOY}

    % Based on `NDOYnumber` value, compute month number and quantieme
    \newcommand{\NDOYtomonthnumber}{%
        \setcounter{tempNDOY}{\value{NDOYnumber}}%
        \setcounter{NDOYmonthnumber}{1}%
        \ifthenelse{\value{tempNDOY}<32}{%              %% JANUARY
            \setcounter{NDOYquantieme}{\value{tempNDOY}}%% Set January quantieme
        }{%
            \addtocounter{tempNDOY}{-31}%
            \stepcounter{NDOYmonthnumber}%                  %% FEBRUARY
            \ifthenelse{\value{tempNDOY}<29}{%
                \setcounter{NDOYquantieme}{\value{tempNDOY}}%
            }{%
                \addtocounter{tempNDOY}{-28}%
                \stepcounter{NDOYmonthnumber}%                  %% MARCH
                \ifthenelse{\value{tempNDOY}<32}{%
                    \setcounter{NDOYquantieme}{\value{tempNDOY}}%
                }{%
                    \addtocounter{tempNDOY}{-31}%
                    \stepcounter{NDOYmonthnumber}%                  %% APRIL
                    \ifthenelse{\value{tempNDOY}<31}{%
                        \setcounter{NDOYquantieme}{\value{tempNDOY}}%
                    }{%
                        \addtocounter{tempNDOY}{-30}%
                        \stepcounter{NDOYmonthnumber}%                  %% MAY
                        \ifthenelse{\value{tempNDOY}<32}{%
                            \setcounter{NDOYquantieme}{\value{tempNDOY}}%
                        }{%
                            \addtocounter{tempNDOY}{-31}%
                            \stepcounter{NDOYmonthnumber}%                  %% JUNE
                            \ifthenelse{\value{tempNDOY}<31}{%
                                \setcounter{NDOYquantieme}{\value{tempNDOY}}%
                            }{%
                                \addtocounter{tempNDOY}{-30}%
                                \stepcounter{NDOYmonthnumber}%                  %% JULY
                                \ifthenelse{\value{tempNDOY}<32}{%
                                    \setcounter{NDOYquantieme}{\value{tempNDOY}}%
                                }{%
                                    \addtocounter{tempNDOY}{-31}%
                                    \stepcounter{NDOYmonthnumber}%                  %% AUGUST
                                    \ifthenelse{\value{tempNDOY}<32}{%
                                        \setcounter{NDOYquantieme}{\value{tempNDOY}}%
                                    }{%
                                        \addtocounter{tempNDOY}{-31}%
                                        \stepcounter{NDOYmonthnumber}%                  %% SEPTEMBER
                                        \ifthenelse{\value{tempNDOY}<31}{%
                                            \setcounter{NDOYquantieme}{\value{tempNDOY}}%
                                        }{%
                                            \addtocounter{tempNDOY}{-30}%
                                            \stepcounter{NDOYmonthnumber}%                  %% OCTOBER
                                            \ifthenelse{\value{tempNDOY}<32}{%
                                                \setcounter{NDOYquantieme}{\value{tempNDOY}}%
                                            }{%
                                                \addtocounter{tempNDOY}{-31}%
                                                \stepcounter{NDOYmonthnumber}%                  %% NOVEMBER
                                                \ifthenelse{\value{tempNDOY}<31}{%
                                                    \setcounter{NDOYquantieme}{\value{tempNDOY}}%
                                                }{%
                                                    \addtocounter{tempNDOY}{-30}%
                                                    \stepcounter{NDOYmonthnumber}%                  %% DECEMBER
                                                    \setcounter{NDOYquantieme}{\value{tempNDOY}}%
        }}}}}}}}}}}%
    }

    % Based on previously computed `NDOYmonthnumber` value, return month name
    \newcommand{\NDOYtomonth}{%
        \foreach \monthnumber/\monthname in {1/Januar, 2/Februar, 3/März, 4/April, 5/Mai, 6/Juni, 7/Juli, 8/August, 9/September, 10/Oktober, 11/November, 12/Dezember}{%
            \ifthenelse{\value{NDOYmonthnumber}=\monthnumber}{\monthname}{}%
        }
    }

    % 'Smartly' increase `NDOYnumber` value (i.e. reset to 1 after December, 31st)
    \newcommand{\stepNDOY}{%
        \ifthenelse{\value{NDOYnumber}=365}{%
            \setcounter{NDOYnumber}{1}%
            \stepcounter{ThisYear}
        }{%
            \stepcounter{NDOYnumber}%
        }%
    }

    % Defines the `tikzpicture` used to print a week (i.e. calendar page)
    \newcommand{\printweek}[1]{% argument = \value{NDOYnumber}, i.e. Monday's day-of-the-year number
        \begin{tikzpicture}[%
            inner sep=3 pt,
            dayname/.style={%
                node font=\footnotesize,
            },
            daynumber/.style={%
                anchor=north east,
                node font=\normalsize\bfseries, 
            },
            xscale = 3,
            yscale=-1.5,% CAUTION: axis direction reversed!
        ]
        \NDOYtomonthnumber%(see below)
        \node (year_number) at (0,1) [anchor = south east, minimum height = 2em] {\theThisYear};    %prints year number
        \node [base right = 1em of year_number, anchor=base west, node font=\large] {\NDOYtomonth}; %prints month name

        %% Monday
        \NDOYtomonthnumber                                                              % compute and store which month and quantieme is this day, based on `NDOYnumber` value
        \node (monday_number) at (0,1) [daynumber] {\theNDOYquantieme};                 % prints quantieme
        \node [base right = 1em of monday_number, anchor=base west] [dayname] {Montag}; % prints day name
        \stepNDOY                                                                       % 'smartly' increases `NDOYnumber` value

        %% Tuesday
        \NDOYtomonthnumber  
        \node (tuesday_number) at (0,2) [daynumber] {\theNDOYquantieme};
        \node [base right = 1em of tuesday_number, anchor=base west] [dayname] {Dienstag};
        \stepNDOY

        %% Wednesday
        \NDOYtomonthnumber
        \node (wednesday_number) at (0,3) [daynumber] {\theNDOYquantieme};
        \node [base right = 1em of wednesday_number, anchor=base west] [dayname] {Mittwoch};
        \stepNDOY

        %% Thursday
        \NDOYtomonthnumber
        \node (thursday_number) at (0,4) [daynumber] {\theNDOYquantieme};
        \node [base right = 1em of thursday_number, anchor=base west] [dayname] {Donnerstag};
        \stepNDOY

        %% Friday
        \NDOYtomonthnumber
        \node (friday_number) at (0,5) [daynumber] {\theNDOYquantieme};
        \node [base right = 1em of friday_number, anchor=base west] [dayname] {Freitag};
        \stepNDOY

        %% Saturday
        \NDOYtomonthnumber
        \node (saturday_number) at (0,6) [daynumber] {\theNDOYquantieme};
        \node [base right = 1em of saturday_number, anchor=base west] [dayname] {Samstag};
        \stepNDOY

        %% Sunday
        \NDOYtomonthnumber
        \node (sunday_number) at (1,6) [daynumber] {\theNDOYquantieme};
        \node [base right = 1em of sunday_number, anchor=base west] [dayname] {Sonntag};
        \stepNDOY

        %% Draw lines
        \foreach \i in {1, 1.2, ..., 7}{%
            \draw [gray, thin] (2,\i) -- (4,\i);
        }

        \path (-0.35,0.25) -- (4,0.25);
        \foreach \i in {1,...,7} {%
            \draw (-0.35,\i) -- (4,\i);
        }
        \draw (2,1) -- (2,7);

        \end{tikzpicture}%
    }

\begin{document}
    \foreach \n in {1,...,\value{NumberOfWeeksThisYear}}{%
        \printweek{\value{NDOYnumber}}
    }
\end{document}

My code is pretty bulky. I'd warmly welcome streamlining suggestion!

Preview

enter image description here


First (preliminary) answer

Here is for now a rough TikZ structure for one week.

Note that due to yscale=-1, the origin of the picture is in the upper left corner (thus, an increased y coordinate means an "increased" day of the week - what is, imho, more intuitive.)

\documentclass{standalone}

\usepackage{lmodern}
\usepackage{tikz}
    \usetikzlibrary{positioning}

\begin{document}
    \begin{tikzpicture}[%
        inner sep=3 pt,
        dayname/.style={%
            node font=\footnotesize, 
        },
        daynumber/.style={%
            anchor=north east,
            node font=\normalsize\bfseries, 
        },
        xscale = 4,
        yscale=-1,
    ]

    \node (saturday_number) at (0,6) [daynumber] {14};
    \node [base right = 1em of saturday_number, anchor=base west] [dayname] {Samstag};

        \node (sunday_number) at (1,6) [daynumber] {15};
        \node [base right = 1em of sunday_number, anchor=base west] [dayname] {Sonntag};

    \node (friday_number) at (0,5) [daynumber] {13};
    \node [base right = 1em of friday_number, anchor=base west] [dayname] {Freitag};

    \node (thursday_number) at (0,4) [daynumber] {12};
    \node [base right = 1em of thursday_number, anchor=base west] [dayname] {Donnerstag};

    \node (wednesday_number) at (0,3) [daynumber] {11};
    \node [base right = 1em of wednesday_number, anchor=base west] [dayname] {Mittwoch};

    \node (tuesday_number) at (0,2) [daynumber] {10};
    \node [base right = 1em of tuesday_number, anchor=base west] [dayname] {Dienstag};

    \node (monday_number) at (0,1) [daynumber] {9};
    \node [base right = 1em of monday_number, anchor=base west] [dayname] {Montag};

    \node (year_number) at (0,1) [anchor = south east, minimum height = 2em] {2017};
    \node [base right = 1em of year_number, anchor=base west, node font=\large] {Januar};

    \foreach \i in {0,1,...,6} {%
        \draw (-0.25,\i) -- (2,\i);
    }

    \node (SW-corner) at (0,7) {};
    \end{tikzpicture}
\end{document}

enter image description here

Next steps:

  • Add friends birthday.
8
  • Wow.. This is so cool !! If you can , please proceed with the updates.
    – Tolaso
    Jan 2, 2017 at 10:04
  • 1
    @Tolaso: Answer updated (-;
    – ebosi
    Jan 2, 2017 at 14:28
  • This is perfect !! Keep up the good job.
    – Tolaso
    Jan 2, 2017 at 15:31
  • @ebo: Sorry for my very late reply, but this is awesome! Thanks a lot for your effort! Great work! I am already using it! Thanks!
    – mbb
    Apr 28, 2017 at 16:27
  • @MichaelBach Glad it helped! I still need to work on how to automatically import birthdays (or name days). I think using Lua might help, but I've not enough time now to poke my nose into it. Don't hesitate to comment again next fall to remember me to do it!
    – ebosi
    Apr 28, 2017 at 16:33

You must log in to answer this question.

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