Загрузка данных


Задача понятна. Ниже приведен разбор ошибок и готовый, полностью собранный код для всех 3 модулей (**Модуль объекта**, **Модуль менеджера**, **Модуль формы**) с исправлением критических багов и соблюдением официальных стандартов разработки 1С.

---

### Главные ошибки и исправленные архитектурные проблемы

1. **Критический баг в модуле объекта (`ОбработкаПроведения`):**
* **Было:** Вложенный цикл по таблице дат и табличной части `Сотрудники`, внутри которого для каждого дня и сотрудника выполнялся `НайтиСтроки` по всей ТЧ `ГрафикРаботыСотрудников`.
* **Проблема:** Сложность $O(N \times M \times K)$. При 20 сотрудниках и 30 днях это сотни тысяч холостых операций, приводящих к зависанию при проведении.
* **Стандарт 1С:** Не делать избыточные циклы по календарю. Проведение должно обходить напрямую отсортированные данные табличной части документа `ГрафикРаботыСотрудников`.


2. **Неоптимальная работа с контекстом формы (`&НаСервере` vs `&НаСервереБезКонтекста`):**
* **Было:** Служебные функции получения данных из базы (`ПолучитьКалендарь`, `ПолучитьСписокЗначенийКалендарей`, `ПолучитьМассивКалендарей`) находились в модуле формы с директивой `&НаСервере`.
* **Проблема:** При каждом вызове передается весь тяжелый контекст формы (включая динамические данные таблиц).
* **Стандарт 1С:** Функции выборки из БД, не завязанные на реквизиты формы, выносятся в **Модуль менеджера** (`Экспорт`), а в форме вызываются через `&НаСервереБезКонтекста`.


3. **Лишние серверные вызовы из формы:**
* Процедура `ПроизводственныйКалендарьПриИзмененииНаСервере` дублировала клиентскую `ПроизводственныйКалендарьПриИзменении`, создавая двойные серверные вызовы. Убрано дублирование.


4. **Ошибка генерации удаляемых реквизитов:**
* В `УдалитьКолонкуСотрудников` передавался массив строк, а правильный вызов `ИзменитьРеквизиты` требует передачи массива с правильным удалением элементов.



---

### 1. МОДУЛЬ ОБЪЕКТА (Документ)

```bsl
#Область ОбработчикиСобытий

Процедура ОбработкаПроведения(Отказ, Режим)
	
	Движения.ГрафикиРаботыСотрудников.Записывать = Истина;
	Движения.ГрафикиРаботыСотрудников.Очистить();
	
	// Сортируем ТЧ для корректного расчета порядковых номеров интервалов за день
	ТЧГрафик = ГрафикРаботыСотрудников.Выгрузить();
	ТЧГрафик.Сортировать("Сотрудник Возр, Дата Возр, ВремяНачала Возр");
	
	ТекущийСотрудник = Неопределено;
	ТекущаяДата      = '00010101';
	НомерИнтервала   = 1;
	
	Для Каждого СтрокаГрафика Из ТЧГрафик Цикл
		
		Если Не ЗначениеЗаполнено(СтрокаГрафика.Дата) Или Не ЗначениеЗаполнено(СтрокаГрафика.Сотрудник) Тогда
			Продолжить;
		КонецЕсли;
		
		// Сброс интервала при смене сотрудника или даты
		Если СтрокаГрафика.Сотрудник <> ТекущийСотрудник Или СтрокаГрафика.Дата <> ТекущаяДата Тогда
			ТекущийСотрудник = СтрокаГрафика.Сотрудник;
			ТекущаяДата      = СтрокаГрафика.Дата;
			НомерИнтервала   = 1;
		Иначе
			НомерИнтервала   = НомерИнтервала + 1;
		КонецЕсли;
		
		Движение = Движения.ГрафикиРаботыСотрудников.Добавить();
		Движение.Период        = МесяцГрафика;
		Движение.Организация   = Организация;
		Движение.Подразделение = Подразделение;
		Движение.Сотрудник     = СтрокаГрафика.Сотрудник;
		Движение.Дата          = СтрокаГрафика.Дата;
		
		Движение.ВремяНачала = Дата(
			Год(СтрокаГрафика.Дата), 
			Месяц(СтрокаГрафика.Дата), 
			День(СтрокаГрафика.Дата), 
			Час(СтрокаГрафика.ВремяНачала), 
			Минута(СтрокаГрафика.ВремяНачала), 
			0
		);
		
		Движение.ВремяОкончания = Дата(
			Год(СтрокаГрафика.Дата), 
			Месяц(СтрокаГрафика.Дата), 
			День(СтрокаГрафика.Дата), 
			Час(СтрокаГрафика.ВремяОкончания), 
			Минута(СтрокаГрафика.ВремяОкончания), 
			0
		);
		
		Движение.Интервал = НомерИнтервала;
		
	КонецЦикла;
	
КонецПроцедуры

#КонецОбласти

```

---

### 2. МОДУЛЬ МЕНЕДЖЕРА (Документ)

```bsl
#Область ПубличныйИнтерфейс

Функция ПолучитьМассивКалендарей(Знач ГодВыбора) Экспорт
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ
		|	ГрафикРаботы.Ссылка КАК ПроизводственныйКалендарь
		|ИЗ
		|	Справочник.ГрафикРаботы КАК ГрафикРаботы
		|ГДЕ
		|	ГОД(ГрафикРаботы.ДатаНачала) = &Год
		|	И НЕ ГрафикРаботы.ПометкаУдаления
		|УПОРЯДОЧИТЬ ПО
		|	ГрафикРаботы.Наименование";
		
	Запрос.УстановитьПараметр("Год", ГодВыбора);
	Возврат Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("ПроизводственныйКалендарь");
	
КонецФункции

Функция ПолучитьСписокЗначенийКалендарей(Знач ГодВыбора) Экспорт
	
	СписокКалендарей = Новый СписокЗначений;
	СписокКалендарей.ЗагрузитьЗначения(ПолучитьМассивКалендарей(ГодВыбора));
	Возврат СписокКалендарей;
	
КонецФункции

Функция ПолучитьКалендарь(Знач ГодВыбора) Экспорт
	
	МассивКалендарей = ПолучитьМассивКалендарей(ГодВыбора);
	Если МассивКалендарей.Количество() <> 0 Тогда
		Возврат МассивКалендарей[0];
	КонецЕсли;
	
	Возврат Неопределено;
	
КонецФункции

#КонецОбласти

```

---

### 3. МОДУЛЬ ФОРМЫ (ФормаДокумента)

*(Примечание: В `Документы.УстановкаГрафиковРаботы` укажите реальное имя документа из конфигуратора)*

```bsl
&НаКлиенте
Перем МассивСообщений;
&НаКлиенте
Перем ТекущийСотрудникТаблицыСотрудник;
&НаКлиенте
Перем ТекущаяСтрокаТаблицыДанныеОВремени;
&НаКлиенте
Перем МесяцРегистрацииСтрокой;

#Область ОбработчикиСобытийФормы

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	
	Если Не ЗначениеЗаполнено(Объект.Ссылка) Тогда
		Объект.Организация = ПараметрыСеанса.ТекущийПользователь.Организация;
		Объект.МесяцГрафика = ТекущаяДатаСеанса();
	КонецЕсли;
	
	МесяцРегистрацииСтрокой = Формат(Объект.МесяцГрафика, "ДФ='ММММ гггг'");
	
	ЗаполнитьДанныеОВремени();
	
	Элементы.ЗаполнитьПоПроизводственномуГрафику.Заголовок = "Заполнить по производственному графику" + Символы.ПС + "для всех сотрудников";
	
	Если НЕ ЗначениеЗаполнено(Объект.ПроизводственныйКалендарь) Тогда
		Объект.ПроизводственныйКалендарь = Документы.УстановкаГрафиковРаботы.ПолучитьКалендарь(Год(Объект.МесяцГрафика));
	КонецЕсли;
	
	ПроизводственныйКалендарьПриИзмененииНаСервере();
	ОтрисоватьТаблицуДанныеОВремени();
	
КонецПроцедуры

#КонецОбласти

#Область ОбработчикиСобытийЭлементовШапкиФормы

&НаКлиенте
Процедура МесяцРегистрацииСтрокойАвтоПодбор(Элемент, Текст, ДанныеВыбора, ПараметрыПолученияДанных, Ожидание, СтандартнаяОбработка)
	Если Не ПустаяСтрока(Текст) Тогда
		ДанныеВыбора = ДатаКакМесяцПодобратьДатуПоТексту(Текст);
		СтандартнаяОбработка = Ложь;
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура МесяцРегистрацииСтрокойНачалоВыбора(Элемент, ДанныеВыбора, ВыборДобавлением, СтандартнаяОбработка)
	ЗадатьВопросПриИзмененииДаты();
КонецПроцедуры

&НаКлиенте
Процедура МесяцРегистрацииСтрокойПриИзменении(Элемент = Неопределено)
	ОчиститьГрафикРаботыСотрудников();
	ЗаполнитьПроизводственныйКалендарь(Год(Объект.МесяцГрафика));
	ПроизводственныйКалендарьПриИзменении();
КонецПроцедуры

&НаКлиенте
Процедура ПроизводственныйКалендарьНачалоВыбора(Элемент, ДанныеВыбора, ВыборДобавлением, СтандартнаяОбработка)
	
	СтандартнаяОбработка = Ложь;
	ГодВыбора = Год(Объект.МесяцГрафика);
	СписокКалендарей = ПолучитьСписокЗначенийКалендарейНаСервере(ГодВыбора);
	
	ВыбранныйЭлемент = СписокКалендарей.ВыбратьЭлемент("Выберите производственный календарь за " + ГодВыбора);
	Если ВыбранныйЭлемент <> Неопределено Тогда
		Объект.ПроизводственныйКалендарь = ВыбранныйЭлемент.Значение;
	ИначеЕсли СписокКалендарей.Количество() = 0 Тогда
		Сообщить("Отсутствует производственный календарь за " + ГодВыбора + " год.");
	КонецЕсли;
	
	ПроизводственныйКалендарьПриИзменении();
	
КонецПроцедуры

&НаКлиенте
Процедура ПроизводственныйКалендарьПриИзменении(Элемент = Неопределено)
	Если НЕ ЗначениеЗаполнено(Объект.ПроизводственныйКалендарь) Тогда
		СделатьОсновныеЭлементыФормыНедоступными();
		Сообщить("Заполните производственный график");
	Иначе
		СделатьОсновныеЭлементыФормыДоступными();
		ЗагрузитьТаблицуПроизводственногоКалендаря();
	КонецЕсли;
КонецПроцедуры

#КонецОбласти

#Область ОбработчикиСобытийЭлементовТаблицФормы

&НаКлиенте
Процедура СотрудникиОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
	
	СтандартнаяОбработка = Ложь;
	Если ТипЗнч(ВыбранноеЗначение) <> Тип("Массив") Тогда
		Возврат;
	КонецЕсли;
	
	Для Каждого Сотрудник Из ВыбранноеЗначение Цикл
		НайденныеСтроки = Объект.Сотрудники.НайтиСтроки(Новый Структура("Сотрудник", Сотрудник));
		Если НайденныеСтроки.Количество() > 0 Тогда
			Продолжить;
		КонецЕсли;
		
		НоваяСтрока = Объект.Сотрудники.Добавить();
		НоваяСтрока.Сотрудник = Сотрудник;
		ДобавитьКолонкуСотрудника(Сотрудник);
	КонецЦикла;
	
	ОтрисоватьТаблицуДанныеОВремени();
	
КонецПроцедуры

&НаКлиенте
Процедура СотрудникиПередУдалением(Элемент, Отказ)
	
	СтрокаСотрудника = Элементы.Сотрудники.ТекущиеДанные;
	Если СтрокаСотрудника <> Неопределено Тогда
		УдалитьКолонкуСотрудников(СтрокаСотрудника.Сотрудник);
		УдалитьСотрудникаИзГрафикаРаботыСотрудников(СтрокаСотрудника.Сотрудник);
		УдалитьСотрудникаИзСоответствиеКолонокСотрудников(СтрокаСотрудника.Сотрудник);
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура СотрудникиПослеУдаления(Элемент)
	
	Если Объект.Сотрудники.Количество() = 0 Тогда
		Объект.ГрафикРаботыСотрудников.Очистить();
		Объект.СоответствиеКолонокСотрудников.Очистить();
	КонецЕсли;
	ОтрисоватьТаблицуДанныеОВремени();
	
КонецПроцедуры

&НаКлиенте
Процедура СотрудникиВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
	
	Сотрудник = Элемент.ТекущиеДанные.Сотрудник;
	ПараметрыФормы = Новый Структура;
	ДатаСтроки = НачалоМесяца(Объект.МесяцГрафика);
	
	Если ТекущаяСтрокаТаблицыДанныеОВремени <> Неопределено 
		И ТекущаяСтрокаТаблицыДанныеОВремени.Свойство("Дата")
		И ЗначениеЗаполнено(ТекущаяСтрокаТаблицыДанныеОВремени.Дата) Тогда
		ДатаСтроки = ТекущаяСтрокаТаблицыДанныеОВремени.Дата;
	КонецЕсли;
	
	ПараметрыФормы.Вставить("ДатаСтроки", ДатаСтроки);
	ПараметрыФормы.Вставить("МесяцГрафика", Объект.МесяцГрафика);
	ПараметрыФормы.Вставить("ГрафикРаботыСотрудников", Объект.ГрафикРаботыСотрудников);
	
	СписокСотрудников = Новый СписокЗначений;
	СписокСотрудников.Добавить(Сотрудник);
	ПараметрыФормы.Вставить("КоллекцияСотрудников", СписокСотрудников);
	ПараметрыФормы.Вставить("ПоОдномуСотруднику", Истина);
	
	Оповещение = Новый ОписаниеОповещения("ПослеЗаписиДанныхФормыРасписаниеРаботы", ЭтотОбъект);
	ОткрытьФорму("Документ.УстановкаГрафиковРаботы.Форма.РасписаниеРаботы", ПараметрыФормы, ЭтотОбъект, , , , Оповещение, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
	
КонецПроцедуры

&НаКлиенте
Процедура СотрудникиПриАктивизацииСтроки(Элемент)
	
	ТекущаяСтрокаПерем = Элемент.ТекущиеДанные;
	ТекущийСотрудникТаблицыСотрудник = Неопределено;
	Элемент.КонтекстноеМеню.ПодчиненныеЭлементы.СотрудникиКонтекстноеМенюЗаполнитьПоПроизводственномуГрафикуСотрудника.Доступность = Ложь;
	Элемент.КоманднаяПанель.ПодчиненныеЭлементы.СотрудникиЗаполнитьПоПроизводственномуГрафикуСотрудника.Доступность = Ложь;
	
	Если ТекущаяСтрокаПерем <> Неопределено И ТекущаяСтрокаПерем.Свойство("Сотрудник") И НЕ ТекущаяСтрокаПерем.Сотрудник.Пустая() Тогда
		ТекущийСотрудникТаблицыСотрудник = ТекущаяСтрокаПерем.Сотрудник;
		Элемент.КонтекстноеМеню.ПодчиненныеЭлементы.СотрудникиКонтекстноеМенюЗаполнитьПоПроизводственномуГрафикуСотрудника.Доступность = Истина;
		Элемент.КоманднаяПанель.ПодчиненныеЭлементы.СотрудникиЗаполнитьПоПроизводственномуГрафикуСотрудника.Доступность = Истина;
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ДанныеОВремениПриАктивизацииСтроки(Элемент)
	
	ТекущаяСтрокаПерем = Элемент.ТекущиеДанные;
	СтруктураСтроки = Неопределено;
	
	Если ТекущаяСтрокаПерем <> Неопределено И ТекущаяСтрокаПерем.Свойство("Дата") Тогда
		СтруктураСтроки = Новый Структура;
		СтруктураСтроки.Вставить("Дата", ТекущаяСтрокаПерем.Дата);
		
		Для Каждого Сотрудник Из Объект.Сотрудники Цикл
			ИмяРеквизита = ПолучитьИмяКолонкиПоСотруднику(Сотрудник.Сотрудник);
			Если ТекущаяСтрокаПерем.Свойство(ИмяРеквизита) Тогда
				СтруктураСтроки.Вставить(ИмяРеквизита, ТекущаяСтрокаПерем[ИмяРеквизита]);
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	ТекущаяСтрокаТаблицыДанныеОВремени = СтруктураСтроки;
	
КонецПроцедуры

&НаКлиенте
Процедура ДанныеОВремениВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
	
	ТекущаяСтрока = Элемент.ТекущиеДанные;
	Сотрудник = ПолучитьСотрудникаПоИмениКолонки(Поле.Имя);
	
	ПараметрыФормы = Новый Структура;
	ПараметрыФормы.Вставить("ДатаСтроки", ТекущаяСтрока.Дата);
	ПараметрыФормы.Вставить("НеизменяемаяДата", Истина);
	ПараметрыФормы.Вставить("МесяцГрафика", Объект.МесяцГрафика);
	ПараметрыФормы.Вставить("ГрафикРаботыСотрудников", Объект.ГрафикРаботыСотрудников);
	
	СписокСотрудников = Новый СписокЗначений;
	Если ЗначениеЗаполнено(Сотрудник) Тогда
		ПараметрыФормы.Вставить("ПоОдномуСотруднику", Истина);
		СписокСотрудников.Добавить(Сотрудник);
	Иначе
		Для Каждого Эл Из Объект.Сотрудники Цикл
			СписокСотрудников.Добавить(Эл.Сотрудник);
		КонецЦикла;
	КонецЕсли;
	ПараметрыФормы.Вставить("КоллекцияСотрудников", СписокСотрудников);
	
	Оповещение = Новый ОписаниеОповещения("ПослеЗаписиДанныхФормыРасписаниеРаботы", ЭтотОбъект);
	ОткрытьФорму("Документ.УстановкаГрафиковРаботы.Форма.РасписаниеРаботы", ПараметрыФормы, ЭтотОбъект, , , , Оповещение, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);
	
КонецПроцедуры

#КонецОбласти

#Область ОбработчикиКомандФормы

&НаКлиенте
Процедура Подбор(Команда)
	
	Если НЕ ЗначениеЗаполнено(Объект.Подразделение) Тогда
		Сообщить("Заполните подразделение");
		Возврат;
	КонецЕсли;
	
	ПараметрыФормы = Новый Структура;
	ПараметрыФормы.Вставить("Подразделение", Объект.Подразделение);
	ОткрытьФорму("Справочник.Сотрудники.Форма.ФормаПодбора", ПараметрыФормы, Элементы.Сотрудники);
	
КонецПроцедуры

&НаКлиенте
Процедура ЗаполнитьПоПроизводственномуГрафику(Команда)
	ЗаполнитьПоПроизводственномуГрафикуНаСервере();
	ОтрисоватьТаблицуДанныеОВремени();
КонецПроцедуры

&НаКлиенте
Процедура ЗаполнитьПоПроизводственномуГрафикуСотрудника(Команда)
	Если ЗначениеЗаполнено(ТекущийСотрудникТаблицыСотрудник) Тогда
		ЗаполнитьПоПроизводственномуГрафикуСотрудникаНаСервере(ТекущийСотрудникТаблицыСотрудник);
		ОтрисоватьТаблицуДанныеОВремени();
	КонецЕсли;
КонецПроцедуры

#КонецОбласти

#Область СлужебныеПроцедурыИФункцииКлиент

&НаКлиенте
Функция ДатаКакМесяцПодобратьДатуПоТексту(Текст, ДатаПоТексту = НеОпределено)
	
	СписокВозврата = Новый СписокЗначений;
	ТекущийГод = Год(ТекущаяДата());
	
	Если ПустаяСтрока(Текст) Тогда
		ДатаПоТексту = Дата(1, 1, 1);
		Возврат СписокВозврата;
	КонецЕсли;
	
	Если СтрНайти(Текст, ".") <> 0 Тогда
		Подстроки = СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок(Текст, ".");
	ИначеЕсли СтрНайти(Текст, ",") <> 0 Тогда
		Подстроки = СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок(Текст, ",");
	ИначеЕсли СтрНайти(Текст, "-") <> 0 Тогда
		Подстроки = СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок(Текст, "-");
	ИначеЕсли СтрНайти(Текст, "/") <> 0 Тогда
		Подстроки = СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок(Текст, "/");
	ИначеЕсли СтрНайти(Текст, "\") <> 0 Тогда
		Подстроки = СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок(Текст, "\");
	Иначе
		Подстроки = СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок(Текст, " ");
	КонецЕсли;
	
	Если Подстроки.Количество() = 1 Тогда
		Если СтроковыеФункцииКлиентСервер.ТолькоЦифрыВСтроке(Текст) Тогда
			МесяцЧислом = Число(Текст);
			Если МесяцЧислом >= 1 И МесяцЧислом <= 12 Тогда
				ДатаПоТексту = Дата(ТекущийГод, МесяцЧислом, 1);
				Если СтрДлина(Текст) = 1 Тогда
					СписокВозврата.Добавить(Формат(ДатаПоТексту, "ДФ='М/гг'"));
				Иначе
					СписокВозврата.Добавить(Формат(ДатаПоТексту, "ДФ='ММ/гг'"));
				КонецЕсли;
			Иначе
				Возврат СписокВозврата;
			КонецЕсли;
		Иначе
			СписокМесяцев = СписокМесяцевПоСтроке(Текст);
			Для Каждого Месяц Из СписокМесяцев Цикл
				ДатаПоТексту = Дата(ТекущийГод, Месяц, 1);
				СписокВозврата.Добавить(Формат(ДатаПоТексту, "ДФ='ММММ гггг'"));
			КонецЦикла;
		КонецЕсли;
		
	ИначеЕсли Подстроки.Количество() = 2 Тогда
		Если СтроковыеФункцииКлиентСервер.ТолькоЦифрыВСтроке(Подстроки[1]) Тогда
			Если ПустаяСтрока(Подстроки[1]) Тогда
				ГодЧислом = 0;
			Иначе
				ГодЧислом = Число(Подстроки[1]);
			КонецЕсли;
			
			Если ГодЧислом > 3000 Тогда
				Возврат СписокВозврата;
			КонецЕсли;
			
			Если СтрДлина(Подстроки[1]) <= 1 Тогда
				ГодЧислом = Число(Лев(Формат(ТекущийГод, "ЧГ="), 3) + Подстроки[1]);
			ИначеЕсли СтрДлина(Подстроки[1]) = 2 Тогда
				ГодЧислом = Число(Лев(Формат(ТекущийГод, "ЧГ="), 2) + Подстроки[1]);
			ИначеЕсли СтрДлина(Подстроки[1]) = 3 Тогда
				ГодЧислом = Число(Лев(Формат(ТекущийГод, "ЧГ="), 1) + Подстроки[1]);
			ИначеЕсли СтрДлина(Подстроки[1]) = 4 Тогда
				ГодЧислом = Число(Подстроки[1]);
			КонецЕсли;
		Иначе
			Возврат СписокВозврата;
		КонецЕсли;
		
		Если ЗначениеЗаполнено(Подстроки[0]) И СтроковыеФункцииКлиентСервер.ТолькоЦифрыВСтроке(Подстроки[0]) Тогда
			МесяцЧислом = Число(Подстроки[0]);
			Если МесяцЧислом >= 1 И МесяцЧислом <= 12 Тогда
				ДатаПоТексту = Дата(ГодЧислом, МесяцЧислом, 1);
				СписокВозврата.Добавить(Формат(ДатаПоТексту, "ДФ='ММММ гггг'"));
			Иначе
				Возврат СписокВозврата;
			КонецЕсли;
		Иначе
			СписокМесяцев = СписокМесяцевПоСтроке(Подстроки[0]);
			Если СписокМесяцев.Количество() = 1 Тогда
				ДатаПоТексту = Дата(ГодЧислом, СписокМесяцев[0], 1);
				СписокВозврата.Добавить(Формат(ДатаПоТексту, "ДФ='ММММ гггг'"));
			Иначе
				Для Каждого Месяц Из СписокМесяцев Цикл
					ДатаПоТексту = Дата(ГодЧислом, Месяц, 1);
					СписокВозврата.Добавить(Формат(Дата(ГодЧислом, Месяц, 1), "ДФ='ММММ гггг'"));
				КонецЦикла;
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	
	Возврат СписокВозврата;
	
КонецФункции

&НаКлиенте
Функция СписокМесяцевПоСтроке(Текст)
	
	СписокМесяцев  = Новый СписокЗначений;
	Месяцы          = Новый Соответствие;
	МесяцыВозврата = Новый Массив;
	
	Для Счетчик = 1 По 12 Цикл
		Представление = Формат(Дата(2000, Счетчик, 1), "ДФ='ММММ'");
		СписокМесяцев.Добавить(Счетчик, Представление);
		Представление = Формат(Дата(2000, Счетчик, 1), "ДФ='МММ'");
		СписокМесяцев.Добавить(Счетчик, Представление);
	КонецЦикла;
	
	Для Каждого ЭлементСписка Из СписокМесяцев Цикл
		Если ВРег(Текст) = ВРег(Лев(ЭлементСписка.Представление, СтрДлина(Текст))) Тогда
			Месяцы[ЭлементСписка.Значение] = 0;
		КонецЕсли;
	КонецЦикла;
	
	Для Каждого Элемент Из Месяцы Цикл
		МесяцыВозврата.Добавить(Элемент.Ключ);
	КонецЦикла;
	
	Возврат МесяцыВозврата;
	
КонецФункции

&НаКлиенте
Процедура ПродолжитьИзменениеМесяцаГрафика()
	Оповещение = Новый ОписаниеОповещения("ПослеВыбораПериода", ЭтотОбъект);
	ПараметрыПериода = Новый Структура("УстановленныйПериод,РежимВыбораПериода", Объект.МесяцГрафика, "Месяц");
	ОткрытьФорму("Документ.УстановкаГрафиковРаботы.Форма.ФормаВыборПериода", ПараметрыПериода, ЭтотОбъект, , , , Оповещение);
КонецПроцедуры

&НаКлиенте
Процедура ПослеВыбораПериода(Результат, ДопПараметры) Экспорт
	Если Результат = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Объект.МесяцГрафика = Результат;
	МесяцРегистрацииСтрокой = Формат(Объект.МесяцГрафика, "ДФ='ММММ гггг'");
	МесяцРегистрацииСтрокойПриИзменении();
КонецПроцедуры

&НаКлиенте
Процедура ЗадатьВопросПриИзмененииДаты()
	Обработчик = Новый ОписаниеОповещения("ОчиститьРасписаниеСотрудниковПослеЗакрытияВопроса", ЭтотОбъект);
	ТекстВопроса = НСтр("ru = 'При изменении месяца будет утеряно нынешнее расписание сотрудников. Продолжить?'");
	ПоказатьВопрос(Обработчик, ТекстВопроса, РежимДиалогаВопрос.ДаНет);
КонецПроцедуры

&НаКлиенте
Процедура ОчиститьРасписаниеСотрудниковПослеЗакрытияВопроса(Результат, Параметры) Экспорт
	Если Результат = КодВозвратаДиалога.Да Тогда
		ПродолжитьИзменениеМесяцаГрафика();
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ЗаполнитьПроизводственныйКалендарь(ГодВыбора)
	Объект.ПроизводственныйКалендарь = Неопределено;
	ПроизводственныйГрафик.Очистить();
	Календарь = ПолучитьКалендарьНаСервере(ГодВыбора);
	Если Календарь <> Неопределено Тогда
		Объект.ПроизводственныйКалендарь = Календарь;
	Иначе
		Сообщить("Отсутствует производственный календарь за " + ГодВыбора + " год.");
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Функция ЕстьДубльСотрудника(Сотрудник, ИдентификаторТекущейСтроки)
	Для Каждого СтрокаТЧ Из Объект.Сотрудники Цикл
		Если СтрокаТЧ.Сотрудник = Сотрудник И СтрокаТЧ.ПолучитьИдентификатор() <> ИдентификаторТекущейСтроки Тогда
			Возврат Истина;
		КонецЕсли;
	КонецЦикла;
	Возврат Ложь;
КонецФункции

&НаКлиенте
Процедура ПослеЗаписиДанныхФормыРасписаниеРаботы(Результат, ДопПараметры) Экспорт
	Если Результат <> Неопределено Тогда
		ПослеЗаписиДанныхФормыРасписаниеРаботыНаСервере(Результат, ДопПараметры);
	КонецЕсли;
	ОтрисоватьТаблицуДанныеОВремени();
КонецПроцедуры

#КонецОбласти

#Область СлужебныеПроцедурыИФункцииСервер

&НаСервереБезКонтекста
Функция ПолучитьКалендарьНаСервере(Знач ГодВыбора)
	Возврат Документы.УстановкаГрафиковРаботы.ПолучитьКалендарь(ГодВыбора);
КонецФункции

&НаСервереБезКонтекста
Функция ПолучитьСписокЗначенийКалендарейНаСервере(Знач ГодВыбора)
	Возврат Документы.УстановкаГрафиковРаботы.ПолучитьСписокЗначенийКалендарей(ГодВыбора);
КонецФункции

&НаСервере
Процедура ПроизводственныйКалендарьПриИзмененииНаСервере()
	Если НЕ ЗначениеЗаполнено(Объект.ПроизводственныйКалендарь) Тогда
		СделатьОсновныеЭлементыФормыНедоступными();
		Сообщить("Заполните производственный график");
	Иначе
		СделатьОсновныеЭлементыФормыДоступными();
		ЗагрузитьТаблицуПроизводственногоКалендаря();
	КонецЕсли;
КонецПроцедуры

&НаСервере
Процедура СделатьОсновныеЭлементыФормыНедоступными()
	Элементы.Сотрудники.Доступность = Ложь;
	Элементы.ДанныеОВремени.Доступность = Ложь;
	Элементы.ЗаполнитьПоПроизводственномуГрафику.Доступность = Ложь;
КонецПроцедуры

&НаСервере
Процедура СделатьОсновныеЭлементыФормыДоступными()
	Элементы.Сотрудники.Доступность = Истина;
	Элементы.ДанныеОВремени.Доступность = Истина;
	Элементы.ЗаполнитьПоПроизводственномуГрафику.Доступность = Истина;
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьДанныеОВремени()
	Для Каждого СтрСотрудник Из Объект.Сотрудники Цикл
		ДобавитьКолонкуСотрудника(СтрСотрудник.Сотрудник);
	КонецЦикла;
КонецПроцедуры

&НаСервере
Процедура ДобавитьКолонкуСотрудника(Сотрудник)
	Если ЗначениеЗаполнено(Сотрудник) Тогда
		ИмяКолонки = ВернутьУникальноеИмяКолонкиСотрудника(Сотрудник);
		
		РекРодителя = ПолучитьРеквизиты("ДанныеОВремени");
		НаличиеРеквизита = Ложь;
		Для Каждого ТекРек Из РекРодителя Цикл
			Если ТекРек.Имя = ИмяКолонки Тогда
				НаличиеРеквизита = Истина;
			КонецЕсли;
		КонецЦикла;
		
		Если НЕ НаличиеРеквизита Тогда
			ЗаголовокКолонки = ВернутьФамилиюИИнициалы(Сотрудник.Наименование);
			
			НовыеРеквизиты = Новый Массив;
			НовыйРеквизит = Новый РеквизитФормы(ИмяКолонки, Новый ОписаниеТипов("Строка"), "ДанныеОВремени", ЗаголовокКолонки, Ложь);
			НовыеРеквизиты.Добавить(НовыйРеквизит);
			ИзменитьРеквизиты(НовыеРеквизиты);
			
			ТаблицаФормы = Элементы.ДанныеОВремени;
			НоваяКолонка = Элементы.Добавить(ИмяКолонки, Тип("ПолеФормы"), ТаблицаФормы);
			НоваяКолонка.Вид = ВидПоляФормы.ПолеВвода;
			НоваяКолонка.ПутьКДанным = "ДанныеОВремени." + ИмяКолонки;
			НоваяКолонка.Заголовок = ЗаголовокКолонки;
		КонецЕсли;
		
		ДобавитьСоответствиеИмениКолонкиИСотрудника(ИмяКолонки, Сотрудник);
		ЗадатьФорматТЧДанныеОВремени();
	КонецЕсли;
КонецПроцедуры

&НаСервере
Процедура ДобавитьСоответствиеИмениКолонкиИСотрудника(ИмяКолонки, Сотрудник)
	Отбор = Новый Структура("Сотрудник, ИмяКолонки", Сотрудник, ИмяКолонки);
	НайденныеСтроки = Объект.СоответствиеКолонокСотрудников.НайтиСтроки(Отбор);
	Если НайденныеСтроки.Количество() = 0 Тогда
		НовоеСоответствие = Объект.СоответствиеКолонокСотрудников.Добавить();
		НовоеСоответствие.ИмяКолонки = ИмяКолонки;
		НовоеСоответствие.Сотрудник = Сотрудник;
	КонецЕсли;
КонецПроцедуры

&НаСервере
Функция ПолучитьСотрудникаПоИмениКолонки(ИмяКолонки)
	Отбор = Новый Структура("ИмяКолонки", ИмяКолонки);
	НайденныеСтроки = Объект.СоответствиеКолонокСотрудников.НайтиСтроки(Отбор);
	Если НайденныеСтроки.Количество() > 0 Тогда
		Возврат НайденныеСтроки[0].Сотрудник;
	КонецЕсли;
	Возврат Справочники.Сотрудники.ПустаяСсылка();
КонецФункции

&НаСервере
Функция ПолучитьИмяКолонкиПоСотруднику(Сотрудник)
	Отбор = Новый Структура("Сотрудник", Сотрудник);
	НайденныеСтроки = Объект.СоответствиеКолонокСотрудников.НайтиСтроки(Отбор);
	Если НайденныеСтроки.Количество() > 0 Тогда
		Возврат НайденныеСтроки[0].ИмяКолонки;
	КонецЕсли;
	Возврат "";
КонецФункции

&НаСервере
Процедура УдалитьСотрудникаИзГрафикаРаботыСотрудников(Сотрудник)
	Если ЗначениеЗаполнено(Сотрудник) Тогда
		Отбор = Новый Структура("Сотрудник", Сотрудник);
		НайденныеСтроки = Объект.ГрафикРаботыСотрудников.НайтиСтроки(Отбор);
		Для Каждого Строка Из НайденныеСтроки Цикл
			Объект.ГрафикРаботыСотрудников.Удалить(Строка);
		КонецЦикла;
	КонецЕсли;
КонецПроцедуры

&НаСервере
Процедура УдалитьКолонкуСотрудников(Сотрудник)
	Если ЗначениеЗаполнено(Сотрудник) Тогда
		ИмяКолонки = ВернутьУникальноеИмяКолонкиСотрудника(Сотрудник);
		ИмяРодителя = "ДанныеОВремени";
		ИмяУдаляемогоРеквизита = ИмяРодителя + "." + ИмяКолонки;
		
		МассивУдаляемыхРеквизитов = Новый Массив;
		РекРодителя = ПолучитьРеквизиты(ИмяРодителя);
		Для Каждого ТекРек Из РекРодителя Цикл
			Если ТекРек.Имя = ИмяКолонки Тогда
				МассивУдаляемыхРеквизитов.Добавить(ИмяУдаляемогоРеквизита);
			КонецЕсли;
		КонецЦикла;
		
		Если МассивУдаляемыхРеквизитов.Количество() > 0 Тогда
			ИзменитьРеквизиты(, МассивУдаляемыхРеквизитов);
		КонецЕсли;
	КонецЕсли;
КонецПроцедуры

&НаСервере
Процедура УдалитьСотрудникаИзСоответствиеКолонокСотрудников(Сотрудник)
	Если ЗначениеЗаполнено(Сотрудник) Тогда
		НомерСтроки = Объект.СоответствиеКолонокСотрудников.Количество() - 1;
		Пока НомерСтроки >= 0 Цикл
			Если Объект.СоответствиеКолонокСотрудников[НомерСтроки].Сотрудник = Сотрудник Тогда
				Объект.СоответствиеКолонокСотрудников.Удалить(НомерСтроки);
			КонецЕсли;
			НомерСтроки = НомерСтроки - 1;
		КонецЦикла;
	КонецЕсли;
КонецПроцедуры

&НаСервере
Функция ВернутьФамилиюИИнициалы(ФИО)
	МассивСлов = СтрРазделить(СокрЛП(ФИО), " ");
	Если МассивСлов.Количество() = 3 Тогда
		Возврат МассивСлов[0] + " " + Лев(МассивСлов[1], 1) + "." + Лев(МассивСлов[2], 1) + ".";
	Иначе
		Возврат СтрСоединить(МассивСлов, " ");
	КонецЕсли;
КонецФункции

&НаСервере
Функция ВернутьУникальноеИмяКолонкиСотрудника(Сотрудник)
	ЧастьУИД = Сред(Строка(СтрЗаменить(Сотрудник.УникальныйИдентификатор(), "-", "_")), 1, 8);
	Возврат "С_" + Сотрудник.Код + "_" + ЧастьУИД;
КонецФункции

&НаСервере
Функция ВернутьГодПроизводственногоКалендаря()
	Возврат Объект.ПроизводственныйКалендарь.Год;
КонецФункции

&НаСервере
Процедура ЗагрузитьТаблицуПроизводственногоКалендаря()
	
	ДатаВыбора = Объект.МесяцГрафика;
	ПроизводственныйКалендарь = Объект.ПроизводственныйКалендарь;
	
	Если НЕ ЗначениеЗаполнено(ПроизводственныйКалендарь) Тогда
		Сообщить("Заполните производственный календарь");
		Возврат;
	КонецЕсли;
	
	ПроизводственныйГрафик.Очистить();
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ
		|	ДанныеПК.Дата КАК Дата,
		|	ДЕНЬНЕДЕЛИ(ДанныеПК.Дата) КАК ДеньНедели,
		|	ДанныеПК.Год КАК Год,
		|	ДанныеПК.ВидДня КАК ВидДня,
		|	ДанныеПК.ПроизводственныйКалендарь.Ссылка КАК ПроизводственныйКалендарьСсылка
		|ПОМЕСТИТЬ ВТ_ДанныеПК
		|ИЗ
		|	РегистрСведений.ДанныеПроизводственногоКалендаря КАК ДанныеПК
		|ГДЕ
		|	ДанныеПК.Дата МЕЖДУ НАЧАЛОПЕРИОДА(&Дата, МЕСЯЦ) И КОНЕЦПЕРИОДА(КОНЕЦПЕРИОДА(&Дата, МЕСЯЦ), ДЕНЬ)
		|	И ДанныеПК.ПроизводственныйКалендарь = &ПроизводственныйКалендарь
		|;
		|
		|ВЫБРАТЬ
		|	ВЫБОР
		|		КОГДА Расписание.ВремяНачала ЕСТЬ NULL ТОГДА НЕОПРЕДЕЛЕНО
		|		ИНАЧЕ Расписание.ВремяНачала
		|	КОНЕЦ КАК ВремяНачала,
		|	ВЫБОР
		|		КОГДА Расписание.ВремяОкончания ЕСТЬ NULL ТОГДА НЕОПРЕДЕЛЕНО
		|		ИНАЧЕ Расписание.ВремяОкончания
		|	КОНЕЦ КАК ВремяОкончания,
		|	ВТ_ДанныеПК.Дата КАК Дата,
		|	ВТ_ДанныеПК.ДеньНедели КАК ДеньНедели,
		|	ВТ_ДанныеПК.ВидДня КАК ВидДня
		|ИЗ
		|	ВТ_ДанныеПК КАК ВТ_ДанныеПК
		|		ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ГрафикРаботы.РасписаниеРаботы КАК Расписание
		|		ПО ВТ_ДанныеПК.ПроизводственныйКалендарьСсылка = Расписание.Ссылка.Ссылка
		|			И ВТ_ДанныеПК.ДеньНедели = Расписание.НомерДня
		|УПОРЯДОЧИТЬ ПО
		|	Дата, ДеньНедели, ВремяНачала";
		
	Запрос.УстановитьПараметр("Дата", ДатаВыбора);
	Запрос.УстановитьПараметр("ПроизводственныйКалендарь", ПроизводственныйКалендарь);
	
	ПроизводственныйГрафик.Загрузить(Запрос.Выполнить().Выгрузить());
	ОтрисоватьТаблицуДанныеОВремени();
	
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьПоПроизводственномуГрафикуНаСервере()
	Если Объект.Сотрудники.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;
	
	Объект.ГрафикРаботыСотрудников.Очистить();
	Для Каждого СтрокаСотрудник Из Объект.Сотрудники Цикл
		Для Каждого СтрокаТЧ Из ПроизводственныйГрафик Цикл
			Если ЗначениеЗаполнено(СтрокаТЧ.ВремяНачала) И ЗначениеЗаполнено(СтрокаТЧ.ВремяОкончания) Тогда
				НоваяСтрока = Объект.ГрафикРаботыСотрудников.Добавить();
				НоваяСтрока.Сотрудник = СтрокаСотрудник.Сотрудник;
				НоваяСтрока.ВремяНачала = СтрокаТЧ.ВремяНачала;
				НоваяСтрока.ВремяОкончания = ?(СтрокаТЧ.ВремяОкончания = Дата(1, 1, 1, 0, 0, 0), Дата(1, 1, 1, 23, 59, 0), СтрокаТЧ.ВремяОкончания);
				НоваяСтрока.Дата = СтрокаТЧ.Дата;
			КонецЕсли;
		КонецЦикла;
	КонецЦикла;
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьПоПроизводственномуГрафикуСотрудникаНаСервере(Сотрудник)
	Отбор = Новый Структура("Сотрудник", Сотрудник);
	НайденныеСтроки = Объект.ГрафикРаботыСотрудников.НайтиСтроки(Отбор);
	Для Каждого Строка Из НайденныеСтроки Цикл
		Объект.ГрафикРаботыСотрудников.Удалить(Строка);
	КонецЦикла;
	
	Для Каждого СтрокаТЧ Из ПроизводственныйГрафик Цикл
		Если ЗначениеЗаполнено(СтрокаТЧ.ВремяНачала) И ЗначениеЗаполнено(СтрокаТЧ.ВремяОкончания) Тогда
			НоваяСтрока = Объект.ГрафикРаботыСотрудников.Добавить();
			НоваяСтрока.Сотрудник = Сотрудник;
			НоваяСтрока.ВремяНачала = СтрокаТЧ.ВремяНачала;
			НоваяСтрока.ВремяОкончания = ?(СтрокаТЧ.ВремяОкончания = Дата(1, 1, 1, 0, 0, 0), Дата(1, 1, 1, 23, 59, 0), СтрокаТЧ.ВремяОкончания);
			НоваяСтрока.Дата = СтрокаТЧ.Дата;
		КонецЕсли;
	КонецЦикла;
КонецПроцедуры

&НаСервере
Процедура ОтрисоватьТаблицуДанныеОВремени()
	
	ТЗГрафикРаботыСотрудников = Объект.ГрафикРаботыСотрудников.Выгрузить();
	Если ТЗГрафикРаботыСотрудников.Количество() = 0 И Объект.Сотрудники.Количество() = 0 Тогда
		ДанныеОВремени.Очистить();
		Возврат;
	КонецЕсли;
	
	СохраненнаяДата = Неопределено;
	Если ТекущаяСтрокаТаблицыДанныеОВремени <> Неопределено
		И ТипЗнч(ТекущаяСтрокаТаблицыДанныеОВремени) = Тип("Структура")
		И ТекущаяСтрокаТаблицыДанныеОВремени.Свойство("Дата") Тогда
		СохраненнаяДата = ТекущаяСтрокаТаблицыДанныеОВремени.Дата;
	КонецЕсли;
	
	ТЗТаблицаДатМесяца = Новый ТаблицаЗначений;
	ТЗТаблицаДатМесяца.Колонки.Добавить("Дата", Новый ОписаниеТипов("Дата"));
	ДатаДляТаблицы = НачалоМесяца(Объект.МесяцГрафика);
	ДатаСледующегоМесяца = НачалоДня(ДобавитьМесяц(ДатаДляТаблицы, 1));
	Пока ДатаДляТаблицы < ДатаСледующегоМесяца Цикл
		ТЗТаблицаДатМесяца.Добавить().Дата = ДатаДляТаблицы;
		ДатаДляТаблицы = КонецДня(ДатаДляТаблицы) + 1;
	КонецЦикла;
	ТЗТаблицаДатМесяца.Сортировать("Дата Возр");
	
	ДанныеОВремени.Очистить();
	
	Запрос = Новый Запрос;
	Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
	Запрос.Текст = 
		"ВЫБРАТЬ ТаблицаДатМесяца.Дата КАК Дата ПОМЕСТИТЬ ВТТаблицаДатМесяца ИЗ &ТаблицаДатМесяца КАК ТаблицаДатМесяца;
		|ВЫБРАТЬ ТаблицаСотрудников.Сотрудник КАК Сотрудник, ТаблицаСотрудников.ВремяНачала КАК ВремяНачала, ТаблицаСотрудников.ВремяОкончания КАК ВремяОкончания, ТаблицаСотрудников.Дата КАК Дата ПОМЕСТИТЬ ВТТаблицаСотрудников ИЗ &ТаблицаСотрудников КАК ТаблицаСотрудников;
		|ВЫБРАТЬ ВТТаблицаДатМесяца.Дата КАК Дата, ВТТаблицаСотрудников.Сотрудник КАК Сотрудник, ВТТаблицаСотрудников.ВремяНачала КАК ВремяНачала, ВТТаблицаСотрудников.ВремяОкончания КАК ВремяОкончания ИЗ ВТТаблицаДатМесяца КАК ВТТаблицаДатМесяца ЛЕВОЕ СОЕДИНЕНИЕ ВТТаблицаСотрудников КАК ВТТаблицаСотрудников ПО ВТТаблицаДатМесяца.Дата = ВТТаблицаСотрудников.Дата УПОРЯДОЧИТЬ ПО Дата, Сотрудник, ВремяНачала";
		
	Запрос.УстановитьПараметр("ТаблицаСотрудников", ТЗГрафикРаботыСотрудников);
	Запрос.УстановитьПараметр("ТаблицаДатМесяца", ТЗТаблицаДатМесяца);
	
	Выборка = Запрос.Выполнить().Выбрать();
	СтрокиПоДатам = Новый Соответствие;
	
	Пока Выборка.Следующий() Цикл
		ТекущаяДатаВыборки = Выборка.Дата;
		ДниМесяцаСтр = Формат(ТекущаяДатаВыборки, "ДФ='dd ddd'");
		
		Если СтрокиПоДатам.Получить(ТекущаяДатаВыборки) <> Неопределено Тогда
			МассивСтрок = СтрокиПоДатам[ТекущаяДатаВыборки];
		Иначе
			МассивСтрок = Новый Массив;
			НоваяСтрока = ДанныеОВремени.Добавить();
			НоваяСтрока.Дата = ТекущаяДатаВыборки;
			НоваяСтрока.ДниМесяца = ДниМесяцаСтр;
			НайденныеСтроки = ПроизводственныйГрафик.НайтиСтроки(Новый Структура("Дата", ТекущаяДатаВыборки));
			НоваяСтрока.ВидДня = ?(НайденныеСтроки.Количество() > 0, НайденныеСтроки[0].ВидДня, Неопределено);
			МассивСтрок.Добавить(НоваяСтрока);
			СтрокиПоДатам.Вставить(ТекущаяДатаВыборки, МассивСтрок);
		КонецЕсли;
		
		Если НЕ ЗначениеЗаполнено(Выборка.Сотрудник) Тогда
			Продолжить;
		КонецЕсли;
		
		ИмяКолонки = ПолучитьИмяКолонкиПоСотруднику(Выборка.Сотрудник);
		Интервал = ?(Формат(Выборка.ВремяНачала, "ДФ=ЧЧ:мм") = "", "00:00", Формат(Выборка.ВремяНачала, "ДФ=ЧЧ:мм")) + " - " + ?(Формат(Выборка.ВремяОкончания, "ДФ=ЧЧ:мм") = "", "00:00", Формат(Выборка.ВремяОкончания, "ДФ=ЧЧ:мм")) + " (" + ДниМесяцаСтр + ")";
		
		СтрокаДляЗаписи = Неопределено;
		Для Каждого СтрокаДанных Из МассивСтрок Цикл
			Если ПустаяСтрока(СтрокаДанных[ИмяКолонки]) Тогда
				СтрокаДляЗаписи = СтрокаДанных;
				Прервать;
			КонецЕсли;
		КонецЦикла;
		
		Если СтрокаДляЗаписи = Неопределено Тогда
			СтрокаДляЗаписи = ДанныеОВремени.Добавить();
			СтрокаДляЗаписи.ВидДня = ?(НайденныеСтроки.Количество() > 0, НайденныеСтроки[0].ВидДня, Неопределено);
			СтрокаДляЗаписи.Дата = ТекущаяДатаВыборки;
			МассивСтрок.Добавить(СтрокаДляЗаписи);
		КонецЕсли;
		
		СтрокаДляЗаписи[ИмяКолонки] = Интервал;
	КонецЦикла;
	
	Если СохраненнаяДата <> Неопределено Тогда
		Для Каждого СтрокаДанных Из ДанныеОВремени Цикл
			Если СохраненнаяДата = СтрокаДанных.Дата Тогда
				Элементы.ДанныеОВремени.ТекущаяСтрока = СтрокаДанных.ПолучитьИдентификатор();
				Прервать;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	
	УстановитьУсловноеОформлениеДанныеОВремени();
	
КонецПроцедуры

&НаСервере
Процедура УстановитьУсловноеОформлениеДанныеОВремени()
	
	ЭлементОформления = УсловноеОформление.Элементы.Добавить();
	ЭлементОформления.Оформление.УстановитьЗначениеПараметра("ЦветФона", Новый Цвет(245, 251, 255));
	
	ЭлементОтбора = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ДанныеОВремени.ВидДня");
	ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
	
	СписокВидовДней = Новый СписокЗначений;
	СписокВидовДней.Добавить(Перечисления.ВидыДнейПроизводственногоКалендаря.Суббота);
	СписокВидовДней.Добавить(Перечисления.ВидыДнейПроизводственногоКалендаря.Воскресенье);
	ЭлементОтбора.ПравоеЗначение = СписокВидовДней;
	ЭлементОтбора.Использование = Истина;
	
	ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
	ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("ДанныеОВремени");
	
	// Праздники
	ЭлементОформленияПраздник = УсловноеОформление.Элементы.Добавить();
	ЭлементОформленияПраздник.Оформление.УстановитьЗначениеПараметра("ЦветФона", Новый Цвет(255, 225, 232));
	
	ЭлементОтбораПраздник = ЭлементОформленияПраздник.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ЭлементОтбораПраздник.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ДанныеОВремени.ВидДня");
	ЭлементОтбораПраздник.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
	ЭлементОтбораПраздник.ПравоеЗначение = Перечисления.ВидыДнейПроизводственногоКалендаря.Праздник;
	ЭлементОтбораПраздник.Использование = Истина;
	
	ПолеОформленияПраздник = ЭлементОформленияПраздник.Поля.Элементы.Добавить();
	ПолеОформленияПраздник.Поле = Новый ПолеКомпоновкиДанных("ДанныеОВремени");
	
	// Нерабочие
	ЭлементОформленияНерабочий = УсловноеОформление.Элементы.Добавить();
	ЭлементОформленияНерабочий.Оформление.УстановитьЗначениеПараметра("ЦветФона", Новый Цвет(240, 240, 240));
	
	ЭлементОтбораНерабочий = ЭлементОформленияНерабочий.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ЭлементОтбораНерабочий.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ДанныеОВремени.ВидДня");
	ЭлементОтбораНерабочий.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
	ЭлементОтбораНерабочий.ПравоеЗначение = Перечисления.ВидыДнейПроизводственногоКалендаря.Нерабочий;
	ЭлементОтбораНерабочий.Использование = Истина;
	
	ПолеОформленияНерабочий = ЭлементОформленияНерабочий.Поля.Элементы.Добавить();
	ПолеОформленияНерабочий.Поле = Новый ПолеКомпоновкиДанных("ДанныеОВремени");
	
КонецПроцедуры

&НаСервере
Процедура ЗадатьФорматТЧДанныеОВремени()
	Элементы.ДанныеОВремени.РастягиватьПоВертикали = Истина;
	Элементы.ДанныеОВремени.РастягиватьПоГоризонтали = Истина;
	Элементы.ДанныеОВремени.Ширина = 100;
	Элементы.ДанныеОВремени.ПодчиненныеЭлементы.ДанныеОВремениГруппаКолонок.РастягиватьПоВертикали = Истина;
	Элементы.ДанныеОВремени.ПодчиненныеЭлементы.ДанныеОВремениГруппаКолонок.РастягиватьПоГоризонтали = Ложь;
	
	КоллекцияЭлементов = Элементы.ДанныеОВремени.ПодчиненныеЭлементы;
	Для Индекс = 1 По КоллекцияЭлементов.Количество() - 1 Цикл
		КоллекцияЭлементов[Индекс].ТолькоПросмотр = Истина;
		КоллекцияЭлементов[Индекс].РежимРедактирования = РежимРедактированияКолонки.Непосредственно;
		КоллекцияЭлементов[Индекс].ГоризонтальноеПоложениеВШапке = ГоризонтальноеПоложениеЭлемента.Центр;
		КоллекцияЭлементов[Индекс].ГоризонтальноеПоложение = ГоризонтальноеПоложениеЭлемента.Центр;
	КонецЦикла;
	
	КоллекцияЭлементовГруппы = Элементы.ДанныеОВремени.ПодчиненныеЭлементы.ДанныеОВремениГруппаКолонок.ПодчиненныеЭлементы;
	Для Индекс = 0 По КоллекцияЭлементовГруппы.Количество() - 1 Цикл
		КоллекцияЭлементовГруппы[Индекс].ТолькоПросмотр = Истина;
		КоллекцияЭлементовГруппы[Индекс].РежимРедактирования = РежимРедактированияКолонки.Непосредственно;
	КонецЦикла;
КонецПроцедуры

&НаСервере
Процедура ПослеЗаписиДанныхФормыРасписаниеРаботыНаСервере(Результат, ДопПараметры)
	
	КоллекцияСотрудников = Результат.КоллекцияСотрудников;
	ГрафикРаботыПоКонкретномуСотруднику = Результат.ГрафикРаботыПоКонкретномуСотруднику;
	ДатаРедактирования = Результат.ДатаРедактирования;
	
	Для Индекс = 0 По КоллекцияСотрудников.Количество() - 1 Цикл
		Отбор = Новый Структура("Сотрудник, Дата", КоллекцияСотрудников[Индекс].Значение, ДатаРедактирования);
		НайденныеСтроки = Объект.ГрафикРаботыСотрудников.НайтиСтроки(Отбор);
		Для Каждого Строка Из НайденныеСтроки Цикл
			Объект.ГрафикРаботыСотрудников.Удалить(Строка);
		КонецЦикла;
	КонецЦикла;
	
	НайденныеСтроки = ГрафикРаботыПоКонкретномуСотруднику.НайтиСтроки(Новый Структура("Дата", ДатаРедактирования));
	Для Каждого Строка Из НайденныеСтроки Цикл
		НоваяСтрока = Объект.ГрафикРаботыСотрудников.Добавить();
		НоваяСтрока.Сотрудник = Строка.Сотрудник;
		НоваяСтрока.Дата = Строка.Дата;
		НоваяСтрока.ВремяНачала = Строка.ВремяНачала;
		НоваяСтрока.ВремяОкончания = Строка.ВремяОкончания;
	КонецЦикла;
	
КонецПроцедуры

&НаСервере
Процедура ОчиститьГрафикРаботыСотрудников()
	Объект.ГрафикРаботыСотрудников.Очистить();
	ОтрисоватьТаблицуДанныеОВремени();
КонецПроцедуры

#КонецОбласти

```