Почему возникает ошибка Ссылка не определено при переносе кода печати в управляемые формы?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Переход с обычных форм на управляемые в платформе 1С:Предприятие 8.3 — это не просто смена интерфейса, но и глубокое изменение архитектуры работы с данными. Одной из самых частых проблем, с которой сталкиваются разработчики, является ошибка Ссылка не определено или Объект не определен при попытке выполнить код, который раньше успешно работал в обычных формах. Рассмотрим подробнее, почему это происходит и как правильно адаптировать логику печати под современные стандарты.

Разберем причину ошибки: разница контекстов модуля объекта и модуля менеджера

Проанализируем ситуацию, описанную автором темы. В старых конфигурациях (на обычных формах) код формирования печатных форм чаще всего располагался в модуле объекта документа. В этом модуле разработчику доступны все реквизиты объекта напрямую (например, Дата, Номер) или через ключевые слова ЭтотОбъект и Ссылка. Платформа автоматически подтягивает данные текущего документа в память.

В современных конфигурациях на управляемых формах (особенно использующих БСП — Библиотеку стандартных подсистем) логика формирования печатных форм выносится в модуль менеджера. Это делается из соображений производительности:

  1. Экономия ресурсов: Модуль менеджера позволяет получить данные через запрос, не загружая в память тяжелый объект со всеми его табличными частями.
  2. Групповая печать: Менеджер может эффективно обработать сразу массив ссылок, сформировав одну общую выборку данных.

Основная проблема заключается в том, что в модуле менеджера отсутствует контекст конкретного экземпляра объекта. Там нет ни ЭтотОбъект, ни предопределенной переменной Ссылка. Менеджер — это набор общих инструментов для всех документов данного типа, и он "не знает", какой именно документ вы хотите напечатать, пока вы явно не передадите ему ссылку на него.

Анализируем ситуацию: работа в модуле объекта

Если бы ваш код действительно находился в модуле объекта, то обращение Ссылка.ДатаСФ было бы избыточным, но допустимым. Однако правильнее было бы обращаться напрямую к реквизиту. Посмотрим на правильный пример для модуля объекта:


Если Не ЗначениеЗаполнено(ДатаСФ) Тогда
    ДП = "''___''________________20__г";
Иначе 
    ДП = Формат(ДатаСФ, "ДФ=dd.MM.yyyy");
КонецЕсли;

Здесь ДатаСФ доступна напрямую, так как модуль объекта уже содержит в себе данные реквизитов. Но, как выяснилось в обсуждении, код автора находился в модуле менеджера, где такой подход работать не будет.

Решение проблемы в модуле менеджера

Рассмотрим, как правильно реализовать ту же логику в модуле менеджера. Обычно процедура печати в управляемом приложении выглядит так:


Процедура Печать(МассивОбъектов, ПараметрыПечати, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
    // Логика подготовки данных
КонецПроцедуры

В данном контексте у нас есть МассивОбъектов, содержащий ссылки на документы. Чтобы получить значение ДатаСФ, мы должны либо обратиться к базе данных через запрос (рекомендуемый способ), либо получить данные напрямую от ссылки (допустимо для простых задач, но медленнее).

Вариант 1: Получение данных через запрос (Оптимально)

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


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

Запрос.УстановитьПараметр("МассивОбъектов", МассивОбъектов);
Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл
    Если Не ЗначениеЗаполнено(Выборка.ДатаСФ) Тогда
        ДП = "''___''________________20__г";
    Иначе 
        ДП = Формат(Выборка.ДатаСФ, "ДФ=dd.MM.yyyy");
    КонецЕсли;
    // Далее код заполнения параметров макета...
КонецЦикла;

Вариант 2: Прямое обращение через точку (Для быстрой правки)

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


// Предположим, мы перебираем МассивОбъектов
Для Каждого ТекущаяСсылка Из МассивОбъектов Цикл
    Если Не ЗначениеЗаполнено(ТекущаяСсылка.ДатаСФ) Тогда
        ДП = "''___''________________20__г";
    Иначе 
        ДП = Формат(ТекущаяСсылка.ДатаСФ, "ДФ=dd.MM.yyyy");
    КонецЕсли;
КонецЦикла;

Важные моменты при работе с датами на управляемых формах

Проанализируем функцию ЗначениеЗаполнено. В 1С пустая дата — это 01.01.0001 00:00:00. Ваша проверка корректно отсекает это значение. Однако при работе в управляемом интерфейсе стоит помнить о нескольких правилах:

Итоги

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

  1. Убедитесь, что вы понимаете, в каком модуле находитесь (Объекта или Менеджера).
  2. В модуле менеджера забудьте про использование слова Ссылка как контекстной переменной. Используйте ссылки, переданные в параметрах процедур.
  3. Всегда отдавайте предпочтение запросам для получения данных реквизитов. Это сделает ваш код профессиональным и быстрым.

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

← На главную