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