TikZ 日历,从 .csv 加载数据

TikZ 日历,从 .csv 加载数据

我的目标是制作一个年历,日历上用方框代替日期,并根据我当天所做的锻炼类型进行填写。这些锻炼将从 .csv 文件中加载,格式如下:

2020-01-01;2020-01-01;2020-01-03

2020-01-02; ...

其中每一列都代表一种特定类型的活动,我只需要添加日期,代码就会完成剩下的工作。

这是我迄今为止的工作:

\documentclass{article}
\usepackage[a4paper, total={8.5in, 11in}]{geometry}
\usepackage{csvsimple}
\usepackage{tikz}
\usetikzlibrary{calendar}
\usepackage{pgfcalendar}

\begin{document}
\def\s{0.85} %size of box around day
\def\ss{6.3ex} %space between days
\def\ds{0.02}

\def\nexer{0.75} %1-1/number of exercise to be put into calendar

\def\cardio{red}
\def\str{blue}
\def\spo{green}
\def\oth{orange}
\begin{tikzpicture}[every calendar/.style={
                    week list, month label above centered, day xshift=\ss, day yshift=\ss,
                    day code = { 
                        \draw (-0.5*\s,0.5*\s) -- (0.5*\s,0.5*\s) -- (0.5*\s,-0.5*\s) -- (-0.5*\s,-0.5*\s) -- cycle;
                    }
                    }]
    \csvreader[no head, separator=semicolon]{cal.csv}{1=\dcar,2=\dstr,3=\dspo,4=\doth}{
    \calendar
        [dates=2020-01-01 to 2020-01-last]
        if (equals=\dcar) {\filldraw[\cardio] (-0.5*\s+\ds,0.5*\s-\ds) --  
            (0.5*\s-\ds,0.5*\s-\ds) --  
            (0.5*\s-\ds,-0.5*\s+\s*\nexer+\ds) --  
            (-0.5*\s+\ds,-0.5*\s+\s*\nexer+\ds) -- cycle;}
        if (equals=\dstr) {\filldraw[\str,yshift=-5] (-0.5*\s+\ds,0.5*\s-\ds) --  
            (0.5*\s-\ds,0.5*\s-\ds) --  
            (0.5*\s-\ds,-0.5*\s+\s*\nexer+\ds) --  
            (-0.5*\s+\ds,-0.5*\s+\s*\nexer+\ds) -- cycle;}
        if (equals=\dspo) {\filldraw[\spo,yshift=-10] (-0.5*\s+\ds,0.5*\s-\ds) --  
            (0.5*\s-\ds,0.5*\s-\ds) --  
            (0.5*\s-\ds,-0.5*\s+\s*\nexer+\ds) --  
            (-0.5*\s+\ds,-0.5*\s+\s*\nexer+\ds) -- cycle;}
        if (equals=\doth) {\filldraw[\oth,yshift=-15] (-0.5*\s+\ds,0.5*\s-\ds) --  
            (0.5*\s-\ds,0.5*\s-\ds) --  
            (0.5*\s-\ds,-0.5*\s+\s*\nexer+\ds) --  
            (-0.5*\s+\ds,-0.5*\s+\s*\nexer+\ds) -- cycle;};}


\end{tikzpicture}
\end{document}

我遇到了几个问题,首先,如果每个活动的天数不同,即 .csv 列的长度不同,则此代码将无法运行。此外,csvreader 会产生这种奇怪的效果,即日历“翻倍”,因为它会覆盖自身,我不知道如何消除它。

任何帮助均感激不尽。

EDIT1:现在看起来怎么样日历的当前状态

答案1

我认为您想要的与 csv 标准不同。因此,您需要一些自定义实现来满足您的目的。

在此处输入图片描述

\documentclass{article}
\usepackage[a4paper, total={8.5in, 11in}]{geometry}
\usepackage{csvsimple}
\usepackage{tikz}
\usetikzlibrary{calendar}
\usepackage{pgfcalendar}
\usepackage{expl3}

% sample csv file
\begin{filecontents*}{cal.csv}
2020-01-01;2020-01-10;2020-01-03
2020-01-02;2020-01-10;2020-01-05;2020-01-25
2020-01-06;2020-01-16;2020-01-03
2020-01-08;2020-01-09;2020-01-23
\end{filecontents*}

\newlength{\daywidth}
\setlength{\daywidth}{5.0ex} %size of box around day
\newlength{\dayinterval}
\setlength{\dayinterval}{6.3ex} %space between days
\newlength{\dayitemheight}
\setlength{\dayitemheight}{0.8ex}
\newlength{\dayiteminterval}
\setlength{\dayiteminterval}{0.2ex}

\ExplSyntaxOn

\seq_new:N \g_doc_dates_seq

\cs_set:Npn \doc_read_file:n #1 {
  \ior_open:Nn \g_tmpa_ior {#1}
  \seq_gclear:N \g_doc_dates_seq
  \ior_str_map_inline:Nn \g_tmpa_ior {
    \str_set:Nx \l_tmpa_str {\tl_trim_spaces:n {##1}}
    \str_if_empty:NF \l_tmpa_str {
      \seq_gput_right:NV \g_doc_dates_seq \l_tmpa_str
    }
  }
  \ior_close:N \g_tmpa_ior
}


\cs_set:Npn \doc_draw_command:nnn #1#2#3 {
  \node[#1,#2] at (#3.north) {};
}

\cs_generate_variant:Nn \regex_split:nnN {nVN}
\cs_generate_variant:Nn \doc_draw_command:nnn {xnx}

\newcommand{\drawfilerow}[3]{
  \iow_term:x {show: \fp_eval:n {-(#2 + 0.5) * (1.0ex)}pt}
  \int_compare:nT {1 <= #2 <= \seq_count:N \g_doc_dates_seq} {
    \tl_set:Nx \l_tmpa_tl {\seq_item:Nn \g_doc_dates_seq {#2}}
    \regex_split:nVN {;} \l_tmpa_tl \l_tmpa_seq
    \seq_map_inline:Nn \l_tmpa_seq {
      \str_set:Nx \l_tmpa_str {\tl_trim_spaces:n {##1}}
      \str_if_empty:NF \l_tmpa_str {
        \doc_draw_command:xnx {
          minimum~width=0.98\daywidth,
          minimum~height=\dayitemheight,
          yshift=\fp_eval:n {-(#2 - 1) * (\dayitemheight + \dayiteminterval) -0.2pt}pt,
          anchor=north,
          inner~sep=0pt,
          outer~sep=0pt
        } {fill=#3} {#1-\str_use:N \l_tmpa_str};
      }
    }
  }
}

\newcommand{\readcalendarfile}[1]{
  \doc_read_file:n {#1}
}

\ExplSyntaxOff

\begin{document}

% read "csv" file
\readcalendarfile{cal.csv}

\begin{tikzpicture}[every calendar/.style={
                    week list, 
                    month label above centered, 
                    day xshift=\dayinterval, 
                    day yshift=\dayinterval,
                    day code = { 
                        \node[minimum width=\daywidth, 
                        minimum height=\daywidth,
                        name=\pgfcalendarsuggestedname,
                        draw=black] {};
                    }
                    }]
    \calendar (mycal) [dates=2020-01-01 to 2020-01-last];
    % use contents from "csv" file
    \drawfilerow{mycal}{1}{red};
    \drawfilerow{mycal}{2}{blue};
    \drawfilerow{mycal}{3}{green};
    \drawfilerow{mycal}{4}{orange};
\end{tikzpicture}


\end{document}

相关内容