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