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