Как скрыть нерабочие часы на временной шкале диаграммы Ганта в 1С?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При построении отчетов и мониторов загрузки оборудования или персонала с помощью объекта ДиаграммаГанта разработчики часто сталкиваются с задачей отображения только рабочих часов (например, с 09:00 до 18:00) за несколько дней подряд. По умолчанию шкала времени строится непрерывно, включая все 24 часа каждых суток, из-за чего полезное пространство диаграммы заполняется пустыми ночными интервалами и нерабочими днями.

В платформе 1С:Предприятие объект ДиаграммаГанта использует линейную и непрерывную ось времени, в которой нет штатного переключателя для исключения разрывов или привязки шкалы к графикам работы. Однако эту задачу можно решить несколькими практическими способами: от программного масштабирования координат до визуального зонирования и использования альтернативных элементов интерфейса.

Способ 1. Программная трансформация интервалов и ручное формирование шкалы

Разберем наиболее эффективный способ сжатия шкалы времени, позволяющий исключить ночные часы. Идея метода заключается в том, чтобы математически растянуть реальный рабочий диапазон времени (например, с ВремяНачала до ВремяОкончания) на полные 24-часовые сутки для каждого дня, а затем вручную расставить нужные подписи меток времени на шкале.

Рассмотрим реализацию пересчета координат времени. Для этого создадим функцию преобразования даты и времени интервала задачи:


Функция ДиаграммаМонитораЗагрузкиОпределитьПериодИнтервала(Период, ВремяНачала, ВремяОкончания)
	
	Если (ВремяНачала > 0) Или (ВремяОкончания < 24) Тогда
		ПериодНачала = НачалоДня(Период) + ВремяНачала * 3600;
		ПериодОкончания = НачалоДня(Период) + ВремяОкончания * 3600;
		
		Если Период < ПериодНачала Тогда
			Период = ПериодНачала;
		ИначеЕсли Период > ПериодОкончания Тогда
			Период = ПериодОкончания;
		КонецЕсли;
		
		// Растягиваем рабочий отрезок на 24 часа
		Период = НачалоДня(Период) + (Период - НачалоДня(Период) - ВремяНачала * 3600) * 24 / (ВремяОкончания - ВремяНачала);
	КонецЕсли;
	
	Возврат Период;
	
КонецФункции

Теперь проанализируем, как сформировать пользовательскую шкалу меток на диаграмме Ганта. Отключаем автоматические периодические метки и вручную заполняем коллекцию меток для суток, часов и минут:


Процедура НастроитьШкалуВремениДиаграммы(ДиаграммаГанта, ПериодНачало, ПериодОкончание, ВремяНачала, ВремяОкончания, ШкалаМинутКратность)
	
	ШкалаСутки = ДиаграммаГанта.ОбластьПостроения.ШкалаВремени.Элементы[0];
	ШкалаЧасы = ДиаграммаГанта.ОбластьПостроения.ШкалаВремени.Элементы[1];
	ШкалаМинуты = ДиаграммаГанта.ОбластьПостроения.ШкалаВремени.Элементы[2];
	
	Если (ВремяНачала > 0) Или (ВремяОкончания < 24) Тогда
		ШкалаСутки.Видимость = Истина;
		ШкалаСутки.ЛинииДелений = Новый Линия(ТипЛинииДиаграммы.Пунктир);
		
		ШкалаЧасы.Видимость = Истина;
		ШкалаЧасы.ОтображатьПериодическиеМетки = Ложь;
		ШкалаЧасы.ЛинииДелений = Новый Линия(ТипЛинииДиаграммы.Пунктир);
		
		ШкалаМинуты.Видимость = Истина;
		ШкалаМинуты.ОтображатьПериодическиеМетки = Ложь;
		ШкалаМинуты.ЛинииДелений = Новый Линия(ТипЛинииДиаграммы.Пунктир);
		
		// Отметка текущего времени
		МеткаТекущая = ШкалаСутки.Метки.Добавить(ДиаграммаМонитораЗагрузкиОпределитьПериодИнтервала(ТекущаяДата(), ВремяНачала, ВремяОкончания));
		МеткаТекущая.ЦветЛинии = WebЦвета.Красный;
		
		Сутки = НачалоДня(ПериодНачало);
		Пока Сутки <= ПериодОкончание Цикл
			// Метка дня
			МеткаДня = ШкалаСутки.Метки.Добавить(ДиаграммаМонитораЗагрузкиОпределитьПериодИнтервала(Сутки, ВремяНачала, ВремяОкончания));
			МеткаДня.Текст = Формат(Сутки, "ДЛФ=DD") + ", " + Формат(Сутки, "ДФ=дддд");
			
			// Метки рабочих часов
			Для Час = ВремяНачала По (ВремяОкончания - 1) Цикл
				ДатаЧаса = Сутки + Час * 3600;
				МеткаЧаса = ШкалаЧасы.Метки.Добавить(ДиаграммаМонитораЗагрузкиОпределитьПериодИнтервала(ДатаЧаса, ВремяНачала, ВремяОкончания));
				МеткаЧаса.Текст = Формат(Час, "ЧЦ=2; ЧН=; ЧВН=") + ":00";
				
				// Метки минут внутри часа
				Минуты = 0;
				Пока Минуты < 60 Цикл
					ДатаМинуты = ДатаЧаса + Минуты * 60;
					МеткаМинуты = ШкалаМинуты.Метки.Добавить(ДиаграммаМонитораЗагрузкиОпределитьПериодИнтервала(ДатаМинуты, ВремяНачала, ВремяОкончания));
					МеткаМинуты.Текст = Формат(Минуты, "ЧЦ=2; ЧН=; ЧВН=");
					Минуты = Минуты + ШкалаМинутКратность;
				КонецЦикла;
			КонецЦикла;
			
			Сутки = НачалоДня(Сутки + 86400);
		КонецЦикла;
	Иначе
		// Стандартное отображение при круглосуточном режиме
		ШкалаСутки.ОтображатьПериодическиеМетки = Истина;
		ШкалаСутки.Единица = ТипЕдиницыШкалыВремени.День;
		ШкалаЧасы.ОтображатьПериодическиеМетки = Истина;
		ШкалаЧасы.Единица = ТипЕдиницыШкалыВремени.Час;
		ШкалаМинуты.ОтображатьПериодическиеМетки = Истина;
		ШкалаМинуты.Единица = ТипЕдиницыШкалыВремени.Минута;
	КонецЕсли;
	
КонецПроцедуры

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

Способ 2. Штатное визуальное выделение нерабочего времени (Интервалы фона)

Если математическая модификация временных интервалов не подходит из-за сложности интерактивного редактирования, стандартным подходом в типовых конфигурациях 1С является сохранение реальной шкалы с затемнением нерабочих интервалов.

Для этого используется коллекция ИнтервалыФона объекта диаграммы:

  1. Обходим календарные дни выбранного периода отчета.
  2. Для каждого дня вычисляем нерабочие отрезки времени: от 00:00 до начала рабочего дня (например, 09:00) и от окончания рабочего дня (18:00) до 23:59:59.
  3. Для каждого такого отрезка добавляем элемент в коллекцию ИнтервалыФона диаграммы, задавая начальную и конечную дату, а также свойство ЦветФона (например, серый цвет или штриховку).

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

Способ 3. Постраничное отображение одного рабочего дня

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

Посмотрим на алгоритм реализации:

  1. Свойствам диаграммы НачалоПолногоИнтервала и КонецПолногоИнтервала присваиваются значения времени начала и окончания рабочего дня выбранной даты (например, 01.09.2024 08:00:00 и 01.09.2024 17:00:00).
  2. На форму отчета выносятся кнопки навигации «Предыдущий день» и «Следующий день», а также поле выбора даты.
  3. При смене даты диаграмма мгновенно перерисовывается в рамках только рабочего диапазона часов, полностью исключая ночные промежутки.

Способ 4. Альтернативные способы отрисовки графика

Если встроенных возможностей ДиаграммаГанта недостаточно для комплексного планирования с разрывами времени, рассмотрим альтернативные варианты:

  1. Использование элемента ТабличныйДокумент: создается сетка, где колонками выступают только рабочие часы нужных дней. Интервалы задач формируются объединением ячеек и фоновой заливкой. Это позволяет полностью убрать любые нерабочие часы и выходные дни.
  2. Использование ПолеHTMLДокумента и JavaScript-библиотек: график строится в веб-компоненте на базе специализированных библиотек (например, Vis.js Timeline, FullCalendar или DHTMLX Gantt), которые нативно поддерживают скрытие нерабочих часов (work time ranges) и гибкое масштабирование.
← На главную