간트차트에서 주말을 제외하거나 제거하는 방법

간트차트에서 주말을 제외하거나 제거하는 방법

안녕하세요. 심령술사만이 답변할 수 있는 불완전한 질문에 대해 죄송합니다 :-)

내 문제는 주말을 포함하지 않고 멋진 간트차트나 시간 일정을 갖고 싶다는 것입니다. 내 문제는 예를 들어 프로젝트 부분의 날짜를 설정하면 다음과 같습니다. 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"율리우스력 일수"로 변환합니다. 이는 "세계시(UT) 1월 1일 월요일 정오에 최초 에포크 이후 경과한 일수"입니다. 역산율 율리우스력으로는 기원전 4713년이다.”

그런 다음 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%
}

인수 year, month, week, dayweekdayto 는 \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키가 있음).

여기에 이미지 설명을 입력하세요

관련 정보