Cómo excluir o eliminar los fines de semana del ganttchart

Cómo excluir o eliminar los fines de semana del ganttchart

Hola y perdón por la pregunta incompleta que sólo un psíquico podría responder :-)

Mi problema es que quiero tener mi bonito ganttchart o horario, pero sin incluir los fines de semana. Como mi problema es que si establezco las fechas para una parte del proyecto, por ejemplo. 3 días y el siguiente también, luego ocurre que el segundo es más largo al incluir el fin de semana. Es más fácil de ver en AP1100 y AP1200, que deberían tener la misma longitud. Realmente agradecería la ayuda, gracias.

\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}

Respuesta1

Actualizar:Marijn ha indicado cómo actualizar esto para que funcione con Gant 5.0 aquí.

El truco principal consiste en redefinir la forma en que pgfganttse indexa el gráfico. El paquete toma una fecha en un formato especificado diciendo time slot format = someformaty la convierte en un "número de día juliano", que es "el número (entero) de días que han transcurrido desde la época inicial al mediodía, hora universal (UT), del lunes 1 de enero. 4713 a. C. en el proléptico calendario juliano”.

Luego pgfgantttoma el número del día juliano de una fecha determinada y lo convierte en "intervalo de tiempo", que si la compress calendaropción no está presente, es simplemente (fecha - día de inicio + 1) donde el día de inicio es el primer día del calendario:

\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%
}

Por lo tanto, debemos cambiar este comando de indexación para convertir un número del calendario juliano en el número de días de la semana entre la fecha de inicio del gráfico y el día actual.

El otro cambio que debemos hacer es arreglar el \gantttitlecalendarcomando. Este comando recorre los días entre el día de inicio y el día de finalización y crea un encabezado de ancho (día de finalización) - (día de inicio) + 1. Necesitamos arreglar esto para que el encabezado solo cuente los días de la semana. El trabajo principal de este comando se realiza en el siguiente comando:

\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%
}

Los argumentos year, month, week, dayy weekdayto \ganttitlecalendarse definen como claves en /pgfgantt/calendar. Vamos a definir nuevas variantes de estos, en /pgfgantt/calendar week days onlylas que no cuentan los días laborables. Este es un cambio bastante menor; por ejemplo, el dayscódigo se ve así:

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%
}

y solo necesitamos dibujar el día si es un día laborable. Entonces agregamos el código.

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

Los cambios en las otras claves son bastante similares.

Una última pregunta es qué sucede cuando das el código de fechas que son el fin de semana. Lo configuré para que los días de inicio se redondeen al lunes y los días de finalización al viernes. Para hacer esto, tengo que crear dos variantes de \gtt@juliantotimeslot: \gtt@juliantotimeslot@roundupy \gtt@juliantotimeslot@rounddownparchearlas en el resto de los comandos del paquete donde \gtt@juliantotimeslotse usa.

Aquí está el código completo:

\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} 

Aquí está el resultado (la misma entrada, primero sin y luego con la weekdays onlyclave):

ingrese la descripción de la imagen aquí

información relacionada