Как вывести контактную информацию и реквизиты документа в печатную форму 1С 8.3

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия
← На главную

При разработке или модификации печатных форм в «1С:Бухгалтерия предприятия 3.0» программисты часто сталкиваются с трудностями при попытке «дотянуться» до данных, которые не были предусмотрены типовым механизмом. Типичные ошибки, такие как «Поле объекта не обнаружено» или «Переменная не определена», возникают из-за различий в архитектуре платформ 1С 7.7 и 8.3. В этой статье мы подробно разберем, как правильно извлекать контактную информацию контрагентов и реквизиты документов для вывода в макет.

Причина ошибки при обращении к контактной информации

Рассмотрим ситуацию: вам необходимо вывести номер телефона контрагента. Начинающий разработчик часто пытается обратиться к данным напрямую через точку, например: Шапка.Контрагент.КонтактнаяИнформация.НомерТелефона. Программа выдает ошибку, так как КонтактнаяИнформация — это не просто поле, а табличная часть справочника. Прямое обращение к имени поля внутри табличной части без указания конкретной строки невозможно.

Проанализируем самый простой способ решения, который часто применяется для быстрого исправления, если в справочнике гарантированно заполнена только одна строка с телефоном:


// Не самый надежный, но рабочий способ «в лоб»
ДанныеПечати.Вставить("ТелефонКонтрагента", Шапка.Контрагент.КонтактнаяИнформация[0].НомерТелефона);

Однако следует помнить, что обращение по индексу [0] опасно. Если в табличной части первой строкой будет записан адрес, а не телефон, вы получите пустой результат или некорректные данные. Кроме того, в современных конфигурациях на базе БСП (Библиотеки стандартных подсистем) данные могут храниться в виде JSON или XML в поле ЗначенияПолей.

Правильный метод получения контактной информации через API

Выясним, как сделать получение данных надежным. В 1С 8.3 для этих целей предусмотрен программный интерфейс в общих модулях. Вместо ручного перебора табличной части, воспользуемся методами БСП. Это гарантирует, что мы получим именно телефон, независимо от количества строк в табличной части.

Рассмотрим пример кода, который лучше использовать в модуле менеджера:


// Используем стандартную функцию получения представления
ТелефонЗначение = УправлениеКонтактнойИнформацией.ПредставлениеКонтактнойИнформацииОбъекта(
    Шапка.Контрагент, 
    Справочники.ВидыКонтактнойИнформации.ТелефонКонтрагента
);
ДанныеПечати.Вставить("ТелефонКонтрагента", ТелефонЗначение);

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

Как вывести реквизит текущего документа (например, Водителя)

Следующая распространенная проблема — обращение к реквизитам самого документа, который мы печатаем. Часто попытка написать ТекущийДокумент.Водитель приводит к ошибке «Переменная не определена». Это происходит потому, что в модуле менеджера (где обычно формируются данные для печати) нет контекста «этого объекта», как в модуле формы или модуля объекта.

Разберем, как получить доступ к реквизиту Водитель. Если у вас уже есть структура Шапка, полученная из запроса, проверьте, включено ли туда нужное поле. Если поле в запросе отсутствует, разработчики иногда используют «быстрый» путь через обращение к ссылке:


// Обращение через ссылку (допустимо, но не оптимально)
ДанныеПечати.Вставить("ВодительПоставщика", Шапка.Ссылка.Водитель);

Хотя этот код сработает, важно понимать его недостатки. Обращение через точку от ссылки (Шапка.Ссылка.Водитель) заставляет платформу выполнить отдельный неявный запрос к базе данных для получения всего объекта целиком. Если вы печатаете сразу 50 накладных, программа сделает 50 лишних запросов, что замедлит работу системы. Это называется проблемой разыменовывания ссылок.

Оптимизация: изменение основного запроса печати

Проанализируем самый правильный с точки зрения производительности путь. В модуле менеджера найдите функцию, которая отвечает за сбор данных (обычно она называется СформироватьЗапросДляПечати или находится внутри процедуры Печать). Вам нужно найти текст запроса и добавить туда ваш реквизит.

Посмотрим на пример модификации запроса:


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

// После выполнения запроса данные попадают в выборку
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    // Теперь поле доступно напрямую из выборки без лишних запросов
    ДанныеПечати.Вставить("ВодительПоставщика", Выборка.Водитель);
КонецЦикла;

Почему нельзя использовать формулы прямо в макете, как в 1С 7.7?

Многие пользователи, пришедшие из «семерки», пытаются вписать выражение типа Шапка.Контрагент.Телефон прямо в ячейку макета. В 1С 8.3 это невозможно. Макет в восьмой версии работает иначе:

  1. Ячейка макета должна иметь тип Параметр.
  2. Имя этого параметра (например, ВодительПоставщика) должно точно совпадать с ключом, который вы указываете в коде в структуре ДанныеПечати.Вставить("Ключ", Значение).
  3. Платформа не вычисляет выражения внутри макета. Всю логику (склеивание строк, форматирование дат, поиск телефонов) необходимо реализовать в коде модуля менеджера и передать в макет уже готовое строковое значение.

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


КонтактнаяИнфо = Телефон + ", " + Адрес;
ДанныеПечати.Вставить("КонтактнаяИнформацияДляПечати", КонтактнаяИнфо);

Резюме и рекомендации

Подведем итоги нашего разбора. Для успешного вывода данных в печатную форму придерживайтесь следующих правил:

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

← На главную