3

I have kludged a fix to the small caps and alternating color requirement for the day headings. My code now reflects those changes, and I describe them at the end of this question for those who may be interested.

However, there are still two items I am struggling to accomplish.

(1) I would like the weekday-names to align flush left in their column rather than centered. I feel I should be able to accomplish this by adjusting anchors, but of labels, the calendar, or something else, I don't know.

(2) Also, on either side of the month name, I would like the year written, aligned with the rightmost text and leftmost text respectively.(That is, the initial 2018 flush left with the weekdays, and the 8 in the second year number aligning with the last daynumber, e.g., in January, the 8 above the 9 in 29. (I have used hspace and xshift in the example, but since each monthname is a different length, a fixed space or shift will not work.)

\documentclass{article}
\usepackage[margin = 2.5cm, landscape]{geometry}
\pagestyle{empty}

\usepackage{tikz}
    \usetikzlibrary{calendar, positioning}

\makeatletter
\tikzstyle{week list}=[
    execute before day scope={%
        \ifdate{day of month=1}{\ifdate{equals=\pgfcalendarbeginiso}{}
            {% On first of month, except when first date in calendar.
            \pgfmathsetlength{\pgf@x}{\tikz@lib@cal@month@xshift}
            \pgftransformxshift{\pgf@x}
            }
        }{}
},
    execute at begin day scope={%
        \ifodd\pgfcalendarcurrentday\relax \color{red} \fi %%% <-- added line to alternate number colors {thanks to Hood Chatham}
        \pgfmathsetlength\pgf@y{\tikz@lib@cal@yshift}%
        \pgf@y=\pgfcalendarcurrentweekday\pgf@y%
        \pgftransformyshift{-\pgf@y}%
        },
   execute after day scope={%
        \ifdate{Sunday}{%
        \pgfmathsetlength{\pgf@x}{\tikz@lib@cal@xshift}%
        \pgftransformxshift{\pgf@x}
        }{}%
    },
    % % According to Berteun the following should be defined:
    % << tikz@lib@cal@width=7 >>. (I don't know why.)
    ]

    \tikzoption{day headings}{\tikzstyle{day heading}=[#1]}
    \tikzstyle{day heading}=[]
    \tikzstyle{day letter headings}=[
    execute before day scope={ \ifdate{day of month=1}{%
        \pgfmathsetlength\pgf@ya{\tikz@lib@cal@yshift}%
        \pgfmathsetlength\pgf@xa{\tikz@lib@cal@xshift}%
        \pgftransformxshift{\pgf@xa}
        \foreach \d/\l in {
    0/\sc{Monday},1/\sc\textcolor{red}{Tuesday},     % <----------------------- |
    2/\sc{Wednesday},3/\sc\textcolor{red}{Thursday},    % <----- modified lines |
    4/\sc{Friday},5/\sc\textcolor{red}{Saturday},6/\sc{Sunday}}{     % <------- |
% had been: {0/Monday,1/Tuesday,2/Wednesday,
%            3/Thursday,4/Friday,5/Saturday,6/Sunday} {
        \pgf@ya=\d\pgf@ya%
        \pgftransformxshift{-\pgf@xa}%
        \pgftransformyshift{-\pgf@ya}%
        \node[every day, day heading, anchor = base]{\l};%
            }
        }{}%
    }%
]
\makeatother

\newcommand{\calyear}{2018}
\newcommand{\mon}[1]{\calendar[dates = \calyear-#1-01 to \calyear-#1-last];}

\begin{document}
    \begin{tikzpicture}[every calendar/.style = {
        month label above centered,
        month text = {\Large \%y- \hspace{.5cm} \textsc{\%mt} \hspace{.5cm} \%y- },
        week list,
        day letter headings,
        day heading/.style={xshift=-2cm} % <--- modified line
        % had been: day heading/.style={red, xshift=-2cm}
    }]
    \matrix (Calendar) [column sep = 4em, row sep = 3em] {
        \mon{01} & \mon{02} & \mon{03} \\
        \mon{04} & \mon{05} & \mon{06} \\
        \mon{07} & \mon{08} & \mon{09} \\
        \mon{10} & \mon{11} & \mon{12} \\ };
    \end{tikzpicture}
\end{document}

To get the names of the weekdays to be printed in small caps, alternating between black and red, I inserted commands for small caps and red text into the line where the text of the day headings were originally given; I also removed [red] from the style definition of day heading/.style since changing the default black to red three times required fewer color changes (three to red vs. four to black). The relevant lines now read:

\foreach \d/\l in {
    0/\sc{Monday},1/\sc\textcolor{red}{Tuesday},2/\sc{Wednesday},
    3/\sc\textcolor{red}{Thursday},4/\sc{Friday},
    5/\sc\textcolor{red}{Saturday},6/\sc{Sunday}}

and

day heading/.style={xshift=-2cm} 

I'm sure there is a better way to accomplishing this rather than "hard-wiring" for each instance of a day heading -- but the kludge works.

1 Answer 1

3

I made a few changes: I assume you want the calendar to be centered on the page both vertically and horizontally. To do this, I set the margins to be zero and use the \centering command to horizontally center. To vertically center the calendar, I say \let\@texttop\vfill\let\@textbottom\vfill.

Instead of manually entering each weekday in the loop to create the weekdays, you can use \pgfcalendarweekdayname{\d} where \d is the day of the week. To make the odd days red, add \ifodd\d \color{red}\fi before this.

To get the days to be aligned left, you need to specify the text width, which will make the node a fixed width rectangle and align the text to the left inside of it. The longest weekday name is Wednesday so we say text width = width("Wednesday").

To get the length of the heading correct, we need to already know the width of the month. pgfcalendar places the month label before it draws the rest of the calendar, which is inconvenient for this. Instead, I place the month heading in the \mon macro after the rest of the month is drawn. Then we can find the distance between the west anchor of a day node and the east anchor of the node for the last day in the month and set the textwidth of the month title to be this (minus a small offset to account for the inner sep of the weekday and month nodes).

\documentclass{article}
\usepackage[margin = 0cm, landscape]{geometry}
\makeatletter
\AtBeginDocument{\centering}
\let\@texttop\vfill
\let\@textbottom\vfill
\pagestyle{empty}

\usepackage{tikz}
\usetikzlibrary{calendar, positioning}

\tikzstyle{week list}=[
    execute before day scope={%
        \ifdate{day of month=1}{\ifdate{equals=\pgfcalendarbeginiso}{}
            {% On first of month, except when first date in calendar.
            \pgfmathsetlength{\pgf@x}{\tikz@lib@cal@month@xshift}
            \pgftransformxshift{\pgf@x}
            }
        }{}
},
    execute at begin day scope={%
        \ifodd\pgfcalendarcurrentday\relax \color{red} \fi %%% <-- added line to alternate number colors {thanks to Hood Chatham}
        \pgfmathsetlength\pgf@y{\tikz@lib@cal@yshift}%
        \pgf@y=\pgfcalendarcurrentweekday\pgf@y%
        \pgftransformyshift{-\pgf@y}%
        },
   execute after day scope={%
        \ifdate{Sunday}{%
        \pgfmathsetlength{\pgf@x}{\tikz@lib@cal@xshift}%
        \pgftransformxshift{\pgf@x}
        }{}%
    },
    % % According to Berteun the following should be defined:
    % << tikz@lib@cal@width=7 >>. (I don't know why.)
    ]

    \tikzoption{day headings}{\tikzstyle{day heading}=[#1]}
    \tikzstyle{day heading}=[]
    \tikzstyle{day letter headings}=[
    execute before day scope={ \ifdate{day of month=1}{%
        \pgfmathsetlength\pgf@ya{\tikz@lib@cal@yshift}%
        \pgfmathsetlength\pgf@xa{\tikz@lib@cal@xshift}%
        \pgftransformxshift{\pgf@xa}
        \foreach \d/\l in {0,...,6}{     % <------- |
            \pgf@ya=\d\pgf@ya%
            \pgftransformxshift{-\pgf@xa}%
            \pgftransformyshift{-\pgf@ya}%
            \node[every day, day heading, anchor = base,text width=width("Wednesday")] (day-\d) {\ifodd\d \color{red}\fi\sc{\pgfcalendarweekdayname{\d}}};%
        }
    }{}}%
]

\newcount\tempcount
\newcommand{\calyear}{2018}
\newcommand{\mon}[1]{
    \calendar (cal) [dates = \calyear-#1-01 to \calyear-#1-last]; 
    % Add the title
    % Get the date of the last day of the month
    \pgfcalendardatetojulian{\calyear-#1-last}{\tempcount}
    \pgfcalendarjuliantodate{\tempcount}{\throwaway}{\throwaway}{\lastday}
    % Find the distance between the west end of the weekday and the east end of the last day of the month
    \pgfpointdiff{\pgfpointanchor{day-0}{west}}{\pgfpointanchor{cal-\calyear-#1-\lastday}{east}}
    % The width of the month should be this distance minus some extra padding
    \edef\monthwidth{\the\dimexpr\pgf@x-7pt}
    % Draw the month title
    \node[above left=0em of day-0,above right, text width=\monthwidth] {\Large \calyear\hfill \textsc{\pgfcalendarmonthname{#1}} \hfill \calyear}; 
}
\makeatother
\begin{document}
    \begin{tikzpicture}[every calendar/.style = {
        week list,
        day letter headings,
        day heading/.style={xshift=-2cm} % <--- modified line
    }]
    \matrix (Calendar) [column sep = 4em, row sep = 3em] {
        \mon{01} & \mon{02} & \mon{03} \\
        \mon{04} & \mon{05} & \mon{06} \\
        \mon{07} & \mon{08} & \mon{09} \\
        \mon{10} & \mon{11} & \mon{12} \\ };
    \end{tikzpicture}
\end{document} 
3
  • I have been unable to compile. The error is: Undefined control sequence. \tikz@text@width ->calendarwidth 1.76 \mon{01} & \mon{02} & \mon{03} \\
    – Bryan H-M
    Jan 9, 2018 at 3:23
  • Sorry, I messed it up in one of the edits. It should be fixed now. Jan 9, 2018 at 5:45
  • Runs like a charm. I was hoping I could figure out the error before bothering you again... but I just didn't see it. I also appreciated seeing how to center the tikzpic on the page both horizontally and vertically.
    – Bryan H-M
    Jan 9, 2018 at 19:10

You must log in to answer this question.

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