Как исправить ошибку «Переменная не определена (ТекущийДокумент)» при переходе из журнала в документ в 1С 7.7

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При разработке и кастомизации интерфейсов в платформе 1С:Предприятие 7.7 программисты часто сталкиваются с аппаратными ограничениями и особенностями работы контекстов выполнения. Распространенной задачей является визуальное оформление списков: добавление пиктограмм (иконок) статуса, раскраска строк или вывод динамических текстовых данных в графах журнала.

Однако попытка реализовать такое оформление может привести к неожиданной ошибке компиляции при открытии документа из этого журнала: Переменная не определена (ТекущийДокумент). В этой статье мы подробно разберем, почему возникает эта ошибка, как работает контекст различных форм в 1С 7.7 и как правильно организовать архитектуру кода, чтобы избежать подобных конфликтов.

Анализ исходной ситуации и причины возникновения ошибки

Рассмотрим сценарий, в котором возникает проблема. Разработчик добавляет в форму журнала документов новую текстовую колонку, в формуле которой вызывает функцию для динамического вывода пиктограмм или форматирования, например, ПоказыватьП().

В модуле формы журнала объявляется следующая функция:


Функция ПоказыватьП()
    Возврат ТекущийДокумент.Статус.ПорядковыйНомер(); 
КонецФункции

В самом журнале всё отображается корректно: пиктограммы выводятся на основе статуса документа. Однако при попытке открыть любой документ (например, двойным кликом мыши по строке журнала) система выдает ошибку:


Возврат ТекущийДокумент<<?>>.Статус.ПорядковыйНомер(); 
{Документ.ПередачаВЗал.Форма.Модуль(8)}: Переменная не определена (ТекущийДокумент)

Казалось бы, код написан в модуле журнала, и форма документа «ПередачаВЗал» не должна иметь к нему отношения. Выясним истинную причину этой проблемы. Она кроется в двух аспектах: разнице контекстов выполнения и использовании директивы препроцессора #ЗагрузитьИзФайла.

Различие контекстов: Журнал vs Документ

Для правильного понимания сути проблемы проанализируем, как обращаться к текущему документу в разных объектах метаданных 1С 7.7:

  1. В контексте формы Журнала: Переменная ТекущийДокумент является предопределенным локальным атрибутом (свойством) формы списка. Он доступен только для чтения и динамически возвращает ссылку на тот документ, на котором в данный момент установлена активная строка в табличной части журнала. Обращение к нему без круглых скобок абсолютно корректно и возвращает объект типа "Документ".
  2. В контексте формы самого Документа: Такого атрибута, как ТекущийДокумент, не существует. Вместо него в модуле формы документа доступен встроенный метод (функция) ТекущийДокумент(), который возвращает ссылку на текущий открытый экземпляр документа. По правилам синтаксиса 1С 7.7, вызов метода без круглых скобок компилятор пытается интерпретировать как обращение к переменной. Поскольку переменная с таким именем в модуле документа не объявлена, система генерирует ошибку Переменная не определена.

Коварство директивы #ЗагрузитьИзФайла

Почему же код, предназначенный для журнала, внезапно начал компилироваться внутри формы документа? Ответ кроется в использовании механизма #ЗагрузитьИзФайла (или его англоязычного аналога ftLoadFromFile).

Эта директива используется разработчиками для отладки кода «на лету». Она прописывается в первой строке модуля конфигуратора и заставляет систему при открытии формы игнорировать внутренний текст модуля и динамически компилировать код из внешнего текстового файла. Это позволяет вносить изменения в логику без монопольного сохранения конфигурации и перезапуска сеанса "1С:Предприятие".

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

---

Варианты устранения ошибки и правильные решения

Рассмотрим несколько способов исправления ситуации — от самого быстрого до наиболее архитектурно правильного.

Решение 1. Разделение внешних файлов отладки

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

После завершения этапа разработки и отладки рекомендуется полностью отказаться от директивы #ЗагрузитьИзФайла, перенеся стабильный код непосредственно в модули конфигурации 1С.

Решение 2. Написание универсального кода для общего файла

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

Определим функцию в общем файле (или Глобальном модуле с ключевым словом Экспорт) следующим образом:


Функция ПоказыватьП(КонтекстДокумента) Экспорт
    Если ПустоеЗначение(КонтекстДокумента) = 1 Тогда
        Возврат "";
    КонецЕсли;
    
    // Проверяем выбранность документа перед обращением к реквизитам
    Если КонтекстДокумента.Выбран() = 0 Тогда
        Возврат "";
    КонецЕсли;
    
    Возврат КонтекстДокумента.Статус.ПорядковыйНомер();
КонецФункции

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

Решение 3. Использование конструкции двойного вызова

В 1С 7.7 существует синтаксический нюанс: выражение ТекущийДокумент.ТекущийДокумент() работает безошибочно в контексте журнала. Первое слово обращается к атрибуту строки журнала, а последующий метод возвращает чистую ссылку на объект. В контексте же самого документа конструкция ТекущийДокумент() вернет ту же ссылку. Однако для предотвращения путаницы лучшей практикой остается явная передача контекста через параметры, как показано в Решении 2.

---

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

Реализуя функции раскраски или вывода пиктограмм в списках (журналах, справочниках), всегда придерживайтесь двух золотых правил разработчика 1С 7.7:

1. Обязательная проверка на выбранность объекта

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

Всегда добавляйте защитное условие на самом старте функции:


Если ТекущийДокумент.Выбран() = 0 Тогда
    Возврат ""; // Возвращаем пустую строку для невыбранных строк
КонецЕсли;

2. Оптимизация производительности

Поскольку функции в графах журнала рассчитываются «на лету» при каждом скроллинге (прокрутке списка пользователем), они должны выполняться мгновенно. Крайне не рекомендуется внутри таких функций:

Допустимым является легкое обращение к реквизитам шапки документа (таким как статус, проведен, дата) или использование простых условных операторов Если ... ИначеЕсли для назначения цвета или индекса картинки.

← На главную