1

I want the calendar month to take up the entire text body in height and width.

However, I can not do that at height:

How can I get rid of these gaps?

It seems the problem is in the setting
DayCellHeight/.store in =\DayCellHeight, DayCellHeight=(\textheight-2\pgflinewidth/\WeekRowsNo-\WeekDayNamesHeight-1\InnerSep)/\WeekRowsNo,

Full Code:

enter image description here

\documentclass[paper=A4,landscape, english]{scrartcl}
% Inputs:
\def\Margin{1.75cm}
\def\Year{2018}
%\def\Month{11}

\renewcommand*{\familydefault}{\sfdefault} % \rmdefault % \sfdefault
\def\CalendarNumbersFont{\Huge\sffamily}%\Huge\bfseries\sffamily
\def\WeekDayNamesFont{\Large\bfseries\sffamily}%\bfseries\sffamily

% Advanced Inputs:
\def\NumberOfWeekRows{\WeekRowsNo}  % 6  % \WeekRowsNo

% Packages and Settings
\setparsizes{0pt}{0pt}{0pt plus 1fil}

\usepackage{lmodern}

\usepackage[showframe=true,
%headsep=0mm, includehead, 
%margin=\Margin
]{geometry}
\newcommand\changehead[1]{
\newgeometry{headheight=#1,  % local
margin=\Margin, includehead, headsep=0mm, nofoot, % global
}}

\usepackage{scrlayer-scrpage}
  \setkomafont{pagehead}{\normalfont}
  \cfoot{}% 'show no foot'

\usepackage{calc}  % for '\settototalheight'

\usepackage{tikz}
  \usepackage[]{babel}
  \usepackage{translator}
  \usetikzlibrary{calendar}

% Content Test
\newcommand\Inhalt{%
%$\text{\tikzdaytext\hspace{0.75pt}}%
%\overset%
%%{\parbox{2em}{\tiny Tag der Deutschen}}%
%{\text{\tiny Tag der Deutschen\:Einheit}}%
%{\text{   \tiny (schulfrei)   }\hfill}%
%$% 
%M%
{\tikzdaytext}% 
%\begin{tabular}[b]{>{\tiny}p{1cm}}
%aa  aa aaa\\[-3pt]
%bbb
%\end{tabular}
M
}


\begin{document}
\newlength\HeadHeight%
\newlength\DayLetterHeight%
%\CalendarNumbersFont%
\settototalheight\DayLetterHeight{\vbox{\CalendarNumbersFont 1 2 3 4 5 6 7 8 9 0 M}}%
%\settototalheight\DayLetterHeight{\parbox[b]{\linewidth}{\strut 1 2 3 4 5 6 7 8 9 0 M \strut}}%
%\pgfmathsetlengthmacro{\DayLetterHeight}{height("1 2 3 4 5 6 7 8 9 0 M")}% 'same result'
%\normalsize\normalfont%
DayLetterHeight:  \the\DayLetterHeight  \\
%
\newlength\weekdaynamesheight
%\WeekDayNamesFont%
\settototalheight\weekdaynamesheight{\vbox{\WeekDayNamesFont\pgfcalendarweekdayname{0}}}%
\pgfmathsetlengthmacro{\WeekDayNamesHeight}{\weekdaynamesheight}%
%\normalsize\normalfont%
WeekDayNamesHeight (from \pgfcalendarweekdayname{0}): \the\weekdaynamesheight  /  \WeekDayNamesHeight

Titelseite \newpage

% Calendar      % 01,02,03,04,05,06,07,08,09,10,11,12
\foreach \Month in {01,02,03,04,05,06,07,08,09,10,11,12}{%%%%%%%%%%%%%%%%%%%
\def\Head{\parbox[b]{\linewidth}{\strut {\Huge\bfseries \pgfcalendarmonthname{\Month} \Year}\\ head \strut}}%
\settototalheight\HeadHeight{\vbox{\Head}} % Kopfhöhe messen
\changehead{\HeadHeight}
%\newgeometry{headheight=\HeadHeight, 
%headsep=0mm, includehead, 
%margin=\Margin}%
\ihead{\Head}%
%HeadHeight \the\HeadHeight
%\centering Inhalt \Month \\
%
% Number of week rows: ===============
\newcount\JulianDateNo
\pgfcalendardatetojulian{\Year-\Month-last}{\JulianDateNo}
%Julian Days: \the\JulianDateNo
%
\pgfcalendarjuliantodate{\JulianDateNo}{\theyear}{\themonth}{\DaysOfMonth}
%Date last Monthday: \theyear-\themonth-\DaysOfMonth~
%Number of Monthdays: \DaysOfMonth
%
\pgfcalendardatetojulian{\Year-\Month-01}{\JulianDateNo}
%Julian Days: \the\JulianDate
\newcount\WeekDayNo
\pgfcalendarjuliantoweekday{\JulianDateNo}{\WeekDayNo}
%Weekdaynumber first day of the month: \the\WeekDayNo
%
\pgfmathsetmacro\WeekRowsNo{
\DaysOfMonth == 31 && \WeekDayNo >= 5 ? 6 : (
\DaysOfMonth == 30 && \WeekDayNo == 6 ? 6 : (
\DaysOfMonth == 28 && \WeekDayNo == 0 ? 4 : 5))
}
%Week rows: \WeekRowsNo
% =============================
% Measures =======================
\pgfkeys{tikz/.cd,
InnerSep/.store in =\InnerSep,
InnerSep=3pt,
DayCellWidth/.store in =\DayCellWidth,
DayCellWidth=(\textwidth-\pgflinewidth)/7,
DayCellHeight/.store in =\DayCellHeight,
DayCellHeight=(\textheight-2\pgflinewidth/\WeekRowsNo-\WeekDayNamesHeight-1\InnerSep)/\WeekRowsNo,
}
% =============================
\begin{tikzpicture}[  %  ultra thick,  red, opacity=0.5,     % for 'showframes'
every day/.append style={
text=black, 
font=\CalendarNumbersFont,
draw,
anchor=north west,
inner sep=\InnerSep,
text width=\DayCellWidth-2*\InnerSep, %<-geändert
text depth=\DayCellHeight-\DayLetterHeight-2*\InnerSep,%<-geändert
minimum width=\DayCellWidth, 
minimum height=\DayCellHeight,%<-geändert
name=\pgfcalendarsuggestedname,
},
]
\newcount\daynocount

\calendar (cal) [
day xshift=\DayCellWidth,% <- 
day yshift=\DayCellHeight,% <- 
dates=\Year-\Month-01 to \Year-\Month-last,
week list, 
%day code={
%\node[name=\pgfcalendarsuggestedname,every day]{\Huge \tikzdaytext};
%}
]
if (Sunday) [nodes={red, fill=pink}]
if (equals=\Year-\Month-02) [
%nodes={red, fill=pink}, 
%day code={\node[every day]{ \Tabelle  };}
day code={
\node[every day]{\Inhalt};
}
]
%
if (equals=\Year-\Month-07) [
%nodes={red, fill=pink}, 
%day code={\node[every day]{   };}
]
;

% Weekdaynames
\foreach \i in {1,...,7} {%
\node[anchor=south, 
inner sep=\InnerSep,
%text width=\DayCellWidth-2*\InnerSep, %ruiniert Zentrierung
text depth=\WeekDayNamesHeight-2*\InnerSep,%<-
minimum width=\DayCellWidth, 
minimum height=\WeekDayNamesHeight,%<
draw,fill=gray, text=white,
font=\WeekDayNamesFont,
] at ([yshift=0ex]cal-\Year-\Month-0\i.north |- cal-\Year-\Month-01.north) {%\vphantom{g}%
\pgfcalendardatetojulian{\Year-\Month-0\i}{\daynocount}%
\pgfcalendarjuliantoweekday{\the\daynocount}{\daynocount}%
\pgfcalendarweekdayname{\the\daynocount}%,\the\daynocount,\i%
};
}%

\fill[red, thick] (cal-\Year-\Month-21) circle (2pt);
\node[red, draw, align =left, 
anchor=south, 
yshift=\InnerSep, 
text width=\DayCellWidth-2*\InnerSep,
inner sep=0pt
] (Termin) at (cal-\Year-\Month-21.south) {This is a long text. This is a long text. \\Termin\\ Termin};


\end{tikzpicture}
\newpage % needed
}%%%%%%%%%%%%%%%%%%%%%%%
%
\end{document}
4
  • Should it be DayCellHeight=(\textheight-2*\pgflinewidth*\WeekRowsNo-\WeekDayNamesHeight-2*\InnerSep)/\WeekRowsNo ?
    – nidhin
    Dec 12, 2018 at 21:24
  • @nidhin Ahaaa... Maybe this is correct... but mmhh, I get Overfull \vbox (0.80008pt too high) has occurred while \output is active and this means: I get an empty page beetween each month :(
    – cis
    Dec 12, 2018 at 22:40
  • @cis Careful, both the line width as well as the outer [xy]seps might contribute to the tikzpicture's bounding box. The whole \DayCellHeight (including \pgflinewidth) won't get evaluated until the every day node gets typeset where \pgflinewidth might be different than where it contributes to the bounding box. Your code is a bit too unorganized for me, to delve deep enough in. For inspiration, I've setup a similar "wall calendar" in another recent answer. Jul 31, 2022 at 23:28
  • Just doing \sbox0{\tikz\draw(0pt,0pt)--(0pt,10pt);}\the\ht0-\the\wd0 shows you that the line width factors in in unexpected places. Jul 31, 2022 at 23:33

1 Answer 1

2

I've tried first something like my other answer that produces a (kinda) full page month sheet but since your header is outside of TikZ I found it hard to get the exact vertical space between the top of the text frame and the top of the yet-to-be created tikzpicture. This also depended on where the baseline of the tikzpicture is.

Here is a simple solution that just does everything inside the tikzpicture.

Again, I'm using the ext.calendar-plus library of my tikz-ext package for

  • the value keys /tikz/day xshift and /tikz/day yshift, in default TikZ we would need to use \tikz@lib@cal@[x|y]shift
  • an fully expandable version of \%m- (the month's number) so that it can be used inside PGFmath (the preceding 0 gets interpreted as an octal number and 08 as well as 09 would trip), otherwise we need to use \numexpr\%m0\relax instead
  • for the PGFmath function weeksinmonthofyear(<first weekday in month>)(<month>)(<year>) which uses the PGFmath function lastdayinmonthofyear(<month>)(<year>) which uses the internal macro \pgfcalendar@getlastYMX which simply evaluates the last day of the month (28, 29, 30 or 31) depending on month and (leap) year. Of course, you can replace the \ifdate line in the code below with your own calculation.

The page will be filled in three steps:

  1. the header
  2. the weekday head
  3. the actual days.

In the answer linked above, the weekdays were placed by the first seven days of the month but since you don't want to give a minimal height for these nodes I'll just place them before the \calendar (of course, we could just determine the height beforehand in a dummy node/box but why bother …

Between step 1 and step 2, the previous node's height will be determined and before step 3 the remaining available height will be calculated an the key /tikz/height for calendar will be set which can then be used by \calendar.

At every first day of the month, the needed number of weekrows will be evaluated and the key /tikz/weeks in this month will be set accordingly.


All outer sep are set to zero so that all nodes' borders align.

The trim left and trim right keys are used to remove the line width's attribution to the bounding box, without it we'll get overfull \hboxes.

I'm still getting

Overfull \vbox (13.59999pt too high) has occurred while \output is active []

but I'm also getting these, when the tikzpicture is empty …

Code

\documentclass[a4paper,landscape,ngerman]{scrartcl}
\usepackage{scrlayer-scrpage}\cfoot{}
\usepackage{babel,translator}
\usepackage[margin=1.75cm,noheadfoot]{geometry}
\usepackage{libertine}
\usepackage{tikz}\usetikzlibrary{ext.calendar-plus}
\tikzset{
  % just some dummy defaults
  height for calendar/.initial=\textheight,
  weeks in this month/.initial=6,
  %
  wall calendar/.style={
    week list, day text=, % empty day nodes
    day xshift=\linewidth/7,
    day yshift=\pgfkeysvalueof{/tikz/height for calendar}/
               \pgfkeysvalueof{/tikz/weeks in this month},
    %
    % recalculates the number of weeks per month at the first of the month
    % uses expandable shorthand \%m- (provided by tikz-ext)
    % to drop preceding 0 for PGFMath
    execute before day scope=
      \ifdate{day of month=1}{%
        \pgfmathweeksinmonthofyear{\pgfcalendarcurrentweekday}{\%m-}{\%y-}%
        \tikzset{weeks in this month/.expanded=\pgfmathresult}}{},
    every weekday/.style={
      draw=black, outer sep=+0pt, anchor=north west,
      fill=gray, text=white,
      minimum width=\pgfkeysvalueof{/tikz/day xshift},% \tikz@lib@cal@xshift
      font=\Large\bfseries\strut,
      xshift=##1*(\pgfkeysvalueof{/tikz/day xshift}),%  \tikz@lib@cal@xshift
      name=weekday-##1,
      node contents=\pgfcalendarweekdayname{##1},
      weekday-##1/.try},
    every head/.style={
      name=cal@head,
      anchor=north west,
      align=left},
    every day/.append style={
      draw=black, outer sep=+0pt, anchor=north west,
      label={[every day label]north west:},
      minimum width=\linewidth/7,
      minimum height=\pgfkeysvalueof{/tikz/day yshift}},% \tikz@lib@cal@yshift
    every day label/.style={
      anchor=north west,
      font=\Large,
      node contents={\%d-},
      inner ysep=.7em,
      inner xsep=.5em}}
}
\makeatletter % quick low-level versions instead of calc library
\newcommand*\getHeightOfHeader{%
  \pgfpointdiff{\pgfpointanchor{cal@head}{south}}
               {\pgfpointanchor{cal@head}{north}}%
  \pgfgetlastxy\tikz@temp\tikz@headheight
  \pgftransformyshift{-\tikz@headheight}}
\newcommand*\getHeightOfWeekdays{%
  \pgfpointdiff{\pgfpointanchor{weekday-0}{south}}
               {\pgfpointanchor{weekday-0}{north}}%
  \pgfgetlastxy\tikz@temp\tikz@weekdayheight
  \pgftransformyshift{-\tikz@weekdayheight}
  \pgfmathadd@{\tikz@headheight}{\tikz@weekdayheight}%
  \pgfmathsubtract@{\textheight}{\pgfmathresult}
  \tikzset{height for calendar/.expanded=\pgfmathresult pt}}
\makeatother
\newcommand*\Year{2022}
\begin{document}\sffamily
\foreach \mon in {1,...,12}{%
\noindent
\begin{tikzpicture}[
  wall calendar, trim left=(weekday-0.west),trim right=(weekday-6.east),
  weekday-6/.style={text=black,draw=red,fill=pink}]
%
%% Headers
\node[every head]
  {{\Huge\strut\pgfcalendarmonthname{\mon}\par}\\{\huge\strut\Year\par}};
\getHeightOfHeader
%
%% Weekdays
\foreach \weekday in {0,...,6}
  \node[every weekday=\weekday];
\getHeightOfWeekdays
%
%% The calendar itself
\calendar[
  dates=\Year-\mon-01 to \Year-\mon-last
] if (Sunday) [days={red, fill=pink}];
\end{tikzpicture}\par\pagebreak}
\end{document}

Output (with geometrys showframe)

August 2022

You must log in to answer this question.

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