1

Sometime ago I've found a really nice snippet for creating Filofax (tm) organizer A5 calendar pages -- sadly I could not find the original source anymore. Subsequently I've modified it and now I'm looking forward to use it.

However, I couldn't manage to create more then two consistent pages. It would be really nice if I could add a loop so that I could create more then one week at the time. Maybe a month, a year, or even a arbitrary time span.

\documentclass[%
a5paper,
BCOR=2cm,%  Space for hole puncher
DIV=25,%    Size of textbody
9pt%       Fontsize
]{scrbook}
%
%%%%%%%%%% PACKAGES %%%%%%%%%%
%
\usepackage{tabularx,booktabs,multirow}
%\renewcommand*\familydefault{\sfdefault}
%\usepackage{roboto}
\renewcommand{\familydefault}{\sfdefault}
%
%%%%%%%%%% COUNTER %%%%%%%%%%
%
\newcount\counter
\newcount\startdate
\newcount\starttime
\newcount\stoptime
\newcount\sundaybegin
\newcount\week
%
%%%%%%%%%% CUSTOMISATIONS %%%%%%%%%%
%
%% Month
\renewcommand{\month}{March}
%% Date to start the week with
\startdate=13
%% Morning starttime
\starttime=8
%% Evening time
\stoptime=20
%% Starttime sunday
% Min \starttime+1
% Max \stoptime-2
\sundaybegin=14
%% Weeknumber
\week=11
%% Rule width thick
\newcommand{\rulew}{.15em}
%% Extra space
%\setlength{\extrarowheight}{1pt}
%
%%%%%%%%%% DEFINITIONS %%%%%%%%%%
%
\newcommand{\lendt}{\cmidrule[\rulew](l){1-2}\cmidrule[\rulew](l){3-4}\cmidrule[\rulew](l){5-6}}
\newcommand{\lend}{\cmidrule(l){1-2}\cmidrule(l){3-4}\cmidrule(l){5-6}}
\newcommand{\lsun}{\cmidrule(l){1-2}\cmidrule(l){3-4}}
\newcommand{\lsunt}{\cmidrule(l){1-2}\cmidrule(l){3-4}\cmidrule[\rulew](l){5-6}}
\newcommand{\printday}[2]{{\LARGE \textbf{#1}}\,\, \large \textbf{#2}}
\newcommand{\neutralline}{& & & & &}
\newcommand{\footer}{\centering\rule{5.5cm}{\cmidrulewidth} \raisebox{-0.5ex}{\textbf{Dragosh Christian OTTO}} \rule{5.5cm}{\cmidrulewidth}}
\newcommand{\printmonth}{{\LARGE \textbf{\month}}}
%
%%%%%%%%%% TABLE CONTENT LEFT SIDE %%%%%%%%%%
%
% Correction due to \global\advance
\advance\startdate-6
%
\advance\stoptime1
\long\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
%
\def\tabledataleft{} \counter=\the\starttime
\loop
    \edef\tabline{\the\counter & & \the\counter & & \the\counter & }
    \expandafter\addto\expandafter\tabledataleft\expandafter{\tabline \\\lend}    
    \expandafter\addto\expandafter\tabledataleft\expandafter{\neutralline \\\lend}
    \expandafter\addto\expandafter\tabledataleft\expandafter{\neutralline \\\lend}
    \expandafter\addto\expandafter\tabledataleft\expandafter{\neutralline \\\lend}
    \advance \counter 2
    \ifnum \counter<\the\stoptime
\repeat 
%
%%%%%%%%%% TABLE CONTENT RIGHT SIDE %%%%%%%%%%
%
\def\tabledatarightupper{} \counter=\the\starttime
\loop
    \edef\tabline{\the\counter &  & \the\counter & & & }
    \expandafter\addto\expandafter\tabledatarightupper\expandafter{\tabline \\\lend}
    \expandafter\addto\expandafter\tabledatarightupper\expandafter{\neutralline \\\lend}
    \expandafter\addto\expandafter\tabledatarightupper\expandafter{\neutralline \\\lend}
    \expandafter\addto\expandafter\tabledatarightupper\expandafter{\neutralline \\\lend}
    \advance \counter 2
    \ifnum \counter<\the\sundaybegin
\repeat 
%
\advance\sundaybegin1
\def\tabledatarightinter{} \counter=\the\sundaybegin
\newcount\sundaystop
\sundaystop=\the\sundaybegin
\advance\sundaystop1
\loop
    \edef\tabline{\the\counter &  & \the\counter & & & }
    %\expandafter\addto\expandafter\tabledatarightinter\expandafter{\neutralline \\\lsun}
    \expandafter\addto\expandafter\tabledatarightinter\expandafter{\neutralline \\\lsun}
    \expandafter\addto\expandafter\tabledatarightinter\expandafter{\neutralline \\\lsun}
    \advance \counter 2
    \ifnum \counter<\the\sundaystop
\repeat
\advance\sundaybegin-1
\advance\sundaystop1
%
\def\tabledatarightlower{} \counter=\the\sundaystop
\loop
    \advance \counter 1
    \edef\tabline{\the\counter &  & \the\counter & & & }
    \expandafter\addto\expandafter\tabledatarightlower\expandafter{\neutralline \\\lend}
    \expandafter\addto\expandafter\tabledatarightlower\expandafter{\neutralline \\\lend}
    \expandafter\addto\expandafter\tabledatarightlower\expandafter{\neutralline \\\lend}
    \expandafter\addto\expandafter\tabledatarightlower\expandafter{\tabline \\\lend}
    \advance \counter 1
    \ifnum \counter<\the\stoptime
\repeat 
\advance\sundaystop-1
%
\begin{document}
%
%% Empty page to start left
\thispagestyle{empty}
\mbox{}
\clearpage
%
\pagestyle{empty}
\enlargethispage{1cm}
%
%%%%%%%%%% LEFT TABLE %%%%%%%%%%
%
\noindent
\begin{tabularx}{\linewidth}{lXlXlX}
    \multicolumn{6}{l}{\printmonth \hfill Week \the\week}\\[.2em]
    \midrule[\rulew]
    \addlinespace[.5em]
    \multicolumn{2}{l}{\printday{\the\startdate}{Monday}} \global\advance\startdate 1\relax &%
    \multicolumn{2}{l}{\printday{\the\startdate}{Tuesday}} \global\advance\startdate 1\relax &%
    \multicolumn{2}{l}{\printday{\the\startdate}{Wednesday}}\global\advance\startdate 1\relax \\[1cm]
     & & & & & \\\lendt
    \tabledataleft
     & & & & & \\[1cm]
     \midrule[\rulew]
\end{tabularx}
%
\vfill
%\footer
%
\clearpage
\enlargethispage{1cm}
% Correction due to \global\advance
\advance\startdate-6
%
%%%%%%%%%% RIGHT TABLE %%%%%%%%%%
%
\noindent
\begin{tabularx}{\linewidth}{lXlXlX}
    \multicolumn{6}{l}{Week \the\week \hfill \printmonth}\\[.2em]\midrule[\rulew]
    \addlinespace[.5em]
    \multicolumn{2}{l}{\printday{\the\startdate}{Thursday}} \global\advance\startdate 1\relax &%
    \multicolumn{2}{l}{\printday{\the\startdate}{Friday}}   \global\advance\startdate 1\relax &%
    \multicolumn{2}{l}{\printday{\the\startdate}{Saturday}} \global\advance\startdate 1\relax \\[1cm]
    & & & & & \\\lendt
    \tabledatarightupper
    %& & & & & \\\lsunt
    \addlinespace[-.15em]
    \the\sundaybegin & & \the\sundaybegin & & \multicolumn{2}{l}{\multirow{4}{*}[1.5em]{\printday{\the\startdate}{Sunday}}}\\\lsun
    \tabledatarightinter
    & & & & & \\\lsun
    \the\sundaystop & & \the\sundaystop & & & \\\lsunt
    \tabledatarightlower
    & & & & & \\\lend
    & & & & & \\\lend
    & & & & & \\\lend
    & & & & & \\[1cm]
    \midrule[\rulew]
\end{tabularx}
%
\vfill
%\footer
\end{document}

1 Answer 1

4

PGF/TikZ comes with the “utility” PGFCalendar. With my tikz-ext package I have added support for week numbering. For this, you will actually need to load the pgfcalendar-ext package.

Now, PGFCalendar has one main command: \pgfcalendar

It does loop through all dates specificed in the range and sets up a few macros (and one TeX count) that holds information about the current day. (And pgfcalendar-ext extends that so that the weeknumber is also available.)

Now, we don't want to actually loop through every single date but only want to look at Mondays (left side) and at Thursday (right side).

So at the last, we trick PGFCalendar by time-travelling to Wednesday (left side) and Sunday (right side):

\ifdate{Monday}{\advance\pgfcalendarcurrentjulian by 2}
               {\advance\pgfcalendarcurrentjulian by 3}
\clearpage

We could actually just use \ifodd\value{page} to figure out where we are but here I'm using PGFCalendar's \ifdate where Monday indicates the left side.

Since the head and the foot of each page is roughly the same we typeset this directly in the loop. We use the same test to figure out if we have to typeset the left or the right header setup. (We probably could have used the left and right mark of the Koma classes for this but that's not our main concern here.)

After we typeset the three days on the top (more on that later) we again have to think about on which page we are (→ \ifdate{Monday}).

For the left side we just typeset all rows for all the times. For the right side we have to break it up for the Sunday.

Instead of your pre-built templates , I'm using Latex3's \int_step_function:nnnN as simple for(each) loop. It can be safely used inside a tabularx. The Sunday side is a bit messy. I've made a few adjustments:

  • Take a look at \lineEndSundayTop where I've added a linespace that will make the table ignore the extra thickness of \ruleThick so that the grid of lines on the right side is spaced exactly the same as on the left side.

  • The Sunday header is lowered (negatively raised) while being \smashed so that it doesn't snuck up to the upper line without enlarging the line vertically.


Now, we can't simply add one, two or – for the Sunday – three to the current day to get the other days on the page that aren't Monday or Thursday because each one of these days could be in the next month.

We could check around a bit if we would be above 28/29/30/31 and adjust things accordingly but I will just let PGFCalendar do that job again via \PGFCalendarPlus.

This macro will start another \pgfcalendar loop of one (1) day, the one that is one, two or days after the current one (which is either a Monday or a Thursday). We'll print the day number and weekday and that's it.

Code

\documentclass[a5paper, BCOR=2cm, DIV=25, fontsize=9pt]{scrbook}
% https://tex.stackexchange.com/a/651888
\usepackage{pgfcalendar-ext} % loads pgfcalendar and has weeknumbering
\usepackage{tabularx, booktabs, multirow}
\usepackage{xfp}% for \inteval for older TeX distributions
\renewcommand*\familydefault{\sfdefault}

% horizontal lines in tabularx
\newcommand*\lineEndTop      {\cmidrule[\ruleThick](l){1-2}\cmidrule[\ruleThick](l){3-4}\cmidrule[\ruleThick](l){5-6}}
\newcommand*\lineEnd         {\cmidrule            (l){1-2}\cmidrule            (l){3-4}\cmidrule            (l){5-6}}
\newcommand*\lineEndSunday   {\cmidrule            (l){1-2}\cmidrule            (l){3-4}}
\newcommand*\lineEndSundayTop{\cmidrule            (l){1-2}\cmidrule            (l){3-4}\cmidrule[\ruleThick](l){5-6}%
                              \addlinespace[\dimexpr-\ruleThick+\lightrulewidth]}
\newcommand*\printDay        {{\LARGE \textbf{\%d-}}\,\, \large \textbf{\%wt}}
\newcommand*\printDays       {%
  \multicolumn{2}{l}                    {\printDay}  &
  \multicolumn{2}{l}{\PGFcalendarPlus{1}{\printDay}} &
  \multicolumn{2}{l}{\PGFcalendarPlus{2}{\printDay}}}
\newcommand*\printWeekLeft   {{\bfseries\LARGE\%mt} \hfill Week \%n-}
\newcommand*\printWeekRight  {Week \%n-\hfill {\bfseries\LARGE\%mt}}
\newcommand*\timeStart  {8}
\newcommand*\timeEnd   {20}
\newcommand*\timeStep   {2}
\newcommand*\timeSunday{14}
\newcommand*\timeBlockX[2]{%
  #1 & & #1 & & #2 \\ \lineEnd
  & & & & &        \\ \lineEnd \\ \lineEnd \\ \lineEnd}
\newcommand*\timeBlockLeft [1]{\timeBlockX{#1}{#1}}
\newcommand*\timeBlockRight[1]{\timeBlockX{#1}{}}
\newcommand*\blockSunday[3]{% Ugh!
  \inteval{\timeSunday-\timeStep} & &
  \inteval{\timeSunday-\timeStep} & & \\ \lineEnd
  \\ \lineEnd       \\ \lineEnd       \\ \lineEndSundayTop
  \timeSunday & & \timeSunday & & #1  \\ \lineEndSunday
  \\ \lineEndSunday \\ \lineEndSunday}

\newcommand*\PGFcalendarPlus[2]{%
  \pgfcalendar{temp}{\pgfcalendarcurrentyear-\pgfcalendarcurrentmonth-\pgfcalendarcurrentday+#1}
                    {\pgfcalendarcurrentyear-\pgfcalendarcurrentmonth-\pgfcalendarcurrentday+#1}{#2}}

\newcommand*\ruleThick{.15em}

\pagestyle{empty}
\setlength\parindent{0pt}% instead of \noindent
\ExplSyntaxOn \let\FOREACH\int_step_function:nnnN \ExplSyntaxOff
\let\%\pgfcalendarshorthand
%\usepackage[showframe, pass]{geometry}
\begin{document}
\null\clearpage
\pgfcalendar{cal}{2023-03-13}{2023-06-30}{%
  \enlargethispage{1cm}
  \begin{tabularx}{\linewidth}{lXlXlX}
    \multicolumn{6}{l}{\ifdate{Monday}{\printWeekLeft}{\printWeekRight}}\\[.2em]
    \midrule[\ruleThick] \addlinespace[.5em]
    \printDays \\[4em]\lineEndTop
  \ifdate{Monday}{% left page
    \FOREACH{\timeStart}{\timeStep}{\timeEnd}\timeBlockLeft
  }{%
    \FOREACH{\timeStart}{\timeStep}{\inteval{\timeSunday-2*\timeStep}}\timeBlockRight
    \blockSunday{\multicolumn{2}{l}{\PGFcalendarPlus{3}{\smash{\raisebox{-.3em}{\printDay}}}}}{}{}
    \\\lineEndSundayTop
    \FOREACH{\inteval{\timeSunday+\timeStep}}{\timeStep}{\timeEnd}\timeBlockRight
  }%
    \\[1cm]
    \midrule[\ruleThick]
  \end{tabularx}
  \ifdate{Monday}{\advance\pgfcalendarcurrentjulian by 2}
                 {\advance\pgfcalendarcurrentjulian by 3}
  \clearpage
}
\end{document}

Output

enter image description here

It's a video.

8
  • @Qrrbrbirbel: First of all: Wow! And thank you for your work. It looks really nice, like the detailed explanation. Sadly I cannot reproduce it because the compiler (LuaLaTeX) can't find pgfcalendar-ext.sty. The links 1 and 2 on the suggested linked answer are dead. You suggest that \ifodd\value{page} could be also used. Is it possible to offer also an solution with the standard texlive-full packages?
    – alex
    Mar 15 at 7:42
  • @alex tikz-ext, which provides pgfcalendar-ext.sty, is a quite new package (first release AFAIK 2022). Since TeX Live packages from Linux distributions are often rather older, I would be surprised if tikz-ext would be offered via the Linux package manager. In Vanilla TeX Live, however, it is included since 2022 and installable via tlmgr. As a last resort, you could install it from CTAN.
    – cabohah
    Mar 15 at 7:51
  • @Qrrbrbirbel: as suggested, by @cabohah, I've installed the package manually from CTAN tkiz-ext. The package documentation doesn't describe the installation process so I've used this one.. Now there seems to be some bracketting error. I've searched for 15m now and did not find any. If possible, please add an alternative version with \ifodd\value{page}. It could be important to other, unexperienced users (me), to test it.
    – alex
    Mar 15 at 8:49
  • @alex The linked error messages seem to be only a snippet. They are not the complete log file. So I even cannot say, where the error happens. Off-Topic: You should replace the deprecated option 9pt by fontsize=9pt.
    – cabohah
    Mar 15 at 8:55
  • 2
    @alex Since your Linux provided TeX Live installation doesn't get updates you will need to \usepackage{xfp} for \inteval. Mar 15 at 9:34

You must log in to answer this question.

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