![采用 Moleskine/Leuchtturm 每周格式的 LaTeX 日历布局](https://linux22.com/image/341977/%E9%87%87%E7%94%A8%20Moleskine%2FLeuchtturm%20%E6%AF%8F%E5%91%A8%E6%A0%BC%E5%BC%8F%E7%9A%84%20LaTeX%20%E6%97%A5%E5%8E%86%E5%B8%83%E5%B1%80.png)
我正在尝试创建自己的 A5 页面,其周历格式类似于标准 Moleskine 或 Leuchtturm 周历(参见附图左侧部分),以便为我的 A5 Atoma 笔记本制作自己的日历,但可以自动添加朋友的生日。
系统:Windows,MiKTeX
看来,使用 TikZ 应该可以实现(http://www.texample.net/tikz/examples/feature/calendar-library/),但是,我找不到符合我想要的风格的例子。
您对于如何开始有什么提示、技巧或建议吗?
提前致谢,迈克尔
答案1
免责声明:这还不是一个功能齐全的解决方案。它计划进行更新。
以下是一个答案,它生成一个 PDF,每页显示一周,为期一年,从包含 1 月 1 日的那一周开始。但是,它尚未实现自动添加亲属生日的功能。它也不支持闰年。
工作准则
每周生成一个单独的tikzpicture
。文档主体只是一个循环,根据tikzpicture
需要多次调用创建该 的宏。(请注意,tikz
给出的选项会\documentclass{standalone}
为每张图片创建一个新页面。)
作为代码的输入,您手动设置:
- 您要生成日历的年份,
- 一月一日(星期一、星期二等)
- 今年有多少周,
- 是什么ISO 周日期一月一日。
然后就是关于计数器的全部内容,如下面的代码所示。
代码
\documentclass[tikz]{standalone}% Does not support leap years.
%% Load needed packages
\usepackage{lmodern}
\usepackage{tikz}
\usetikzlibrary{positioning}
\usepackage{ifthen}
%% Create needed conters
\newcounter{ThisYear}
\newcounter{NewYearsDay}
\newcounter{NewYearsWeek}
\newcounter{NumberOfWeeksThisYear}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% SET VARIABLES HERE %
% Year number you want to generate the calendar for:
\setcounter{ThisYear}{2017}
% Which day is the January, 1st? (1 for Monday, 2 for Tuesday, etc.)
\setcounter{NewYearsDay}{7}
% Which week does January, 1st belongs to?
% Choose 52 (sometimes 53) or 1. Week 1 is not necessary the week of Jan, 1st; but *it is the week of Jan, 4th.*)
\setcounter{NewYearsWeek}{52}
% How many weeks this year? (Choose 52 or 53, appropriately)
\setcounter{NumberOfWeeksThisYear}{52}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Let's begin with messy stuff
% If Jan, 1st is not on Week #1...
\ifthenelse{\value{NewYearsWeek}>51}{
\addtocounter{ThisYear}{-1} % start calendar with the last week of the previous year
\stepcounter{NumberOfWeeksThisYear} % increase amount of weeks to generate
}{}
% Following counter is the backbone of the calendar generation.
\newcounter{NDOYnumber} %% Nth Day Of the Year: 1 for Jan, 1st; 2 for Jan, 2nd; etc.
% Set the first day of the calendar (i.e. Monday of the first generated week)
\ifthenelse{\value{NewYearsDay}=1}{
% Monday = Jan, 1st
\setcounter{NDOYnumber}{1}
}{
% Monday belongs to previous year
\setcounter{NDOYnumber}{367}
\addtocounter{NDOYnumber}{-\value{NewYearsDay}}
}
% Store day's quantieme (1 for Jan, 1st & Feb, 1st, etc.; 17 for Jan, 17th, Feb, 17th, etc.)
\newcounter{NDOYquantieme}
% Store day's month number (1 for Jan, 2 for Feb, etc.)
\newcounter{NDOYmonthnumber}
% Internal counter
\newcounter{tempNDOY}
% Based on `NDOYnumber` value, compute month number and quantieme
\newcommand{\NDOYtomonthnumber}{%
\setcounter{tempNDOY}{\value{NDOYnumber}}%
\setcounter{NDOYmonthnumber}{1}%
\ifthenelse{\value{tempNDOY}<32}{% %% JANUARY
\setcounter{NDOYquantieme}{\value{tempNDOY}}%% Set January quantieme
}{%
\addtocounter{tempNDOY}{-31}%
\stepcounter{NDOYmonthnumber}% %% FEBRUARY
\ifthenelse{\value{tempNDOY}<29}{%
\setcounter{NDOYquantieme}{\value{tempNDOY}}%
}{%
\addtocounter{tempNDOY}{-28}%
\stepcounter{NDOYmonthnumber}% %% MARCH
\ifthenelse{\value{tempNDOY}<32}{%
\setcounter{NDOYquantieme}{\value{tempNDOY}}%
}{%
\addtocounter{tempNDOY}{-31}%
\stepcounter{NDOYmonthnumber}% %% APRIL
\ifthenelse{\value{tempNDOY}<31}{%
\setcounter{NDOYquantieme}{\value{tempNDOY}}%
}{%
\addtocounter{tempNDOY}{-30}%
\stepcounter{NDOYmonthnumber}% %% MAY
\ifthenelse{\value{tempNDOY}<32}{%
\setcounter{NDOYquantieme}{\value{tempNDOY}}%
}{%
\addtocounter{tempNDOY}{-31}%
\stepcounter{NDOYmonthnumber}% %% JUNE
\ifthenelse{\value{tempNDOY}<31}{%
\setcounter{NDOYquantieme}{\value{tempNDOY}}%
}{%
\addtocounter{tempNDOY}{-30}%
\stepcounter{NDOYmonthnumber}% %% JULY
\ifthenelse{\value{tempNDOY}<32}{%
\setcounter{NDOYquantieme}{\value{tempNDOY}}%
}{%
\addtocounter{tempNDOY}{-31}%
\stepcounter{NDOYmonthnumber}% %% AUGUST
\ifthenelse{\value{tempNDOY}<32}{%
\setcounter{NDOYquantieme}{\value{tempNDOY}}%
}{%
\addtocounter{tempNDOY}{-31}%
\stepcounter{NDOYmonthnumber}% %% SEPTEMBER
\ifthenelse{\value{tempNDOY}<31}{%
\setcounter{NDOYquantieme}{\value{tempNDOY}}%
}{%
\addtocounter{tempNDOY}{-30}%
\stepcounter{NDOYmonthnumber}% %% OCTOBER
\ifthenelse{\value{tempNDOY}<32}{%
\setcounter{NDOYquantieme}{\value{tempNDOY}}%
}{%
\addtocounter{tempNDOY}{-31}%
\stepcounter{NDOYmonthnumber}% %% NOVEMBER
\ifthenelse{\value{tempNDOY}<31}{%
\setcounter{NDOYquantieme}{\value{tempNDOY}}%
}{%
\addtocounter{tempNDOY}{-30}%
\stepcounter{NDOYmonthnumber}% %% DECEMBER
\setcounter{NDOYquantieme}{\value{tempNDOY}}%
}}}}}}}}}}}%
}
% Based on previously computed `NDOYmonthnumber` value, return month name
\newcommand{\NDOYtomonth}{%
\foreach \monthnumber/\monthname in {1/Januar, 2/Februar, 3/März, 4/April, 5/Mai, 6/Juni, 7/Juli, 8/August, 9/September, 10/Oktober, 11/November, 12/Dezember}{%
\ifthenelse{\value{NDOYmonthnumber}=\monthnumber}{\monthname}{}%
}
}
% 'Smartly' increase `NDOYnumber` value (i.e. reset to 1 after December, 31st)
\newcommand{\stepNDOY}{%
\ifthenelse{\value{NDOYnumber}=365}{%
\setcounter{NDOYnumber}{1}%
\stepcounter{ThisYear}
}{%
\stepcounter{NDOYnumber}%
}%
}
% Defines the `tikzpicture` used to print a week (i.e. calendar page)
\newcommand{\printweek}[1]{% argument = \value{NDOYnumber}, i.e. Monday's day-of-the-year number
\begin{tikzpicture}[%
inner sep=3 pt,
dayname/.style={%
node font=\footnotesize,
},
daynumber/.style={%
anchor=north east,
node font=\normalsize\bfseries,
},
xscale = 3,
yscale=-1.5,% CAUTION: axis direction reversed!
]
\NDOYtomonthnumber%(see below)
\node (year_number) at (0,1) [anchor = south east, minimum height = 2em] {\theThisYear}; %prints year number
\node [base right = 1em of year_number, anchor=base west, node font=\large] {\NDOYtomonth}; %prints month name
%% Monday
\NDOYtomonthnumber % compute and store which month and quantieme is this day, based on `NDOYnumber` value
\node (monday_number) at (0,1) [daynumber] {\theNDOYquantieme}; % prints quantieme
\node [base right = 1em of monday_number, anchor=base west] [dayname] {Montag}; % prints day name
\stepNDOY % 'smartly' increases `NDOYnumber` value
%% Tuesday
\NDOYtomonthnumber
\node (tuesday_number) at (0,2) [daynumber] {\theNDOYquantieme};
\node [base right = 1em of tuesday_number, anchor=base west] [dayname] {Dienstag};
\stepNDOY
%% Wednesday
\NDOYtomonthnumber
\node (wednesday_number) at (0,3) [daynumber] {\theNDOYquantieme};
\node [base right = 1em of wednesday_number, anchor=base west] [dayname] {Mittwoch};
\stepNDOY
%% Thursday
\NDOYtomonthnumber
\node (thursday_number) at (0,4) [daynumber] {\theNDOYquantieme};
\node [base right = 1em of thursday_number, anchor=base west] [dayname] {Donnerstag};
\stepNDOY
%% Friday
\NDOYtomonthnumber
\node (friday_number) at (0,5) [daynumber] {\theNDOYquantieme};
\node [base right = 1em of friday_number, anchor=base west] [dayname] {Freitag};
\stepNDOY
%% Saturday
\NDOYtomonthnumber
\node (saturday_number) at (0,6) [daynumber] {\theNDOYquantieme};
\node [base right = 1em of saturday_number, anchor=base west] [dayname] {Samstag};
\stepNDOY
%% Sunday
\NDOYtomonthnumber
\node (sunday_number) at (1,6) [daynumber] {\theNDOYquantieme};
\node [base right = 1em of sunday_number, anchor=base west] [dayname] {Sonntag};
\stepNDOY
%% Draw lines
\foreach \i in {1, 1.2, ..., 7}{%
\draw [gray, thin] (2,\i) -- (4,\i);
}
\path (-0.35,0.25) -- (4,0.25);
\foreach \i in {1,...,7} {%
\draw (-0.35,\i) -- (4,\i);
}
\draw (2,1) -- (2,7);
\end{tikzpicture}%
}
\begin{document}
\foreach \n in {1,...,\value{NumberOfWeeksThisYear}}{%
\printweek{\value{NDOYnumber}}
}
\end{document}
我的代码比较臃肿,欢迎大家提出精简建议!
预览
第一个(初步)答案
这是目前一周的粗略 TikZ 结构。
请注意,由于yscale=-1
,图片的原点位于左上角(因此,y
坐标的增加意味着一周中某一天的“增加” - 在我看来,这更直观。)
\documentclass{standalone}
\usepackage{lmodern}
\usepackage{tikz}
\usetikzlibrary{positioning}
\begin{document}
\begin{tikzpicture}[%
inner sep=3 pt,
dayname/.style={%
node font=\footnotesize,
},
daynumber/.style={%
anchor=north east,
node font=\normalsize\bfseries,
},
xscale = 4,
yscale=-1,
]
\node (saturday_number) at (0,6) [daynumber] {14};
\node [base right = 1em of saturday_number, anchor=base west] [dayname] {Samstag};
\node (sunday_number) at (1,6) [daynumber] {15};
\node [base right = 1em of sunday_number, anchor=base west] [dayname] {Sonntag};
\node (friday_number) at (0,5) [daynumber] {13};
\node [base right = 1em of friday_number, anchor=base west] [dayname] {Freitag};
\node (thursday_number) at (0,4) [daynumber] {12};
\node [base right = 1em of thursday_number, anchor=base west] [dayname] {Donnerstag};
\node (wednesday_number) at (0,3) [daynumber] {11};
\node [base right = 1em of wednesday_number, anchor=base west] [dayname] {Mittwoch};
\node (tuesday_number) at (0,2) [daynumber] {10};
\node [base right = 1em of tuesday_number, anchor=base west] [dayname] {Dienstag};
\node (monday_number) at (0,1) [daynumber] {9};
\node [base right = 1em of monday_number, anchor=base west] [dayname] {Montag};
\node (year_number) at (0,1) [anchor = south east, minimum height = 2em] {2017};
\node [base right = 1em of year_number, anchor=base west, node font=\large] {Januar};
\foreach \i in {0,1,...,6} {%
\draw (-0.25,\i) -- (2,\i);
}
\node (SW-corner) at (0,7) {};
\end{tikzpicture}
\end{document}
下一步:
- 添加好友生日。