0

I am adopting this calendar (https://texample.net/tikz/examples/birthday-calendar/) to my needs, but I have a problem I cannot solve on my own.

In each single day grid, how can I get rid of the last comma in the list of birthdays (blue top line) and the list of special days (green bottom line)?

enter image description here

Bonus question: Is it possible that a second line of birthdays starts right of the day number?

This is my code:

% Birthday calendar
% Author: Hakon Malmedal
\documentclass[fontsize=15pt]{scrartcl}
\usepackage[german]{babel}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage[paperheight=70cm,paperwidth=50cm,margin=0mm,heightrounded]{geometry}
%\usepackage[margin=1cm,a4paper,landscape]{geometry}
\pagestyle{empty}
\usepackage{graphicx}
\usepackage{tikz}
%%%<
\usepackage{verbatim}
%%%>
\begin{comment}
:Title: Birthday calendar
:Tags: Calendar library;Calendars
:Author: Hakon Malmedal
:Slug: birthday-calendar
\end{comment}
\usetikzlibrary{calendar,fit}
\usepackage{expl3,xparse}

%from https://tex.stackexchange.com/questions/140948/tikz-calendar-and-conditional-tests \makeatletter \def\pgfcalendar@matchesfalse{\global\let\ifpgfcalendar@matches\iffalse} \def\pgfcalendar@matchestrue{\global\let\ifpgfcalendar@matches\iftrue} \pgfcalendar@matchesfalse \pgfqkeys{/pgf/calendar}{and/.code 2 args={% \begingroup \ifdate{#1}{\ifdate{#2}{\pgfcalendar@matchestrue}{}}{}% \endgroup \ifpgfcalendar@matches\pgfcalendarmatchestrue\pgfcalendar@matchesfalse\fi}} \makeatother

%% Adapted from pgf source \def\pgfcalendarmonthname#1{% \translate{\ifcase#1\or Januar\or Februar\or März\or April\or Mai\or Juni\or Juli\or August\or September\or Oktober\or November\or Dezember\fi}% }

%% Adapted from http://tex.stackexchange.com/a/10199/4771 \makeatletter% \tikzoption{day headings}{\tikzstyle{day heading}=[#1]} \tikzstyle{day heading}=[] \tikzstyle{day letter headings}=[ execute before day scope={ \ifdate{equals=01-01}{% \pgfmathsetlength{\pgf@ya}{\tikz@lib@cal@yshift}% \pgfmathsetlength\pgf@xa{\tikz@lib@cal@xshift}% \pgftransformyshift{-\pgf@ya} \foreach \d/\l in {0/Montag,1/Dienstag,2/Mittwoch,3/Donnerstag,% 4/Freitag,5/Samstag,6/Sonntag} { \pgf@xa=\d\pgf@xa% \pgftransformxshift{\pgf@xa-\cellwidth/2}% \pgftransformyshift{2\pgf@ya-2pt}% \node[below=0.5ex,day heading, inner sep=2.5mm,font=\Large]{\l};% } }{}% }% ] \makeatother% %% End

\ExplSyntaxOn

%% Adapted from http://tex.stackexchange.com/a/56214/4771 %% % first of all we define the user level commands \NewDocumentCommand{\addtext}{ m }{ \bdaycal_input_add_text:n { #1 } } \NewDocumentCommand{\addbirthday}{ mm }{ \bdaycal_input_add_birthday:nn { #1 } { #2 } } \NewDocumentCommand{\addbirthdaydead}{ mm }{ \bdaycal_input_add_birthday_dead:nn { #1 } { #2 } } \NewDocumentCommand{\adddateofdeath}{ mm }{ \bdaycal_input_add_date_of_death:nn { #1 } { #2 } } \NewDocumentCommand{\addweek}{ m }{ \bdaycal_input_add_week:n { #1 } } \NewDocumentCommand{\showtext}{ }{ \bdaycal_output_direct_text: } \NewDocumentCommand{\showbirthdays}{ }{ \bdaycal_output_direct_birthday: }

% allocate variable: % a sequence for global storage of the inputs; \seq_new:N \g_bdaycal_input_seq_text \seq_new:N \g_bdaycal_input_seq_birthday

% store globally an input in the sequence \cs_new:Npn \bdaycal_input_add_text:n #1 { \seq_gput_right:Nn \g_bdaycal_input_seq_text { #1 } }

\cs_new:Npn \bdaycal_input_add_birthday:nn #1 #2 { \seq_gput_right:Nn \g_bdaycal_input_seq_birthday { #1 ~ \int_to_arabic:n { \pgfcalendarifdateyear - #2 }} }

\cs_new:Npn \bdaycal_input_add_birthday_dead:nn #1 #2 { \seq_gput_right:Nn \g_bdaycal_input_seq_birthday {( #1 ~ \int_to_arabic:n { \pgfcalendarifdateyear - #2 })} }

\cs_new:Npn \bdaycal_input_add_date_of_death:nn #1 #2 { \seq_gput_right:Nn \g_bdaycal_input_seq_birthday {\dag \ #1 ~ #2} }

% how to output in direct order; we simply do a mapping function calling % \bdaycal_print:n after incrementing the counter \cs_new_protected:Npn \bdaycal_output_direct_text: { \seq_map_inline:Nn \g_bdaycal_input_seq_text { \int_gincr:N \g_tmpa_int % \int_compare:nNnT {\g_tmpa_int}={1}{}%vor dem ersten Eintrag ##1 \int_compare:nNnF {\g_tmpa_int}={\seq_count:N \g_bdaycal_input_seq_text}{,~}%am Ende jedes Eintrags, außer nach dem letzten } \seq_gclear:N \g_bdaycal_input_seq_text }

\cs_new_protected:Npn \bdaycal_output_direct_birthday: { \seq_map_inline:Nn \g_bdaycal_input_seq_birthday { \int_gincr:N \g_tmpa_int % \int_compare:nNnT {\g_tmpa_int}={1}{}%vor dem ersten Eintrag ##1 \int_compare:nNnF {\g_tmpa_int}={\seq_count:N \g_bdaycal_input_seq_birthday}{,~}%am Ende jedes Eintrags, außer nach dem letzten } \seq_gclear:N \g_bdaycal_input_seq_birthday } %% End

%% Knuth's AoCP, vol 1, 2nd ed, pp 155--156 \int_new:N \l_easter_Y_int \int_new:N \l_easter_G_int \int_new:N \l_easter_C_int \int_new:N \l_easter_X_int \int_new:N \l_easter_Z_int \int_new:N \l_easter_D_int \int_new:N \l_easter_E_int \int_new:N \l_easter_N_int \int_new:N \l_easter_M_int \int_new:N \l_easter_julian_day_int

\cs_new:Nn \easter_sunday:n {

\int_set:Nn \l_easter_Y_int { #1 }

\int_set:Nn \l_easter_G_int { \int_mod:nn { \l_easter_Y_int } { 19 } + 1 }

\int_set:Nn \l_easter_C_int { \int_div_truncate:nn { \l_easter_Y_int } { 100 } + 1 }

\int_set:Nn \l_easter_X_int { \int_div_truncate:nn { 3 * \l_easter_C_int } { 4 } - 12 }

\int_set:Nn \l_easter_Z_int { \int_div_truncate:nn { 8 * \l_easter_C_int + 5 } { 25 } - 5 }

\int_set:Nn \l_easter_D_int { \int_div_truncate:nn { 5 * \l_easter_Y_int } { 4 } - \l_easter_X_int - 10 }

\int_set:Nn \l_easter_E_int { \int_mod:nn { 11 * \l_easter_G_int + 20 + \l_easter_Z_int - \l_easter_X_int } { 30 } }

% \int_mod:nn behaves strangely. \int_compare:nNnT { \l_easter_E_int } < { 0 } { \int_add:Nn \l_easter_E_int { 30 } }

\int_compare:nNnTF { \l_easter_E_int } = { 25 } { % true \int_compare:nNnT { \l_easter_G_int } > { 11 } { % true \int_incr:N \l_easter_E_int } } { % false \int_compare:nNnT { \l_easter_E_int } = { 24 } { % true \int_incr:N \l_easter_E_int } }

\int_set:Nn \l_easter_N_int { 44 - \l_easter_E_int }

\int_compare:nNnT { \l_easter_N_int } < { 21 } { % true \int_add:Nn \l_easter_N_int { 30 } }

\int_add:Nn \l_easter_N_int { 7 - \int_mod:nn { \l_easter_D_int + \l_easter_N_int } { 7 } }

\int_compare:nNnTF { \l_easter_N_int } > { 31 } { % true \int_sub:Nn \l_easter_N_int { 31 } \int_set:Nn \l_easter_M_int { 4 } % April } { % false \int_set:Nn \l_easter_M_int { 3 } % March }

\pgfcalendardatetojulian { \l_easter_Y_int - \l_easter_M_int - \l_easter_N_int } { \l_easter_julian_day_int }

}

\pgfkeys{/pgf/calendar/Easter/.default = 0} \pgfkeys{/pgf/calendar/Easter/.code = { \easter_sunday:n { \pgfcalendarifdateyear } \int_compare:nNnT { \pgfcalendarifdatejulian } = {\l_easter_julian_day_int + #1} { \pgfcalendarmatchestrue } } }

\int_new:N \l_advent_Y_int \int_new:N \l_advent_xmas_julian_day_int \int_new:N \l_advent_xmas_week_day_int \int_new:N \l_advent_julian_day_int

\cs_new:Nn \advent_sunday:n {

\int_set:Nn \l_advent_Y_int { #1 }

\pgfcalendardatetojulian { \l_advent_Y_int - 12 - 25 } { \l_advent_xmas_julian_day_int }

\pgfcalendarjuliantoweekday { \l_advent_xmas_julian_day_int } { \l_advent_xmas_week_day_int }

\int_set:Nn \l_advent_julian_day_int { \l_advent_xmas_julian_day_int - \l_advent_xmas_week_day_int - 22 }

}

\ExplSyntaxOff

\pgfkeys{/tikz/observance/.code = { \addtext{#1} } }

\pgfkeys{/tikz/anniversary/.code 2 args=\addbirthday{#1}{#2}} \pgfkeys{/tikz/anniversary_dead/.code 2 args=\addbirthdaydead{#1}{#2}} \pgfkeys{/tikz/date_of_death/.code 2 args=\adddateofdeath{#1}{#2}}

\pgfkeys{/tikz/day code = { \node (lower right) at (-1pt,1pt){}; \node (upper left) at (-\cellwidth +1pt,\cellheight -1pt){}; \node (day of month) at (-\cellwidth + 3pt,0.3\cellheight) [above right,font=\bfseries\Large] {\tikzdaytext};

\node (birthdays) at (-\cellwidth +2pt,\cellheight -2pt)

[below right,align=left,text width=\cellwidth-3pt, font=\tiny\bfseries,blue] {\showbirthdays};

\node (name of day) at (-\cellwidth +2pt,8pt)

[below right,align=left,text width=\cellwidth-\pgflinewidth, font=\tiny,green] {\showtext};

\node[draw,
      fit=(lower right) (upper left),
      inner sep=0mm] {};

} }

\pgfkeys{/tikz/inner sep = 0pt} \pgfkeys{/tikz/day xshift=\cellwidth} \pgfkeys{/tikz/day yshift=\cellheight} \pgfkeys{/tikz/month yshift=0mm}

\newlength{\cellheight} \setlength{\cellheight}{13mm} \newlength{\cellwidth} \setlength{\cellwidth}{68mm}

\begin{document}

\centering

\begin{tikzpicture}[thick] \calendar[dates=2021-01-01 to 2021-12-last, week list, day headings={font=\footnotesize}, day letter headings ] if (%Sunday, % Easter=-3, % Maundy Thursday Easter=-2, % Good Friday Easter, % Easter Sunday Easter=1, % Easter Monday Easter=39, % Feast of the Ascension Easter=49, % Pentecost Easter=50, % Whit Monday equals=01-01,%Neujahr equals=03-08,%Internationaler Frauentag (nur Berlin) equals=05-01,%Tag der Arbeit equals=10-03,%Tag der deutschen Einheit equals=12-25,%1. und 2. Weihnachtsfeiertag equals=12-26) [red] if (Easter=-48) [observance=Rosenmontag] if (Easter=-46) [observance=Aschermittwoch] if (Easter=-7) [observance=Palmsonntag] if (Easter=-3) [observance=Gründonnerstag] if (Easter=-2) [observance=Karfreitag] if (Easter) [observance=Ostersonntag] if (Easter=1) [observance=Ostermontag] if (Easter=39) [observance=Christi Himmelfahrt] if (Easter=39) [observance=Vatertag] if (Easter=49) [observance=Pfingstsonntag] if (Easter=50) [observance=Pfingstmontag] if (Easter=59) [observance=Fronleichnam] if (equals=01-01) [observance=Neujahr] if (equals=01-06) [observance=Heilige drei Könige] if (equals=02-14) [observance=Valentinstag] if (equals=03-08) [observance=Internationaler Frauentag] if (equals=05-01) [observance=Tag der Arbeit] if (equals=05-08) [observance=Tag der Befreiung / Ende WWII 1945] if (equals=08-15) [observance=Mariä Himmelfahrt] if (equals=10-03) [observance=Tag der deutschen Einheit 1990] if (equals=10-31) [observance=Reformationstag] if (equals=10-31) [observance=Halloween] if (equals=11-01) [observance=Allerheiligen] if (equals=11-09) [observance=Fall der Mauer 1989] if (equals=11-09) [observance=Novemberprogrome 1938] if (equals=12-24) [observance=Heilig Abend] if (equals=12-25) [observance=1. Weihnachtstag] if (equals=12-26) [observance=2. Weihnachtstag] if (equals=12-31) [observance=Silvester] if (and={between=11-16 and 11-22}{Wednesday}) [observance=Buß- und Bettag] if (and={between=11-13 and 11-19}{Sunday}) [observance=Volkstrauertag] if (and={between=11-20 and 11-26}{Sunday}) [observance=Totensonntag] if (and={between=11-27 and 12-03}{Sunday}) [observance=1. Advent] if (and={between=12-04 and 12-10}{Sunday}) [observance=2. Advent] if (and={between=12-11 and 12-17}{Sunday}) [observance=3. Advent] if (and={between=12-18 and 12-24}{Sunday}) [observance=4. Advent] if (and={between=03-25 and 03-31}{Sunday}) [observance=Beginn Sommerzeit]%letzter Sonntag im März if (and={between=10-25 and 10-31}{Sunday}) [observance=Ende Sommerzeit]%letzter Sonntag im Oktober if (and={between=05-08 and 05-14}{Sunday}) [observance=Muttertag]%2. Sonntag im Mai if (equals=12-06) [observance=Nikolaus] if (equals=07-17) [anniversary={John Smith}{2018}] if (equals=12-07) [anniversary={John Smith}{1982}] if (equals=01-04) [anniversary={John Smith}{1983}] if (equals=01-18) [anniversary={John Smith}{1985}] if (equals=10-23) [anniversary={John Smith}{1986}] if (equals=08-29) [anniversary={John Smith}{1954}] if (equals=10-14) [anniversary={John Smith}{1954}] if (equals=03-01) [anniversary_dead={John Smith}{1923}] if (equals=05-24) [date_of_death={John Smith}{2011}] if (equals=12-01) [anniversary={John Smith}{1927}] if (equals=08-29) [anniversary={John Smith}{2013}] if (equals=08-29) [anniversary={John Smith}{1981}] ; \end{tikzpicture}

\end{document}

epR8GaYuh
  • 2,432

1 Answers1

0

The following code solves the problem:

\int_new:N \g_counter_int
\cs_new_protected:Npn \bdaycal_output_direct_text:
 {
  \seq_map_inline:Nn \g_bdaycal_input_seq_text
   {
 \int_add:Nn \g_counter_int { 1 }
    ##1
    \int_compare:nNnF {\g_counter_int}={\seq_count:N \g_bdaycal_input_seq_text}{,~}
   }
  \seq_gclear:N \g_bdaycal_input_seq_text
 \int_set:Nn \g_counter_int {0}
 }

\cs_new_protected:Npn \bdaycal_output_direct_birthday: { \seq_map_inline:Nn \g_bdaycal_input_seq_birthday { \int_add:Nn \g_counter_int { 1 } ##1 \int_compare:nNnF {\g_counter_int}={\seq_count:N \g_bdaycal_input_seq_birthday}{,~} } \seq_gclear:N \g_bdaycal_input_seq_birthday \int_set:Nn \g_counter_int {0} }