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