如何从甘特图中排除或删除周末

如何从甘特图中排除或删除周末

你好,很抱歉这个问题不完整,只有通灵者才能回答:-)

我的问题是,我想要一个漂亮的甘特图或时间表,但不包括周末。我的问题是,如果我将项目部分的日期设置为例如 3 天,并将下一个部分也设置为 3 天,那么第二个部分会更长,因为它包括周末。最容易看到的是 AP1100 和 AP1200,它们的长度应该相等。我真的很感激帮助,谢谢。

\documentclass[a4paper]{article}
\usepackage{fullpage}
\usepackage{lscape}
\usepackage{pgfgantt}

\begin{document}

\begin{landscape}
\noindent\resizebox*{\linewidth}{!}{ % Rescale the chart to linewidth
\begin{ganttchart}[hgrid,time slot format = isodate]{2014-05-12}{2014-09-14}

  \gantttitlecalendar{year, month=shortname, week}\\
  \ganttgroup[progress=00]     {AP 1000: test eee}{2014-05-12}{2014-05-23}\\    %
  \ganttbar[progress=00]       {AP 1100: test eee}{2014-05-12}{2014-05-14}\\
  \ganttlinkedbar[progress=00] {AP 1200: test eee}{2014-05-15}{2014-05-19}\\
    \ganttlinkedbar[progress=00] {AP 1300: test eee}{2014-05-20}{2014-05-23}\\

  \ganttgroup{AP 2000: test eee}{2014-05-26}{2014-06-11}\\
  \ganttbar  {AP 2100: test eee}{2014-05-26}{2014-05-28}\\
  \ganttbar  {AP 2200: test eee}{2014-05-29}{2014-05-30}\\
  \ganttbar  {AP 2300: test eee}{2014-06-02}{2014-06-06}\\
    \ganttbar  {AP 2400: test eee}{2014-06-09}{2014-06-11}\\

    \ganttgroup{AP 3000: test eee}{2014-06-12}{2014-08-13}\\
  \ganttbar  {AP 3100: test eee}{2014-06-12}{2014-07-17}\\
  \ganttbar  {AP 3200: test eee}{2014-07-18}{2014-07-21}\\
    \ganttbar  {AP 3300: test eee}{2014-07-22}{2014-08-05}\\
    \ganttbar  {AP 3300: test eee}{2014-08-06}{2014-08-13}\\

    \ganttgroup{AP 4000: test eee}{2014-08-14}{2014-08-29}\\
  \ganttbar  {AP 4100: test eee}{2014-08-14}{2014-08-20}\\
  \ganttbar  {AP 4200: test eee}{2014-08-21}{2014-08-27}\\
    \ganttbar  {AP 4300: test eee}{2014-08-28}{2014-08-29}\\

  \ganttgroup{AP 5000: test eee}{2014-09-01}{2014-09-12}\\
  \ganttbar  {AP 5100: test eee}{2014-09-01}{2014-09-05}\\
  \ganttbar  {AP 5200: test eee}{2014-09-08}{2014-09-10}\\
  \ganttbar  {AP 5300: test eee}{2014-09-11}{2014-09-12}\\

  \ganttmilestone{Status}{2014-05-12}\\

 \end{ganttchart}
}
\end{landscape}
\end{document}

答案1

更新:Marijn 在这里指出了如何更新它以与 gant 5.0 兼容。

pgfgantt主要技巧是重新定义索引到图表中的方式。该包采用通过以下方式指定的格式获取日期time slot format = someformat,并将其转换为“儒略日数”,即“自公元前 4713 年 1 月 1 日星期一中午世界标准时间 (UT) 的初始纪元以来,在预测儒略历中经过的 (整数) 天数。”

然后pgfgantt取给定日期的儒略日数并将其转换为“时间段”,如果compress calendar没有该选项,则仅为(日期 - 开始日期 + 1),其中开始日期是日历的第一天:

\newcommand\gtt@juliantotimeslot[2]{%
  \begingroup%
  \@tempcnta=#1\relax%
  \ifgtt@compresscalendar % test for `compress calendar` option
     % do something here we don't care about
  \else % set \@tempcnta = current date - start date + 1 
    \advance\@tempcnta by-\gtt@startjulian\relax% 
    \advance\@tempcnta by1\relax%
  \fi%
  #2=\@tempcnta\relax % output the result into #2
  \gtt@smugglecount#2%
  \endgroup%
}

因此,我们需要更改此索引命令,将儒略历数字转换为图表开始日期和当前日期之间的工作日数。

我们需要做的另一个更改是修复\gantttitlecalendar命令。此命令遍历开始日期和结束日期之间的日期,并创建一个宽度为 (结束日期) - (开始日期) + 1 的标题。我们需要修复此问题,以便标题仅计算工作日。此命令的主要工作在以下命令中完成:

\newcommand\@@@gantttitlecalendar[3]{%
  \pgfcalendarjuliantodate{#1}{\@tempa}{\@tempb}{\@tempc}%
  \edef\gtt@calendar@startdate{\@tempa-\@tempb-\@tempc}%
  \pgfcalendarjuliantodate{#2}{\@tempa}{\@tempb}{\@tempc}%
  \edef\gtt@calendar@enddate{\@tempa-\@tempb-\@tempc}%
  \gtt@calendar@eolfalse%
  \pgfqkeys{/pgfgantt/calendar}{#3}%
  \endgroup%
}

参数yearmonthweekdayweekdayto\ganttitlecalendar被定义为 中的键/pgfgantt/calendar。我们将定义这些参数的新变体,其中/pgfgantt/calendar week days only不计算工作日。这是一个很小的变化,例如days代码如下所示:

day/.code={%
    \ifgtt@calendar@eol\ganttnewline\fi%
    \begingroup%
    \pgfcalendar{}{\gtt@calendar@startdate}{\gtt@calendar@enddate}{%
        %%% This is the command that draws the day:
        \gantttitle{\pgfcalendarcurrentday}{1}
    }%
    \endgroup%
    \gtt@calendar@eoltrue%
}

并且我们只需要在星期几为工作日时绘制日期。因此我们添加代码

\ifnum\pgfcalendarcurrentweekday<5\relax % 0 -- 4 are Monday -- Friday
   \gantttitle{\pgfcalendarcurrentday}{1}
\fi

其它键的改变也十分类似。

最后一个问题是,当您给出周末的代码日期时会发生什么。我将其设置为将开始日期四舍五入为星期一,将结束日期四舍五入为星期五。为了做到这一点,我必须制作 : 和 的两个变体,\gtt@juliantotimeslot并将\gtt@juliantotimeslot@roundup它们修补到使用 的\gtt@juliantotimeslot@rounddown包中的其余命令中。\gtt@juliantotimeslot

完整代码如下:

\documentclass[a4paper]{article}
\usepackage{fullpage}
\usepackage{lscape}
\usepackage{etoolbox}
\usepackage{pgfgantt}
\parindent=0pt
\parskip=60pt

\makeatletter
% some extra count registers
\newcount\gtt@tempweekdaya
\newcount\gtt@tempweekdayb
\newcount\gtt@tempcounta
\newcount\gtt@tempcountb

% Define the "weekdays only" key
\ganttset{weekdays only/.code={% install the modified commands
    \let\gtt@juliantotimeslot@roundup\gtt@juliantotimeslot@roundup@weekdaysonly
    \let\gtt@juliantotimeslot@rounddown\gtt@juliantotimeslot@rounddown@weekdaysonly
    \let\@@@gantttitlecalendar\@@@gantttitlecalendar@weekdaysonly
}}

\def\gtt@patchcmd#1{\expandafter\patchcmd\csname\string#1\endcsname}

% Add check whether start date is on the weekend, if so round it up to Monday:
\gtt@patchcmd\ganttchart{\gtt@tsstojulian{#2}{\gtt@startjulian}}{%
    \gtt@tsstojulian{#2}{\gtt@startjulian}%
    \ifx\@@@gantttitlecalendar\@@@gantttitlecalendar@weekdaysonly % If weekdays only key is present
        \pgfcalendarjuliantoweekday{\gtt@startjulian}{\gtt@tempweekdaya}
        \ifnum\gtt@tempweekdaya>4\relax % and start date is a weekend
            \advance\gtt@startjulian7\relax
            \advance\gtt@startjulian-\gtt@tempweekdaya\relax % round to the nearest Monday
            \@gtt@PackageWarning{Given start date was on the weekend, rounding to the next Monday}
        \fi
    \fi
}{}{\error}

% Fix \gtt@juliantotimeslot calls to either refer to \gtt@juliantotimeslot@rounddown or \gtt@juliantotimeslot@roundup
\gtt@patchcmd\ganttchart{\gtt@juliantotimeslot{\gtt@endjulian}}{\gtt@juliantotimeslot@rounddown{\gtt@endjulian}}{}{\error}
\gtt@patchcmd\ganttchart{\gtt@juliantotimeslot{\gtt@today@slot}}{\gtt@juliantotimeslot@rounddown{\gtt@today@slot}}{}{\error}
\gtt@patchcmd\gtt@chartelement{\gtt@juliantotimeslot{\gtt@left@slot}}{\gtt@juliantotimeslot@roundup{\gtt@left@slot}}{}{\error}
\gtt@patchcmd\gtt@chartelement{\gtt@juliantotimeslot{\gtt@right@slot}}{\gtt@juliantotimeslot@rounddown{\gtt@right@slot}}{}{\error}

% Both rounddown and roundup by default are just synonyms for \gtt@juliantotimeslot
\let\gtt@juliantotimeslot@rounddown\gtt@juliantotimeslot
\let\gtt@juliantotimeslot@roundup\gtt@juliantotimeslot

% \gtt@juliantotimeslot computes the number of days between the start date and the Julian day #1 and stores the result in #2.
% Our modified versions compute the number of weekdays between the start date and the Julian day #1 and stores the result in #2.
% \gtt@juliantotimeslot@roundup rounds weekend days to the next Monday
% \gtt@juliantotimeslot@rounddown rounds weekend days to the previous Monday
\newcommand\gtt@juliantotimeslot@roundup@weekdaysonly[2]{
    \begingroup
    \@tempcnta=#1\relax%
    \pgfcalendarjuliantoweekday{\@tempcnta}{\gtt@tempweekdaya}
    \ifnum\gtt@tempweekdaya>4\relax % if start date is a weekend
        \advance\@tempcnta7\relax
        \advance\@tempcnta-\gtt@tempweekdaya\relax % round to the nearest Monday
        \@gtt@PackageWarning{Given start date was on the weekend, rounding to the next Monday}
    \fi
    \gtt@tempcounta=\@tempcnta\relax
    \gtt@juliantotimeslot@rounddown@weekdaysonly{\gtt@tempcounta}{\gtt@tempcountb}
    #2=\gtt@tempcountb\relax
    \gtt@smugglecount#2%
    \endgroup%
}    

\newcommand\gtt@juliantotimeslot@rounddown@weekdaysonly[2]{%
  \begingroup%
  \@tempcnta=#1\relax%
  \ifgtt@compresscalendar%
    \pgfcalendarjuliantodate{\@tempcnta}{\@tempa}{\@tempb}{\@tempc}%
    \@tempcnta=\@tempa\relax%
    \advance\@tempcnta by-\gtt@startyear\relax%
    \multiply\@tempcnta by12\relax%
    \advance\@tempcnta by\@tempb\relax%
    \advance\@tempcnta by-\gtt@startmonth\relax%
    \advance\@tempcnta by1\relax%
  \else%
    \pgfcalendarjuliantoweekday{\gtt@startjulian}{\gtt@tempweekdaya} % Put the day of the week of the start and end days into counters
    \pgfcalendarjuliantoweekday{\@tempcnta}{\gtt@tempweekdayb}
    \ifnum\gtt@tempweekdayb>4\relax
        \@gtt@PackageWarning{Weekend date rounded down to the preceding Friday}
    \fi
    
    \advance\@tempcnta by-\gtt@startjulian\relax % Now \@tempcnta has the number of days in the period minus one
    \divide\@tempcnta7\relax % Now it has how many whole weeks occur
    \multiply\@tempcnta5\relax % Now it has the number of weekdays that occur in whole weeks minus one
    \advance\@tempcnta1\relax % Now the number of weekdays that occur in whole weeks
    %
    % Okay now let's correct for the last partial week. First we need to calculate how many days we have left over.
    \@tempcntb=#1\relax% 
    \advance\@tempcntb by-\gtt@startjulian\relax% Number of days
    \divide\@tempcntb7\relax
    \multiply\@tempcntb-7\relax % negative number of days that occur in whole weaks
    \advance\@tempcntb#1\relax
    \advance\@tempcntb by-\gtt@startjulian\relax% Number of left over days
    \advance\@tempcnta\@tempcntb % \@tempcnta has (weekdays occurring in whole weeks) + (all left over days). 
    %
    % We still need to subtract off the left over days that land on weekends.
    \ifnum\gtt@tempweekdayb<\gtt@tempweekdaya\relax
        \advance\gtt@tempweekdayb7\relax % make sure the end day is greater than or equal to start day
    \fi
    %
    % Is Saturday in left over days?
    \@tempcntb=5\relax % Saturday is day 5
    \ifnum\@tempcntb<\gtt@tempweekdaya\relax
        \advance\@tempcntb7\relax % make sure Saturday is greater than or equal to start day
    \fi
    \ifnum\@tempcntb>\gtt@tempweekdayb\relax\else % If Saturday is one of left over days
        \advance\@tempcnta-1\relax % subtract it
    \fi
    % Is Sunday in left over days?
    \@tempcntb=6 % Sunday is day 6
    \ifnum\@tempcntb<\gtt@tempweekdaya\relax
        \advance\@tempcntb7\relax
    \fi
    \ifnum\@tempcntb>\gtt@tempweekdayb\relax\else
        \advance\@tempcnta-1\relax 
    \fi
  \fi%
  #2=\@tempcnta\relax%

  \gtt@smugglecount#2%
  \endgroup%
}

% Now it's time to fix \ganttitlecalendar
% Our modified version of \ganttitlecalendar passes control to "/pgfgantt/calendar weekdays only" instead of "/pgfgantt/calendar"
\newcommand\@@@gantttitlecalendar@weekdaysonly[3]{%
  \pgfcalendarjuliantodate{#1}{\@tempa}{\@tempb}{\@tempc}%
  \edef\gtt@calendar@startdate{\@tempa-\@tempb-\@tempc}%
  \pgfcalendarjuliantodate{#2}{\@tempa}{\@tempb}{\@tempc}%
  \edef\gtt@calendar@enddate{\@tempa-\@tempb-\@tempc}%
  \gtt@calendar@eolfalse%
  \pgfqkeys{/pgfgantt/calendar weekdays only}{#3}% Only difference is here 
  \endgroup%
}

% Here is the modified calendar printing code. It's mostly the same as the original code, with a bunch of extra tests for weekdays and 
% some minor differences in the edge cases
\pgfqkeys{/pgfgantt/calendar weekdays only}{
  year/.code={%
    \ifgtt@calendar@eol\ganttnewline\fi%
    \begingroup%
    \gtt@calendar@slots=0\relax%
    \ifgtt@compresscalendar%
      \pgfcalendar{}{\gtt@calendar@startdate}{\gtt@calendar@enddate}{%
        \ifdate{equals=12-31}{%
          \advance\gtt@calendar@slots by1\relax %added this line 
          \gantttitle{\pgfcalendarcurrentyear}{\the\gtt@calendar@slots}%
          \gtt@calendar@slots=1\relax%
        }{%
          \ifdate{end of month=1}{%
            \advance\gtt@calendar@slots by1\relax%
          }{}%
        }%
        \ifdate{equals=\pgfcalendarendiso}{%
          \ifdate{end of month=1}{%
            % Used to be a decrement here
          }{}%
          \ifdate{equals=12-31}{}{%
            \gantttitle{\pgfcalendarcurrentyear}{\the\gtt@calendar@slots}%
          }%
        }{}%
      }%
    \else%
      \pgfcalendar{}{\gtt@calendar@startdate}{\gtt@calendar@enddate}{%
        \ifdate{equals=12-31}{%
          \ifnum\pgfcalendarcurrentweekday<5\relax % Only increment if it's a weekday
            \advance\gtt@calendar@slots by1\relax%
          \fi
          \gantttitle{\pgfcalendarcurrentyear}{\the\gtt@calendar@slots}%
          \gtt@calendar@slots=0\relax% used to be 1
        }{%
          \ifnum\pgfcalendarcurrentweekday<5\relax % Only increment if it's a weekday
            \advance\gtt@calendar@slots by1\relax%
          \fi
        }%
        \ifdate{equals=\pgfcalendarendiso}{%
          \ifnum\gtt@calendar@slots=1\relax\else%
            % Used to be a decrement here
            \gantttitle{\pgfcalendarcurrentyear}{\the\gtt@calendar@slots}%
          \fi%
        }{}%
      }%
    \fi%
    \endgroup%
    \gtt@calendar@eoltrue%
  },%
  month/.code={%
    \ifgtt@calendar@eol\ganttnewline\fi%
    \begingroup%
    \gtt@calendar@slots=0\relax
    \pgfcalendar{}{\gtt@calendar@startdate}{\gtt@calendar@enddate}{%
      \ifdate{end of month=1}{%
        \ifnum\pgfcalendarcurrentweekday<5\relax % Only increment if it's a weekday
            \advance\gtt@calendar@slots by1\relax%
        \fi
        \gantttitle{%
          \csname pgfcalendarmonth#1\endcsname{\pgfcalendarcurrentmonth}%
        }{%
          \ifgtt@compresscalendar1\else\the\gtt@calendar@slots\fi%
        }%
        \gtt@calendar@slots=0\relax% used to be 1
      }{%
        \ifnum\pgfcalendarcurrentweekday<5\relax % Only increment if it's a weekday
            \advance\gtt@calendar@slots by1\relax%
        \fi
      }%
      \ifdate{equals=\pgfcalendarendiso}{%
        \ifnum\gtt@calendar@slots=0\relax\else % used to test for 1
          % Used to be a decrement here
          \gantttitle{%
            \csname pgfcalendarmonth#1\endcsname{\pgfcalendarcurrentmonth}%
          }{%
            \ifgtt@compresscalendar1\else\the\gtt@calendar@slots\fi%
          }%
        \fi%
      }{}%
    }%
    \endgroup%
    \gtt@calendar@eoltrue%
  },%
  week/.code={%
    \ifgtt@calendar@eol\ganttnewline\fi%
    \begingroup%
    \gtt@calendar@slots=0\relax%
    \gtt@calendar@weeknumber=#1\relax%
    \pgfcalendar{}{\gtt@calendar@startdate}{\gtt@calendar@enddate}{%
      \ifdate{Sunday}{%
        \gtt@calendar@startofweek=\pgfcalendarcurrentjulian\relax%
        \advance\gtt@calendar@startofweek by1\relax%
        \advance\gtt@calendar@startofweek by-\gtt@calendar@slots\relax%
        \pgfcalendarjuliantodate{\gtt@calendar@startofweek}%
          {\startyear}{\startmonth}{\startday}%
        \def\currentweek{\the\gtt@calendar@weeknumber}%
        \gantttitle{%
          \ganttvalueof{calendar week text}%
        }{%
          \the\gtt@calendar@slots%
        }%
        \gtt@calendar@slots=0\relax% Used to be 1
        \advance\gtt@calendar@weeknumber by1\relax%
      }{%
        \ifnum\pgfcalendarcurrentweekday<5\relax % Only increment if it's a weekday
            \advance\gtt@calendar@slots by1
        \fi
      }%
      \ifdate{equals=\pgfcalendarendiso}{%
        \ifnum\gtt@calendar@slots=0\relax\else% used to test for 1
          % Deleted decrement line used to be here
          \gtt@calendar@startofweek=\pgfcalendarcurrentjulian\relax%
          \advance\gtt@calendar@startofweek by1\relax%
          \advance\gtt@calendar@startofweek by-\gtt@calendar@slots\relax%
          \pgfcalendarjuliantodate{\gtt@calendar@startofweek}%
            {\startyear}{\startmonth}{\startday}%
          \def\currentweek{\the\gtt@calendar@weeknumber}%
          \gantttitle{%
            \ganttvalueof{calendar week text}%
          }{%
            \the\gtt@calendar@slots%
          }%
        \fi%
      }{}%
    }%
    \endgroup%
    \gtt@calendar@eoltrue%
  },%
  week/.default=1,
  weekday/.code={%
    \ifgtt@calendar@eol\ganttnewline\fi%
    \begingroup%
    \pgfcalendar{}{\gtt@calendar@startdate}{\gtt@calendar@enddate}{%
        \ifnum\pgfcalendarcurrentweekday<5\relax % only increment if it's a weekday
          \gantttitle{%
            \csname pgfcalendarweekday#1\endcsname{\pgfcalendarcurrentweekday}%
          }{1}%
        \fi
    }%
    \endgroup%
    \gtt@calendar@eoltrue%
  },
  day/.code={%
    \ifgtt@calendar@eol\ganttnewline\fi%
    \begingroup%
    \pgfcalendar{}{\gtt@calendar@startdate}{\gtt@calendar@enddate}{%
        \ifnum\pgfcalendarcurrentweekday<5\relax % only increment if it's a weekday
            \gantttitle{\pgfcalendarcurrentday}{1}
        \fi
    }%
    \endgroup%
    \gtt@calendar@eoltrue%
  }%
}
\makeatother


\begin{document}
\def\pgfcalendarweekdayletter#1{\ifcase#1M\or Tu\or W\or Th\or F\or Sa\or Su\fi}


\begin{ganttchart}[
    time slot format=little-endian,
    progress=today,
    today=4.5.13,
    calendar week text = {W~\currentweek},
]{1.5.13}{14.5.13}
      \gantttitlecalendar{week,day,weekday=letter}\\
\ganttgroup{Group 1}{1.5.13}{14.5.13} \\
\ganttbar{Subtask 1}{1.5.13}{3.5.13} \\
\ganttbar{Subtask 2}{3.5.13}{8.5.13} \\
\ganttbar{Subtask 3}{9.5.13}{14.5.13}
\end{ganttchart}


\begin{ganttchart}[
    time slot format=little-endian,
    progress=today,
    today=4.5.13,
    calendar week text = {W~\currentweek},
    weekdays only
]{1.5.13}{14.5.13}
      \gantttitlecalendar{week,day,weekday=letter}\\
\ganttgroup{Group 1}{1.5.13}{14.5.13} \\
\ganttbar{Subtask 1}{1.5.13}{3.5.13} \\
\ganttbar{Subtask 2}{3.5.13}{8.5.13} \\
\ganttbar{Subtask 3}{9.5.13}{14.5.13}
\end{ganttchart}

\newpage

\begin{ganttchart}[
    time slot format=little-endian,
    progress=today,
    today=3.12.16,
    calendar week text = {W~\currentweek},
]{26.11.16}{11.12.16}
      \gantttitlecalendar{week,day,weekday=letter}\\
\ganttgroup{Group 1}{26.11.16}{11.12.16} \\
\ganttbar{Subtask 1}{26.11.16}{3.12.16} \\
\ganttbar{Subtask 2}{3.12.16}{11.12.16} \\
\end{ganttchart}

\begin{ganttchart}[
    time slot format=little-endian,
    progress=today,
    today=3.12.16,
    calendar week text = {W~\currentweek},
    weekdays only
]{26.11.16}{11.12.16}
      \gantttitlecalendar{week,day,weekday=letter}\\
\ganttgroup{Group 1}{26.11.16}{11.12.16} \\
\ganttbar{Subtask 1}{26.11.16}{3.12.16} \\
\ganttbar{Subtask 2}{3.12.16}{11.12.16} \\
\end{ganttchart}

\end{document} 

这是输出(相同的输入,首先没有密钥,然后有密钥weekdays only):

在此处输入图片描述

相关内容