TikZ 日历的 \foreach 中的前导零

TikZ 日历的 \foreach 中的前导零

TikZcalendar库为每一天创建一个名为 的节点。但是从 到有(<name>-<year>-<month>-<day>)一个前导零,也就是说,要使用第一天的节点,我们必须通过 来引用它。<day>19(<name>-<year>-<month>-01)

由于我尝试使用\foreach循环连接一些节点,因此在处理前导零时遇到了麻烦。例如,

! Package pgf Error: No shape named cal-2015-01-2 is known.
! Package pgf Error: No shape named cal-2015-09-4 is known.

但如果我插入前导零,(cal-2015-09-0\x.north east)错误就会变为

! Package pgf Error: No shape named cal-2015-01-016 is known.

因此,我认为只有两位数的整数可以解决问题。

我希望有与下面第一个日历相同的两条虚线,但可以将其转换为分隔其他周末。

平均能量损失

\documentclass[11pt]{report}
\usepackage[margin=1cm,landscape,a4paper]{geometry}
\usepackage{tikz}
\usetikzlibrary{calendar,calc,math}

\begin{document}

\begin{tikzpicture}%
  [every day/.style={anchor=mid},
   every node/.style={inner sep=2pt,rectangle,thick}
  ]
\calendar (cal)%
 [dates=\the\year-1-1 to \the\year-12-last,
  month list,
  month label left,
  month text=\textcolor{black}{\%mt},
  month yshift=1.7em,
  black
 ]
if (Saturday) [blue]
if (Sunday)   [red]
;
\draw[dashed]
  ( $(cal-\the\year-01-02.north east)!.5!(cal-\the\year-01-03.north west)$ ) --
  ( $(cal-\the\year-12-04.south east)!.5!(cal-\the\year-12-05.south west)$ )
%%
  ( $(cal-\the\year-01-04.north east)!.5!(cal-\the\year-01-05.north west)$ ) --
  ( $(cal-\the\year-12-06.south east)!.5!(cal-\the\year-12-07.south west)$ )
;
\end{tikzpicture}

\vfill\noindent\hrulefill\vfill

\begin{tikzpicture}%
  [every day/.style={anchor=mid},
   every node/.style={inner sep=2pt,rectangle,thick}
  ]
\calendar (cal)%
 [dates=\the\year-1-1 to \the\year-12-last,
  month list,
  month label left,
  month text=\textcolor{black}{\%mt},
  month yshift=1.7em,
  black
 ]
if (Saturday) [blue]
if (Sunday)   [red]
;
%%  use only one foreach below
%% the first has problems with leading zeros on day numbers
%%
\foreach \i in {0,7,...,31}{% should be tested if is >31
%\foreach \i in {16,23,...,31}{% should be tested if is >31
%%
%% January 02 and 04 are starting days
  \tikzmath{integer \xaa; \xaa = 2+\i;}
  \tikzmath{integer \xab; \xab = \xaa+1;}
  \tikzmath{integer \xba; \xba = 4+\i;}
  \tikzmath{integer \xbb; \xbb = \xba+1;}
%% December 04 and 06 are ending days
  \tikzmath{integer \yaa; \yaa = 4+\i;}
  \tikzmath{integer \yab; \yab = \yaa+1;}
  \tikzmath{integer \yba; \yba = 6+\i;}
  \tikzmath{integer \ybb; \ybb = \yba+1;}
\draw[dashed]
  ( $(cal-\the\year-01-\xaa.north east)!.5!(cal-\the\year-01-\xab.north west)$ ) --
  ( $(cal-\the\year-12-\xba.south east)!.5!(cal-\the\year-12-\xbb.south west)$ )
%%
  ( $(cal-\the\year-01-\yaa.north east)!.5!(cal-\the\year-01-\yab.north west)$ ) --
  ( $(cal-\the\year-12-\yba.south east)!.5!(cal-\the\year-12-\ybb.south west)$ )
;
}
\end{tikzpicture}

\end{document}

在此处输入图片描述

答案1

更新

整个问题的优雅解决方案:

这是另一个简化的解决方案,它避免了两位数问题,并添加了 OP 最终请求的最后两列。这个想法是日历列之间有一段默认距离。这里,对于 11pt 文档,它是。我们通过明确设置选项并将其传递给日历命令来3.5ex确保它是。3.5exday xshift=3.5ex

接下来,我们执行一个\foreach循环来绘制两条垂直线,并在一周后重复此操作,如下xshift所示7*3.5ex

\foreach \i in {0,...,4}{%
\pgfmathparse{3.5*7*\i} \edef\w{\pgfmathresult}
\pgfmathparse{\w+2*3.5} \edef\x{\pgfmathresult}
\draw[dashed]
([xshift=\w ex]$(cal-\the\year-01-02.north east)!.5!(cal-\the\year-01-03.north west)$) --
([xshift=\w ex]$(cal-\the\year-12-04.south east)!.5!(cal-\the\year-12-05.south west)$)
([xshift=\x ex]$(cal-\the\year-01-02.north east)!.5!(cal-\the\year-01-03.north west)$) --
([xshift=\x ex]$(cal-\the\year-12-04.south east)!.5!(cal-\the\year-12-05.south west)$);
} 

该循环将所有垂直线绘制成如下形式:

在此处输入图片描述

现在总的简化代码如下:

\documentclass[11pt]{report}
\usepackage[margin=1cm,landscape,a4paper]{geometry}
\usepackage{tikz}
\usetikzlibrary{calendar,calc,math}
\begin{document}

\begin{tikzpicture}%
  [every day/.style={anchor=mid},
   every node/.style={inner sep=2pt,rectangle,thick}
  ]
\calendar (cal)%
 [dates=\the\year-1-1 to \the\year-12-last,
  month list,
  month label left,
  month text=\textcolor{black}{\%mt},
  month yshift=1.7em,
  black
 ]
if (Saturday) [blue]
if (Sunday)   [red];

\draw[dashed]
  ( $(cal-\the\year-01-02.north east)!.5!(cal-\the\year-01-03.north west)$ ) --
  ( $(cal-\the\year-12-04.south east)!.5!(cal-\the\year-12-05.south west)$ )
%%
  ( $(cal-\the\year-01-04.north east)!.5!(cal-\the\year-01-05.north west)$ ) --
  ( $(cal-\the\year-12-06.south east)!.5!(cal-\the\year-12-07.south west)$ );
\end{tikzpicture}

\vfill\noindent\hrulefill\vfill

\begin{tikzpicture}%
  [every day/.style={anchor=mid},
   every node/.style={inner sep=2pt,rectangle,thick}
  ]
\calendar[day xshift=3.5ex](cal)%
 [dates=\the\year-1-1 to \the\year-12-last,
  month list,
  month label left,
  month text=\textcolor{black}{\%mt},
  month yshift=1.7em,
  black
 ]
if (Saturday) [blue]
if (Sunday)   [red];

% use only one foreach below
% the first has problems with leading zeros on day numbers

\foreach \i in {0,...,4}{%
\pgfmathparse{3.5*7*\i} \edef\w{\pgfmathresult}
\pgfmathparse{\w+2*3.5} \edef\x{\pgfmathresult}
\draw[dashed]
([xshift=\w ex]$(cal-\the\year-01-02.north east)!.5!(cal-\the\year-01-03.north west)$) --
([xshift=\w ex]$(cal-\the\year-12-04.south east)!.5!(cal-\the\year-12-05.south west)$)
%
([xshift=\x ex]$(cal-\the\year-01-02.north east)!.5!(cal-\the\year-01-03.north west)$) --
([xshift=\x ex]$(cal-\the\year-12-04.south east)!.5!(cal-\the\year-12-05.south west)$);
}
\end{tikzpicture}

\end{document}

解决方案 1

受@clemens提到的错误消息的启发,一个简单的解决方案可能是避免超过31天。为了实现这一点,观察最大的节点号\ybb = \yba+1,它等于\i+7因为\yba=\i+6。后者的值应该最大化为31。所以,,max{ \i }= 24这仅仅意味着条件:

\ifnum\i<25\draw ... \else\fi 

以下是第二种解决方案的完整代码(其结果与上述相同):

\documentclass[11pt]{report}
\usepackage[margin=1cm,landscape,a4paper]{geometry}
\usepackage{tikz}
\usetikzlibrary{calendar,calc,math}
\makeatletter
\let\twodigits\two@digits
\makeatother

\begin{document}

\begin{tikzpicture}%
  [every day/.style={anchor=mid},
   every node/.style={inner sep=2pt,rectangle,thick}
  ]
\calendar (cal)%
 [dates=\the\year-1-1 to \the\year-12-last,
  month list,
  month label left,
  month text=\textcolor{black}{\%mt},
  month yshift=1.7em,
  black
 ]
if (Saturday) [blue]
if (Sunday)   [red];

\draw[dashed]
  ( $(cal-\the\year-01-02.north east)!.5!(cal-\the\year-01-03.north west)$ ) --
  ( $(cal-\the\year-12-04.south east)!.5!(cal-\the\year-12-05.south west)$ )
%%
  ( $(cal-\the\year-01-04.north east)!.5!(cal-\the\year-01-05.north west)$ ) --
  ( $(cal-\the\year-12-06.south east)!.5!(cal-\the\year-12-07.south west)$ );
\end{tikzpicture}

\vfill\noindent\hrulefill\vfill

\begin{tikzpicture}%
  [every day/.style={anchor=mid},
   every node/.style={inner sep=2pt,rectangle,thick}
  ]
\calendar(cal)%
 [dates=\the\year-1-1 to \the\year-12-last,
  month list,
  month label left,
  month text=\textcolor{black}{\%mt},
  month yshift=1.7em,
  black
 ]
if (Saturday) [blue]
if (Sunday)   [red];

%%  use only one foreach below
%% the first has problems with leading zeros on day numbers
%%
\foreach \i in {0,7,...,31}{% should be tested if is >31
%\foreach \i in {16,23,...,31}{% should be tested if is >31
%%
%% January 02 and 04 are starting days
  \tikzmath{integer \xaa; \xaa = 2+\i;}
  \tikzmath{integer \xab; \xab = \xaa+1;}
  \tikzmath{integer \xba; \xba = 4+\i;}
  \tikzmath{integer \xbb; \xbb = \xba+1;}
%% December 04 and 06 are ending days
  \tikzmath{integer \yaa; \yaa = 4+\i;}
  \tikzmath{integer \yab; \yab = \yaa+1;}
  \tikzmath{integer \yba; \yba = 6+\i;}
  \tikzmath{integer \ybb; \ybb = \yba+1;}
\ifnum\i<25
\draw[dashed]
  ($(cal-\the\year-01-\twodigits\xaa.north east)!.5!(cal-\the\year-01-\twodigits\xab.north west)$) --
  ($(cal-\the\year-12-\twodigits\xba.south east)!.5!(cal-\the\year-12-\twodigits\xbb.south west)$)
%%
  ($(cal-\the\year-01-\twodigits\yaa.north east)!.5!(cal-\the\year-01-\twodigits\yab.north west)$) --
  ($(cal-\the\year-12-\twodigits\yba.south east)!.5!(cal-\the\year-12-\twodigits\ybb.south west)$);
\else\fi
}
\end{tikzpicture}

\end{document}

在此处输入图片描述

答案2

LaTeX 有(可扩展的)函数\two@digits,它接受一个整数作为输入,如果数字小于 10,则在前导 0 处添加。因此,你可以放置

\makeatletter
\let\twodigits\two@digits
\makeatother

在你的序言中的某个地方,然后使用

\draw[red] 
  ($(cal-2015-09-\twodigits\x.north east)!.5!(cal-2015-09-05.north west)$)--
  ($(cal-2016-02-\twodigits\y.south east)!.5!(cal-2016-02-06.south west)$) ;

在你的第一个例子中

$\frac{\twodigits\i}{\twodigits\x}$

在你的第二个例子中。


编辑根据更新后的问题,代码部分如下:

\draw[dashed]
  ( $(cal-\the\year-01-\twodigits\xaa.north east)!.5!(cal-\the\year-01-\twodigits\xab.north west)$ ) --
  ( $(cal-\the\year-12-\twodigits\xba.south east)!.5!(cal-\the\year-12-\twodigits\xbb.south west)$ )
%%
  ( $(cal-\the\year-01-\twodigits\yaa.north east)!.5!(cal-\the\year-01-\twodigits\yab.north west)$ ) --
  ( $(cal-\the\year-12-\twodigits\yba.south east)!.5!(cal-\the\year-12-\twodigits\ybb.south west)$ )
;

顺便说一句:这仍然会产生错误

! Package pgf Error: No shape named cal-2015-12-32 is known.

但现在不是由于缺少零,而是因为4+\i最终大于 31。

相关内容