The following example creates a Page-a-Day calendar with the corresponding entries read from an ASCII text file (actually CSV). The construction of the CSV file uses standard Excel or OpenOffice techniques, while the datatool
package provides reading and manipulating of record entries.
page-calendar.csv
"DayNum","Date","Year","MonthNum","Month","Mnth","Day","WeekdayNum","Weekday","Wkday","Saying"
1,2012-01-01,2012,1,"January","Jan",1,1,"Sunday","Sun","Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae, felis. Curabitur dictum gravida mauris."
2,2012-02-13,2012,2,"February","Feb",13,2,"Monday","Mon","Nam arcu libero, nonummy eget, consectetuer id, vulputate a, magna. Donec vehicula augue eu neque."
3,2012-03-02,2012,3,"March","Mar",2,6,"Friday","Fri","Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Mauris ut leo. Cras viverra metus rhoncus sem."
4,2012-04-19,2012,4,"April","Apr",19,5,"Thursday","Thu","Nulla et lectus vestibulum urna fringilla ultrices. Phasellus eu tellus sit amet tortor gravida placerat. Integer sapien est, iaculis in, pretium quis, viverra ac, nunc."
5,2012-05-23,2012,5,"May","May",23,4,"Wednesday","Wed","Praesent eget sem vel leo ultrices bibendum. Aenean faucibus. Morbi dolor nulla, malesuada eu, pulvinar at, mollis ac, nulla. Curabitur auctor semper nulla."
6,2012-06-07,2012,6,"June","Jun",7,5,"Thursday","Thu","Donec varius orci eget risus. Duis nibh mi, congue eu, accumsan eleifend, sagittis quis, diam. Duis eget orci sit amet orci dignissim rutrum."
7,2012-07-30,2012,7,"July","Jul",30,2,"Monday","Mon","Nam dui ligula, fringilla a, euismod sodales, sollicitudin vel, wisi. Morbi auctor lorem non justo. Nam lacus libero, pretium at, lobortis vitae, ultricies et, tellus."
8,2012-08-22,2012,8,"August","Aug",22,4,"Wednesday","Wed","Donec aliquet, tortor sed accumsan bibendum, erat ligula aliquet magna, vitae ornare odio metus a mi. Morbi ac orci et nisl hendrerit mollis. Suspendisse ut massa."
9,2012-09-18,2012,9,"September","Sep",18,3,"Tuesday","Tue","Cras nec ante. Pellentesque a nulla. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam tincidunt urna."
10,2012-10-06,2012,10,"October","Oct",6,7,"Saturday","Sat","Nulla ullamcorper vestibulum turpis. Pellentesque cursus luctus mauris. Nulla malesuada porttitor diam. Donec felis erat, congue non, volutpat at, tincidunt tristique, libero."
11,2012-11-20,2012,11,"November","Nov",20,3,"Tuesday","Tue","Vivamus viverra fermentum felis. Donec nonummy pellentesque ante. Phasellus adipiscing semper elit. Proin fermentum massa ac quam."
12,2012-12-31,2012,12,"December","Dec",31,2,"Monday","Mon","Sed diam turpis, molestie vitae, placerat a, molestie nec, leo. Maecenas lacinia. Nam ipsum ligula, eleifend at, accumsan nec, suscipit a, ipsum."
This file contains all the data to be used to create your page-a-day calendar. I've created a number of fields:
DayNum
: Number of the current entry
Date
: Entry date
Year
: Year of entry (Excel/OpenOffice formula: =YEAR(<Date>)
)
MonthNum
: Month (number) 1..12 of entry (Excel/OpenOffice formula: =MONTH(<Date>)
)
Month
: Month (name) of entry (Excel/OpenOffice VLOOKUP
using <MonthNum>
)
Mnth
: Abbreviated month (name) of entry (Excel/OpenOffice VLOOKUP
using <MonthNum>
)
Day
: Day 1..31 of entry (Excel/OpenOffice formula: =DAY(<Date>)
)
WeekdayNum
: Weekday number 1..7 of entry (Excel/OpenOffice formula: =WEEKDAY(<Date>)
)
Weekday
: Weekday name of entry (Excel/OpenOffice VLOOKUP
using <WeekdayNum>
)
Wkday
: Abbreviated weekday (name) of entry (Excel/OpenOffice VLOOKUP
using <WeekdayNum>
)
Saying
: Saying for that specific entry
page-calendar.tex
\documentclass[12pt]{article}
\usepackage[margin=2cm,landscape,a5paper]{geometry}% http://ctan.org/pkg/geometry
\usepackage{tikz}% http://ctan.org/pkg/pgf
\usetikzlibrary{calc}%
\usepackage{datatool}% http://ctan.org/pkg/datatool
\DTLloaddb{calendar}{page-calendar.csv}% Load page-calendar.csv into calendar DB
\pagestyle{empty}% Remove page headers/footers
\begin{document}
\sffamily% Default font family
\DTLforeach{calendar}
{\calDayNum=DayNum,
\calDate=Date,
\calYear=Year,
\calMonthNum=MonthNum,
\calMonth=Month,
\calMnth=Mnth,
\calDay=Day,
\calWeekdayNum=WeekdayNum,
\calWeekday=Weekday,
\calWkday=Wkday,
\calSaying=Saying}
{%
\begin{tikzpicture}[remember picture,overlay]
\fill[black!80!green!25]
(current page.north east) rectangle (current page.south west);% Outer frame
\shade [bottom color=black!70!green!25, top color=black!70!green!10]
($(current page.north east)+(-5mm,-5mm)$) rectangle ($(current page.south west)+(5mm,5mm)$); % Inner frame + shading
\draw ($(current page.north west)+(5mm,-5mm)$)
node[anchor=north west] {\scalebox{5}{\bfseries\color{black!65}\calYear}};% Print YEAR
\draw ($(current page.north east)+(-5mm,-5mm)$)
node[anchor=north east] {\scalebox{3}{\bfseries\color{black!80}%
\begin{minipage}{.5\linewidth}\raggedleft%
\calWeekday \par% Print WEEKDAY
\calDay~\calMonth% Print DAY + MONTH
\end{minipage}}};
\draw (current page.center)
node {\scalebox{2}{\color{black!95!green}%
\begin{minipage}{.5\linewidth}
\centering\large\calSaying% Print SAYING
\end{minipage}}};
\end{tikzpicture}%
\newpage%
}
\end{document}
Here I've just played around with tikz
to position the extracted elements on the page. I've only used Year
, Month
, Day
, Weekday
and Saying
, although all are accessible via macros. The macros are defined as part of the \DBLforeach
command. Specifically, Year
is references via the macro \calYear
, Month
via the macro \calMonth
, ... Saying
via the macro \calSaying
. Of course, you can rename these, and use a different layout and colour scheme or whatever (including the choice of page dimensions specified using geometry
).
The output
Why this way? Well, perhaps you don't want to create an entire annual calendar, but just a monthly one. Instead of fixing the construction within LaTeX, you can now manipulate it on a case-by-case basis outside and only export the entries you're interested in.
The approach is flexible enough since datatool
allows any recognizable LaTeX content to be included in the database. So, for example, if you don't want to include a saying, you could replace it with an image by merely using
\includegraphics[<options>]{<filename>}
and datatool
will place the image on the corresponding calendar day.
And so, after three years...
My approach is to draw TikZ
rectangles on the background layer once the Gantt chart has been drawn.
In the example below, I've highlighted the units used in the calendar, so that you can easily redefine the rectangles as you need. (For example, this approach could also be used to define horizontal stripes that would correspond to task groups.)
Note that the coloring of weekdays (Saturday in light red, and Sundays in bold red) is implemented here in a much lighter way that in your original code (i.e. directly in the definition of \pgfcalendarweekdayletter
-- cf. line 27)
What remains to do:
- automatically compute the number of title lines (to be implemented on line 75)
- automatically compute the number of chart lines (to be implemented on line 83)
Edit: Now automatically computes the number of weeks, when does the first week-end starts, and handles correctly if the first day of the calendar is a Sunday.
\documentclass[margin=10pt]{standalone}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usetikzlibrary{backgrounds,calc,calendar}
\usepackage{pgfgantt}
\usepackage{pgfcalendar}
\usepackage{calc}
\usepackage{ifthen}
%\newcommand{\datenumber}[1]{% to compute the number of days between \mystartdate and a given date. Unused here
% \pgfcalendardatetojulian{#1}{\dtnmbr}%
% \advance\dtnmbr by -\mystrtdt%
% \the\dtnmbr%
%}
%TO BE UPDATED ACCORDING TO YOUR NEEDS
\def\mystartdate{2016-08-29}%starting date of the calendar
\def\myenddate{2016-10-31}%ending date of the calendar
\def\myxunit{.5cm}%width of 1 day
\def\myyunittitle{.5cm}%height of 1 title line
\def\myyunitchart{1cm}%height of 1 chart line
\def\pgfcalendarweekdayletter#1{% define the name of weekdays + formatting
\ifcase#1M\or T\or W\or T\or F\or \textcolor{red!50!white}{S}\or \textcolor{red}{\textbf{S}}\fi
}
%Some calculation for plotting week-ends area
\newcount\myenddatecount
\pgfcalendardatetojulian{\myenddate}{\myenddatecount}
\newcount\mystartdatecount
\pgfcalendardatetojulian{\mystartdate}{\mystartdatecount}
\newcount\mynumberofdays
\mynumberofdays \myenddatecount\relax
\advance \mynumberofdays by -\mystartdatecount\relax% so \mynumberofdays is now the number of days in the calendar
\newcount\mynumberofweeks
\mynumberofweeks\mynumberofdays\relax
\advance \mynumberofweeks by -1\relax
\divide \mynumberofweeks by 7\relax% so we have the number of full weeks
\newcount\myfirstweekday
\pgfcalendarjuliantoweekday{\mystartdatecount}{\myfirstweekday}
\newcount\myfirstweekendshift
\myfirstweekendshift 5\relax
\advance\myfirstweekendshift by -\myfirstweekday\relax
\ifnum \myfirstweekendshift=-1%if first day = sunday
\advance \myfirstweekendshift by 7\relax% the first full weekend will thus begin one week after
\fi
\begin{document}
\begin{ganttchart}[%
hgrid,
vgrid,
x unit = \myxunit,
y unit title = \myyunittitle,
title height = .75,
y unit chart = \myyunitchart,
time slot format=isodate,
canvas/.append style={fill opacity=.1},
]%
{\mystartdate}%
{\myenddate}
\gantttitlecalendar{year}\\
\gantttitlecalendar{month=name}\\
\gantttitlecalendar{day}\\
\gantttitlecalendar{weekday=letter}\\
%So we have 4 title lines
\def\numbttitlelines{4}
\ganttgroup{Group 1}{\mystartdate}{2016-10-14} \\
\ganttbar{Bar 1}{\mystartdate}{2016-09-05}\\
\ganttbar{Bar 2}{2016-09-06}{2016-09-15}\\
\ganttbar{Bar 3}{2016-09-15}{2016-10-12}\\
\ganttmilestone{Milestone}{2016-10-14}%Note that whe didn't add \\ here! (so that last line is not blanck)
%So we have 5 chart lines
\def\numbtchartlines{5}
\begin{scope}[|<->| ,thick] %Display units
\fill [red] (0,0) circle [radius = 2.5pt] node [above left] {origin \texttt{(0,0)}};
\draw [blue] (-1ex,0) --(-1ex,-\myyunittitle) node [midway, right] {\verb| 1*\myyunittitle|};
\draw [blue!33!white] (-1em,0) --(-1em,-\numbttitlelines*\myyunittitle) node [midway, left] {\verb| <# of title lines>*\myyunittitle|};
\draw [green!75!black] (-1ex,-\numbttitlelines*\myyunittitle) --(-1ex,-\numbttitlelines*\myyunittitle-1*\myyunitchart) node [midway, right, anchor=south west] {\verb| 1*\myyunitchart|};
\draw [green] (-1em,-\numbttitlelines*\myyunittitle)--(-1em,-\numbttitlelines*\myyunittitle -\numbtchartlines*\myyunitchart) node [midway, left, anchor=south east] {\verb| <# of chart lines>*\myyunitchart|};
\draw [yellow!50!orange] (0, 4pt-2*\myyunittitle) -- (\myxunit,4pt-2*\myyunittitle) node [right, anchor=base west] {\verb| 1*\myxunit|};
\end{scope}
\begin{scope}[on background layer]%display week-ends
\foreach \i in {0,...,\the\mynumberofweeks}
\fill [red!10]
(\myfirstweekendshift*\myxunit+\i*7*\myxunit,-\numbttitlelines*\myyunittitle)% on the x-absis: shift the number of days before the first Saturday + 7days*\i; on the y-absis: shift down the number of title lines * their height
rectangle
(\myfirstweekendshift*\myxunit+\i*7*\myxunit+2*\myxunit,-\numbttitlelines*\myyunittitle -\numbtchartlines*\myyunitchart);% on the x-absis: add two days (the week-end); on the y-absis: add the number of chartlines*their height
\ifthenelse{\myfirstweekendshift=6}{% if the first day is a sunday, it is not grayed. So draw a rectangle for the first day of the chart.
\fill [red!10]
(0,-\numbttitlelines*\myyunittitle)
rectangle
(1*\myxunit,-\numbttitlelines*\myyunittitle -\numbtchartlines*\myyunitchart);
}{}
\end{scope}
\end{ganttchart}
\end{document}
Best Answer
I did a little bit of rtfm and I've come up with some macros for that task.
First, we need to compute the 'day of the year' for a given date, i.e. the number of days that have passed since the beginning of a year with respect to a given date:
The
initbegin
macro initializes thebegincnt
counter to the julian day number (JDN) of the 1st of January we want to use in our calendar.doy
gets the JDN of a 2014 date as input and sets the counter given as first argument to the day-of-the-year result.With that we can define a weak of the year (woy) macro:
Again, a result counter is the first argument and 2nd argument is a counter that contains the JDN of a date.
The
yearoff
macro returns 2 for a 2014 date - it is needed as 'correction' for years where the first of January is not a Monday. Its code:With that we are (nearly) ready to define a custom pgf-key for ifdate-clauses in PGF- and TikZ-Calendar constructs:
This filter uses another custom macro
mod
to compute the modulo (\cntp
contains the number of parties):Examples
We can use the filter like this:
Or in a TikZ-calendar command:
(which colorizes all days where the third party is in charge)
Or as part of a calendar style: