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.
