Класс PdfGantt для вывода диаграмм Ганта в PDF документе

Класс PdfGantt является "оберткой" (wrapper) над классом TCPDF и предназначен для печати графиков (диаграмм) Ганта в PDF-документах.

Класс имеет следующие возможности.

Установка

Скопируйте файл pdf_gantt.php в одну из папок, перечисленных в include_path (либо в своих кодах всегда указывайте полный путь к нему в операторах include/require). Так как данный модуль для работы требует наличия классов TCPDF, также необходимо их наличие. Ссылка: tcpdf.org

Использование класса

Класс может использоваться как самостоятельный для вывода диаграмм непосредственно в объект класса TCPDF, так и в качестве плагина к модулю генерации PDF-документов с данными пользователя - CPrintFormPdf.
Использование как самостоятельного класса (PdfGantt)
Для самостоятельных вызовов применяется основной класс PdfGantt.

Пример.
require_once('tcpdf/tcpdf.php');
require_once('pdf_gantt.php');

$pdf = new TCPDF('P','mm','A4');
$pdf->SetFont('', '', 8); # Your default font name,style,size here !
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);

$pdf->AddPage();

$gantt_cfg = array(
    ,'dateformat'=>'j Y'
    ,'descr_width'=>0.30
    ,'bgcolor'=>'#eee'
    ,'arrow_color'=>'#25e'
    ,'grid_color'=>'#cce'
    ,'shade_color'=>'#bbb'
);

$gantt = new PdfGantt($pdf, $gantt_cfg,10,10,190,80);

$ganttdata = array(
   'title' => 'Project Dream Application'
  ,'daterange'=>array('2013-01-01')
  ,'items' => array(
        array('id'=>'task00', 'description'=>'Publish on KickStarter', 'datestart'=>'2013-01-01', 'workdays'=>14
          ,'members'=>'Andriano,Mickele','progress'=>0.30)
       ,array('id'=>'task01', 'description'=>'Planning Development process', 'datestart'=>'2013-01-15'
           , 'workdays'=>28,'members'=>'Steve,Paul,Hanna')
       ,array('id'=>'task03', 'description'=>'Developing Application Core', 'datestart'=>'2013-01-01', 'workdays'=>59
           ,'progress'=>0.20, 'members'=>'Antonio,Paul,Barbara')
       ,array('id'=>'task02', 'description'=>'Developing Main UI', 'datestart'=>'2013-01-01', 'workdays'=>59
           , 'progress'=>0.25, 'members'=>array('John','Paul'))
       ,array('id'=>'task04', 'description'=>'Programming Plugins', 'datestart'=>'2013-01-01'
         , 'workdays'=>30, 'dependencies'=>'task02,task03', 'members'=>'Antonio,Paul,John', 'milestone'=>'Stage 1')
       ,array('id'=>'task05', 'description'=>'Alpha Testing', 'workdays'=>30, 'dependencies'=>'task01,task02,task03,task04'
         , 'members'=>'All team members','color'=>'#aa0', 'mcolor'=>'#e22')
       ,array('id'=>'task06', 'description'=>'Beta (open) Testing', 'workdays'=>30, 'dependencies'=>'task05')
       ,array('id'=>'task07', 'description'=>'Making Release Package', 'workdays'=>14, 'datestart'=>'2013-01-01'
         ,'dependencies'=>'task06', 'members'=>'Paul,Andriano',     'milestone'=>'Releasing')
       ,array('id'=>'task08', 'description'=>'Publishing on Steam', 'workdays'=>10, 'datestart'=>'2013-01-01'
         ,'dependencies'=>'task07', 'members'=>'John,Mickele')
  )
);

$gantt->Render($ganttdata);

$pdf->Output('Gantt_standalone.pdf', 'I');
Обратите внимание, всю подготовительную работу над объектом TCPDF надо выполнять самостоятельно (SetFont(), AddPage() перед вызовом Render(), и Output() для финальной выдачи содержимого PDF документа.
Использование как плагина, подключаемого к модулю printform-pdf.php (PfPdf_Gantt)
Класс генерации PDF-форм PrintFormPdf начиная с версии 1.1 позволяет подключать плагины, выводящие специфический контент в указанной прямоугольной области. Для этого должен быть реализован класс, наследующий от PfPdfPlugin (абстрактный класс, объявленный в printform-pdf.php).
В файле pdf_gantt.php это класс PfPdf_Gantt. Таким образом, если вы подключили в своем коде файл pdf_gantt.php после модуля printform-pdf.php, то полдела уже сделано.
Остается добавить описание вывода графика в ваш XML файл настроек печати для CPrintFormPdf.

// Образец заполнения XML файла настроек с плагином для вывода графика Ганта
<?xml version="1.0" encoding="UTF-8"?>
<printdef>
  <version modified="2012-04-28">1.0</version>

  <baseparameters>
    <margins left="0" top="0" right="0" bottom="0" />
    <font name="arial" size="10" />
    <page orientation="L" size="A4" units="mm" />

  </baseparameters>
  <pages>
   <page>
    <field name="policy_serno" posx="165" posy="17.0" />
    <field name="policydate" posx="210" posy="17.0" />
    <field name="insurance_period" posx="184" posy="21.0" />

    <field name="drv_no" posx="15" />
    <field name="drv_name" posx="23" width="85" size="9"/>
    <field name="drv_birth" posx="120" />
    <field name="drv_sex" posx="145" />
    <field name="drv_license" posx="160" />
    <field name="drv_exp" posx="194" />
    <field name="drv_scases" posx="228" width="10" align="C" />
    <field name="drv_bmc" posx="268" width="10" align="C"/>
    <datagrid name="drv_list" fields="drv_no,drv_name,drv_birth,drv_sex,drv_license,drv_exp,drv_scases,drv_bmc" posx="0" posy="50" step_y="4.6" rows="26" />

    <field name="ispolnitel" posx="135.0" posy="200" />
    <field name="b2bmark" posx="109" posy="189.5" size="8" />
    <field name="barcode1" type="barcode:C128B" options="text,fontsize=7" posx="110" posy="193" align='c' height="7" width="80" />

    <plugin type="pfpdf_gantt" name="my_gantt1" posy="70" posx="10" height="70" width="0" bgcolor="#e8e8e8"
      options="dateformat=d.m,title_width=0.25,arrow_color=#F22,shade_color=#BBB" />

    <field name="draft_mark" posx="70" posy="45" size="40" rotate="20" color="gray"/>
   </page>
  </pages>
</printdef>
Обратите внимание на тег plugin, находящийся среди описаний "полей" вывода. С точки зрения печати через CPrintFormPdf это очередное поле, имеющее особый тип "plugin", "контент" в котором будет сформирован при помощи соответствующего подключенного плагина, имя его класса плагина должно указывается в атрибуте type. В нашем случае type="pfpdf_gantt" - имя плагин-класса, объявленного в файле pdf_gantt.php

Как и к прочим выводимым полям, к выводу, выполняемому плагином, применимы атрибуты цвета фона и поворота, т.е. вы можете подложить под график свой фон и/или повернуть его на нужный угол.

Передача данных о задачах, выводимых в график, производится при помощи метода setPluginData($name, $data). Вызывать метод необходимо ДО вызова финального метода CPrintformPdf::Render().

Ниже пример кода из тестового файла gantt_sample1.php, выполняющего печать графика Ганта в составе модуля PrintformPdf:
$pdf = new CPrintFormPdf( $options );
$pdf->LoadConfig('gantt-sample1.xml');
// ...
$pdf->AddData($data); // передаем "обычные" данные для вывода при помощи CPrintformPdf

$plgdata = array(
   'title' => 'Project <<Dream Application>>'
  ,'daterange'=>array('2013-01-01','2013-12-31') # Общий выводимый диапазон дат на графике
  ,'items' => array(
        array('id'=>'task00', 'description'=>'Publish on KickStarter', 'datestart'=>'2013-01-01', 'workdays'=>14
          ,'members'=>'Andriano,Mickele','progress'=>0.30)
       ,array('id'=>'task01', 'description'=>'Planning Development process', 'datestart'=>'2013-01-15', 'workdays'=>28,'members'=>'Steve,Paul,Hanna')
       ,array('id'=>'task03', 'description'=>'Developing Application Core', 'datestart'=>'2013-01-01', 'workdays'=>59,'progress'=>0.20, 'members'=>'Antonio,Paul,Barbara')
       ,array('id'=>'task02', 'description'=>'Developing Main UI', 'datestart'=>'2013-01-01', 'workdays'=>59, 'progress'=>0.25, 'members'=>array('John','Paul'))
       ,array('id'=>'task04', 'description'=>'Programming Plugins', 'datestart'=>'2013-01-01', 'workdays'=>30, 'dependencies'=>'task02,task03')
// ...
);

$pdf->setPluginData('my_gantt1', $plgdata); // передаем данные о задачах/сотрудниках/вехах, для формирования гр.Ганта
$pdf->Render();
Обратите внимание на значение первого параметра у метода setPluginData(), my_gantt1, это имя нашего "Plugin-поля" (значение атрибута name в теге plugin).
Т.к. на форме допустим вывод нескольких графов Ганта (или других областей, рисуемых подключенными плагинами), очевидно, у каждого из них должно быть уникальное символьно-числовое имя, чтобы однозначно ассигновать массив данных.

Описание методов класса PdfGantt

__construct($tcpdfobj, $cfg = null, $x=0,$y=0,$w=0,$h=0) - конструктор класса. Параметры:

$tcpdfobj - ранее созданный экземпляр класса TCPDF, через который будут выполняться все функции вывода в PDF документ.


$cfg - предполагается ассоциативный массив 'ключ' => значение, список поддерживаемых ключей (параметров настройки для вывода графика Ганта) описан ниже). Если переданное значение не является массивом, оно игнорируется.

$x, $y - координаты левого верхнего угла области вывода графика, $w и $h - соответственно, ее ширина и высота.
При нулевой ширине под график отводится вся доступная область страницы от указанной x-координаты, за вычетом небольшого 5-мм поля. Аналогично рассчитывается высота области графика при переданном нулевом значении высоты $h.

Список поддерживаемых параметров настройки для вывода графика Ганта :

Имя параметраОписаниеПо умолчанию
stringcharset Кодировка, в которой будут названия (описания) задач, участвующих в них сотрудниках, вех (milestone) и т.д. Необходимо указывать для корректной конвертации строк в UTF-8 перед непосредственным выводом. В случае работы как плагин к CprintformPdf здесь передается аналогичный параметр, заданный для головного модуля (CprintformPdf), таким образом указание кодировки вдостаточно выполнить один раз (например, через настроечный XML файл к CprintformPdf) UTF-8
dateformat Формат даты для вывода первых чисел (названий) месяцев над графиком Ганта (узлы сетки). Формат - строка в стандарте PHP функции date() 'M Y', т.е. выводятся строки типа "Jan 2013", "Feb 2013" и т.д.
dateformat2 Формат для вывода даты начала задач (над столбиком самой задачи на графике), также строка в стандарте PHP функции date() 'm/j' ("01/1", "01/24" и т.д.)
descr_width Ширина левой колонки, для вывода названий(описаний) задач и списков работающих над ними людей. Может быть указана в долях единицы , тогда от общей ширины области под график берется соответствующая доля. Если же указано число больше 1, оно интерпретируется как точная длина в миллиметрах. Чтобы вообще не выводить колонку с названиями задач, укажите нулевое значение (например, это может быть логично при выводе второй и далее частей графика - "панорамы", где названия нужны только у первой части) 0.2 (20 процентов от общей ширины области вывода графика)
bgcolor задает цвет фона под графиком. Для этого и всех последующих цветовых значений допустимы любые строки, поддерживаемые классом TCPDF ('blue','#F0F0EE','#DDD'). '' (пустая строка, фон не выводится)
grid_color задает цвет линий сетки (вертикальные линии для первых дней месяца, горизонтальные - между задачами). Этим же цветом рисуются вертикали от задач к значкам "вех" (milestone) '#888'
box_bgcolor задает основной цвет заливки "отрезков", показывающих задачу на временной линии. '#88e'
box_bgcolor2 задает дополнительный цвет, применяемый для заливки "неисполненной" части задачи. Используется, если в описании задачи есть параметр 'progress' (значение от 0 до 1) '#ccf'
ms_color задает цвет заливки значков "вех" '#4ff'
box_border задает цвет окантовки вокруг значков задач и вех. '#111'
text_color задает общий цвет для всех текстов на графике. '#000'
arrow_color задает цвет стрелок-указателей, показывающих зависимости между задачами (ведет от "родительских" задач к зависящим от них). '#777'
dates_fontsize задает размер шрифта для вывода дат 6
taskdescr_fontsize задает размер шрифта в наименованиях задач (левая колонка графика) 7
members_fontsize задает размер шрифта для вывода списка людей, работающих над задачей. Рекомендуется маленький размер, иначе при большом количестве людей или недостаточной заданной высоте графика список членов команды может стать частично или полностью невидимым ( во избежание наползания на следующую строку делается авто-скрытие неумещающихся строк). TCPDF может автоматически изменить размер этого шрифта, чтобы текст уместился в отведенной области. 5.5
ms_fontsize задает размер шрифта для вывода наименований вех. 6
shade_color непустое значение включает вывод "тени" под прямоугольниками задач, и задает ее цвет. '' (пустая строка - тени не формируются)
shade_offsetx горизонтальное смещение тени от ее "источника" 1 (мм)
shade_offsety вертикальное смещение тени от ее "источника" 0.7 (мм)
show_taskdays параметр, указывающий, выводить ли над задачей количество дней, отведенных на ее выполнение. Чтобы отключить вывод, укажите ноль. 1 (выводить)
ms_height "Milestone height", высота области, выделяемой на графике для вывода "вех". Эта область автоматически создается, уменьшая полезную высоту собственно графика, только в случае, если хотя бы у одной задачи есть непустой атрибут 'milestone'. Высота задается либо в долях единицы (и тогда рассчитывается от общей высоты области графика), либо в абсолютных величинах - текущих юнитах (mm) (если указать значение больше 1). 0.08


Render($data) - осуществляет печать графика Ганта на основании переданных данных о задачах и границах выводимого диапазона времени.

$data - ассоциативный массив, включающий следующие элементы:

daterange массив (один или два элемента) либо строка с разделенными запятой значениями: дата_начала и дата_конца выводимого диапазона (начало и конец таймлайна). Даты должны передаваться в строке в формате 'YYYY-MM-DD'. Если даты не заданы вообще или не задана дата конца диапазона, они определяются автоматически из списка задач и их дат начала-конца, так чтобы все задачи целиком попали на таймлайн. Если при этом вычисленная дата начала диапазона - не первое число месяца, график все равно будет построен от начала месяца.
Пример: $data['daterange'] = array('2013-01-01','2013-12-31')
items Массив со списком задач,их сроков, исполнителей. Каждый элемент массива должен быть ассоциативным массивом со следующими элементами:
  • 'id' - (обязательное) уникальное имя (идентификатор) задачи. Отношения между "главными" и зависящими от них задачами задаются ссылками на эти имена.
    Отсутствие элемента id или его пустое значение не допускается (такая "задача" будет игнорирована)
  • 'description' - (необязательное) описание задачи. Выводится в левую колонку графика. При пустом значении используется имя (id) задачи
  • 'color' - (необязательное) цвет шрифта, которым выводить название данной задачи. Цвет используется вместо "стандартного", указанного в параметре конфигурации 'text_color'
  • 'members' - (необязательное) список имен людей, участвующих в задаче. Может быть одной строкой(имена разделенные запятой) или простым массивом строк-имен
  • 'mcolor' - (необязательное) цвет шрифта, которым выводить список работающих над задачей
  • 'datestart' - (необязательное) дата начала работы над задачей, строка в формате 'YYYY-DD-MM'
  • 'dateend' - (необязательное) дата окончания (последнего дня) работы над задачей, 'YYYY-DD-MM'
  • 'workdays' - (необязательное) количество дней, отводимых на задачу (целое число)
  • 'progress' - (необязательное) степень текущего исполнения задачи, задается в долях от единицы (т.е. 0.1 означает "выполнена на 10 %)
    Если элемента нет или он равен единице, задача на таймлайне полностью закрашивается "базовым" цветом (box_bgcolor), при значении ниже 1.0 на задаче рисуется столбик "прогресса"
  • 'dependencies' - (необязательное) список имен (id) задач, от которых зависит данная задача (не может стартовать, пока хоть одна из них не выполнена)
    Допустимо пепедавать массив или строку (список имен, разделенных запятыми)
  • 'milestone' - (необязательное) название вехи, которая стартует вместе с данной задачей
В каждой задаче, для возможности определения дат ее начала и окончания должны быть либо явно указаны собственно обе даты, либо дата начала и количество дней (workdays), либо только количество дней, но при этом задача должна быть зависимой от других задач (у которых даты действия также заданы или могут однозначно вычислены по родительским задачам).

Зависимость можно указывать только от задач, уже присутствующих в списке, иначе печать графика будет неверной. В процессе генерации графика даты начала (и соответственно окончания) зависящих задач при необходимости автоматически перерасчитываются и сдвигаются вправо: даже если для такой задачи явно указана конкретная дата старта, но одна или более "родительских" задач заканчивается позже, то дата сдвигается за самую позднюю из них.

При наличии хотя бы у одной из задач элемента 'milestone', на графике вверху выводится дополнительная линейка, для отображения вех и их названий.

localize($param) - вызывается для локализации, заменяет "стандартные" строки заголовков на пользовательские.
$param должен быть ассоциативным массивом пользовательских строк, со следующими ключами:
days Строка для блока "число дней", выводимого в каждой задаче. "%s" в ней будет заменено на текущее кол-во дней у задачи.
milestones Строка заголовка "Milestones"


setAreaPosition($x, $y, $w=0, $h=0) задает координаты и размер области под график. Можно использовать, например, если эти параметры не были переданы в конструкторе класса PdfGantt.

setConfig($cfg) явно передает новые (дополнительные) значения параметров конфигурации. Можно использовать, например, если параметры не были переданы в конструкторе класса PdfGantt.

Вывод части графика

Возможны ситуации, когда при большом количестве задач в проекте, их большой общей протяженности по времени, невозможно будет вместить их все в один единственный график. В этом случае можно воспользоваться выводом "по частям", с тем чтобы потом соединить части в единый график (как делают в панорамной фото-съемке).

Для этого достаточно многократно вывести один и тот же набор данных, каждый раз явно задавая в элементе 'daterange' нужные интервалы времени. Логичным шагом будет на всех страницах кроме первой отключить вывод столбца с названиями задач, для чего указать нулевой размер параметра 'descr_width'.
// пример вывода графика по частям на две страницы

$pdf = new TCPDF('P','mm','A4');
$pdf->SetFont('', '', 8);
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);

$pdf->AddPage();

$gantt_cfg = array(
    'descr_width'=>0.30
    // ...
);

$gantt = new PdfGantt($pdf, $gantt_cfg,10,10,190,80);

$ganttdata = array(
   'title' => 'Project Dream Application'
  ,'daterange'=>array('2013-01-01','2013-05-31')
  ,'items' => array(
  // ...
  )
);

$gantt->Render($ganttdata); // вывели первую часть

$gantt_cfg['descr_width'] = 0; // отключить вывод колонки с названиями задач
$ganttdata['daterange'] = array('2013-06-01','2013-12-31'); // вторая часть даипазона

$pdf->AddPage(); // новая страница
$gantt->setConfig($gantt_cfg);
$gantt->Render($ganttdata); // вывели первую часть
$pdf->Output('Gantt_standalone.pdf', 'I');


Данный класс можно использовать как образец или стартовую точку для создания собственных плагинов к printform-pdf.php. Правила их написания есть в в соответствующей документации к классу CPrintFormPdf.
Распространяется по лицензии: BSD License

История версий (Change log)

0.90.0018 (26.04.2013)


Copyright © Alexander Selifonov, www.selifan.ru