6

I want nearly every Gantt-Chart to fit automatically to the textwidth of a page. The big word in that question is automatic. And that is what it differs from other questions like that.

The textwidth and the count of timeslots in the chart are not specified. The solution should be flexible enough to take care of it.

Maybe there is a solution to calculate x unit? The MWE below has 122 timeslots. So I would set x unit to \textwidth divided by 122. Is there a way to do that?

\documentclass{article}
\usepackage[showframe]{geometry} % show page borders
\usepackage{pgfgantt}

\begin{document}
\noindent
\begin{ganttchart}
    [
        x unit=1.23mm,              % timeslot width
        time slot format=isodate    % Datumsformat
    ]
    {2017-04-01}{2017-07-31}        % from-to (122 days)

    \gantttitle{Gantt-Chart with 122 timeslots}{122}\\
    \ganttbar{Short}{2017-05-01}{2017-06-01}\\
    \ganttbar{Long Long}{2017-05-25}{2017-06-04}\\
\end{ganttchart}
\end{document}
  • 1
    I've updated the answer with a cleaner syntax. – Alan Munn Apr 16 '17 at 19:43
3

Following discussion in chat, this is an adaption of Alan's answer which implements the syntax he was trying to realise.

% addaswyd o ateb Alan Munn: https://tex.stackexchange.com/questions/364944/expand-a-gantt-chart-automatically-to-textwidth-of-a-page/364969#364969 a chwestiwn buhtz: https://tex.stackexchange.com/questions/364944/expand-a-gantt-chart-automatically-to-textwidth-of-a-page
\documentclass[a4paper]{article}
\usepackage[showframe]{geometry} % show page borders
\parindent=0pt
\usepackage{pgfgantt}
\makeatletter
\tikzset{%
  /pgfgantt/time slots/.code={%
    \tikzset{%
      /pgfgantt/time slots/.cd,
      #1,
      /pgfgantt/.cd,
    }%
  },
  /pgfgantt/time slots/.search also={/pgfgantt},
  /pgfgantt/time slots/.cd,
  width/.store in=\ts@width,
  width=\textwidth,
  slots/.store in=\totaltimeslots,
  slots=20,
  label width/.store in=\ts@labelwidth,
  label width=25mm,
  calc x unit/.code n args=3{%
    \pgfmathsetmacro\ts@xunit{(#1-#2-0.6667em-2*\pgflinewidth)/#3}%
    \tikzset{%
      /pgfgantt/x unit=\ts@xunit pt,
    }%
  },
  widest/.code={%
    \pgfmathsetmacro\ts@wdlabel{width("#1")}%
    \tikzset{/pgfgantt/time slots/label width=\ts@wdlabel pt}%
  },
  calc x unit aux width/.style={/pgfgantt/time slots/calc x unit={#1}{\ts@labelwidth}{\totaltimeslots}},
  calc x unit aux label width/.style={/pgfgantt/time slots/calc x unit={\ts@width}{#1}{\totaltimeslots}},
  calc x unit aux slots/.style={/pgfgantt/time slots/calc x unit={\ts@width}{\ts@labelwidth}{#1}},
  width/.forward to=/pgfgantt/time slots/calc x unit aux width,
  slots/.forward to=/pgfgantt/time slots/calc x unit aux slots,
  label width/.forward to=/pgfgantt/time slots/calc x unit aux label width,
}
\makeatother
\begin{document}
\begin{ganttchart}
    [
        time slots={slots=122, widest=Long Long},
        time slot format=isodate,
    ]
    {2017-04-01}{2017-07-31}        % from-to (122 days)

    \gantttitle{Gantt-Chart with 122 timeslots}{\totaltimeslots}\\
    \ganttbar{Short}{2017-05-01}{2017-06-01}\\
    \ganttbar{Long Long}{2017-05-25}{2017-06-04}\\
\end{ganttchart}

\begin{ganttchart}
    [
        time slots/slots=15,
        time slots/widest=Foo,
        time slots/width=.9\linewidth,
        time slot format=isodate,
    ]
    {2017-04-01}{2017-04-15}        % from-to (122 days)
    \gantttitle{Gantt-Chart with 15 timeslots}{15}\\
    \ganttbar{Foo}{2017-05-25}{2017-06-04}
\end{ganttchart}
\end{document}
  • Wow. Impressiv! What does time slots/width=.9\linewidth, do? – buhtz Apr 18 '17 at 21:31
  • 1
    @buhtz Alan thought I should post it after I answered his query in chat. time slots/width=.9\linewidth sets the total width (label on the left + chart on the right) to 90% of the current width of a line. (Here, that is \textwidth, but \linewidth does not always equal \textwidth e.g. in a 2-column document or a special environment.) – cfr Apr 19 '17 at 0:36
  • @buhtz Note that time slots={width=<dim>} is equivalent to time slots/width=<dim>. The use of time slots/means I'm not overwriting any use pgfgantt or TikZ makes of a key called width. (Otherwise, I'd need a different name for the key.) – cfr Apr 19 '17 at 1:02
3

Use the calc package to set the length as you need. Since the number of timeslots needs to be set manually in the \ganttitle command, I've created a ganttchart style timeslots which takes as its arguments the number of slots for the chart, and the text of the longest \gantttitle label (comma separated) and then uses that to calculate the width. It also sets the value of a macro \timeslots which can then be used in the \gantttitle command.

I've added the code as a ganttchart style, so that it can be specified without its own macro as in the previous version (see edit history for details). I've also added a length for the width that you want the autosizing to be relative to. For your specific example, it's set to \textwidth, but this allows you to set it to any width you like.

Usage: [ ..., timeslots={<number>,<text of longest label>}, ... ]

\usepackage[]{geometry} % show page borders
\parindent=0pt
\usepackage{pgfgantt}
\usepackage{calc}
\newlength{\myunitx}
\newlength{\autosizewidth}
\setlength{\autosizewidth}{\textwidth} % this allows you to change the value for autosizing
\newcommand*{\timeslots}{}
\ganttset{
timeslots/.code args={#1,#2}{\setlength{\myunitx}{(\autosizewidth-\widthof{#2}-1em)/#1}
                 \renewcommand{\timeslots}{#1}\pgfkeys{pgfgantt/x unit=\myunitx}}
}
\begin{document}

\begin{ganttchart}
    [
        timeslots={122,Long Long},  % timeslots
        time slot format=isodate    % Datumsformat
    ]
    {2017-04-01}{2017-07-31}        % from-to (122 days)

    \gantttitle{Gantt-Chart with 122 timeslots}{\timeslots}\\
    \ganttbar{Short}{2017-05-01}{2017-06-01}\\
    \ganttbar{Long Long}{2017-05-25}{2017-06-04}\\
    \end{ganttchart}

\begin{ganttchart}
    [
        timeslots={15,Foo},         % timeslots
        time slot format=isodate    % Datumsformat
    ]
    {2017-04-01}{2017-04-15}        % from-to (122 days)
    \gantttitle{Gantt-Chart with 15 timeslots}{15}\\
    \ganttbar{Foo}{2017-05-25}{2017-06-04}
\end{ganttchart}
\end{document}

output of code

  • This is great. Thx. But while minimizing my example I forgot the width of the text when using ganttbar{}. Couldn't get widthof{My Bar} working here. – buhtz Apr 16 '17 at 19:54
  • 1
    @buhtz Can you update your example and I'll try to fix. – Alan Munn Apr 16 '17 at 20:03
  • 1
    @buhtz Ok, I see the problem. – Alan Munn Apr 16 '17 at 20:30
  • 1
    @buhtz I've fixed the problem. I'm not totally happy with the syntax, but it works as you need. – Alan Munn Apr 17 '17 at 2:21
  • Thank you very much. This works fine! You are right, the code is impressionistic. I contacted the pgfgantt maintainer and pointed him to your solution. Hope he will integrate it into his package or minimaly into its documentation. – buhtz Apr 17 '17 at 6:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.