Exercise 23: Calendar for 2014 (Solution)
This is a solution to Exercise 23. I suggest you use a better colour scheme.\documentclass[a4paper,landscape,12pt]{article} \usepackage[margin=1cm]{geometry} \usepackage{etoolbox} \usepackage{tikz} \usepackage{pgfcalendar} \usetikzlibrary{shapes.multipart} \pagestyle{empty} \newcount\rowcount \newcount\julianday \newcommand*{\addevent}[2]{% \ifcsdef{cal-#1} {% already defined so append info \csappto{cal-#1}{\newline #2}% }% {% not defined \csdef{cal-#1}{#2}% } } \newlength\dayinnersep \setlength\dayinnersep{4pt} \newcommand*{\daynode}[2]{% #1\nodepart{two}\parbox[t][\dayheight]{\daywidth}{\raggedright\mbox{}#2}} \newlength\daywidth \newlength\dayheight \newlength\dayyunit \newcommand*{\calendarmonth}[2]{% \setlength{\daywidth}{0.12\textwidth}% \edef\dayxunit{\the\daywidth}% \addtolength{\daywidth}{-2\dayinnersep}% \setlength{\dayheight}{0.1\textheight}% \settoheight{\dayyunit}{% \tikz{\node[rectangle split,rectangle split parts=2] {\daynode{0}{}};}}% \addtolength{\dayyunit}{2pt}% \fbox{% \rowcount=1\relax \let\%\pgfcalendarshorthand \begin{tikzpicture}[x=\dayxunit,y=\dayyunit,every node/.style={inner sep=\dayinnersep}] % display the month name at the top \path (3,0.25) node {\Huge\bfseries\itshape \pgfcalendarmonthname{#2}}; \begin{scope}[every node/.style={rectangle,fill=green!5,minimum width=\dayxunit,outer sep=0pt}] \foreach \x in {0,...,6} { \path (\x,-0.25) node {\pgfcalendarweekdayshortname{\x}}; } \end{scope} \pgfcalendar{cal}{#1-#2-01}{#1-#2-last} {% % Is this the first day of the month? \ifnum\pgfcalendarcurrentday=1\relax % Fill in days from previous month if this isn't a Monday \ifdate{Monday}{} { % Get last day of previous month \julianday = \pgfcalendarcurrentjulian\relax \advance\julianday by -\pgfcalendarcurrentweekday\relax \foreach \x in {0,...,\numexpr\pgfcalendarcurrentweekday-1} { \pgfcalendarjuliantodate{\julianday}{\theyear}{\themonth}{\theday} \path (\x,-1) node [ rectangle split, rectangle split parts=2, draw=gray, text=gray] {% \daynode{\number\theday}{}% }; \global\advance\julianday by 1\relax } } \fi \def\thebackground{magenta!4}% \ifcsdef{\pgfcalendarsuggestedname}% {% \def\thecontents{\csuse{\pgfcalendarsuggestedname}}% \def\thebackground{black!4}% }% {% \def\thecontents{\mbox{}}% \ifdate{weekend}{\def\thebackground{black!4}}{}% }% \path (\pgfcalendarcurrentweekday,-\rowcount) node [ rectangle split, rectangle split parts=2, rectangle split part fill={cyan!20,\thebackground}, draw] {% \daynode{\%d-}{\small\thecontents}% }; \ifdate{Sunday}{\global\advance\rowcount by 1}{}% \xdef\lastjulianday{\number\pgfcalendarcurrentjulian} \xdef\lastweekday{\number\pgfcalendarcurrentweekday} }% \ifnum\lastweekday < 6\relax \julianday = \lastjulianday\relax \edef\lastweekday{\number\numexpr\lastweekday+1} \foreach \x in {\lastweekday,...,6} { \global\advance\julianday by 1\relax \pgfcalendarjuliantodate{\julianday}{\theyear}{\themonth}{\theday} \path (\x,-\rowcount) node [ rectangle split, rectangle split parts=2, draw=gray, text=gray] {% \daynode{\number\theday}{}% }; } \fi \end{tikzpicture}% } } \addevent{2014-01-01}{New Year's Day} \addevent{2014-05-05}{Early May BH} \addevent{2014-05-26}{Spring BH} \addevent{2014-04-21}{Easter Monday BH} \addevent{2014-08-25}{Summer BH} \addevent{2014-12-25}{Christmas Day} \addevent{2014-12-26}{Boxing Day} \begin{document} \centering \foreach \thismonth in {1,...,12} { \calendarmonth{2014}{\thismonth} \newpage } \end{document}
Download calendar2014.tex or calendar2014.pdf.