Как исправить ошибку «Объект не найден» при создании документа в модуле объекта и правильно организовать взаимодействие между модулем объекта и формой в 1С?

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

При разработке и доработке конфигураций на платформе 1С:Предприятие программисты часто сталкиваются с неочевидными ошибками, которые на первый взгляд кажутся сбоем самой платформы. Одним из таких примеров является ошибка «Объект не найден» (или «Переменная не определена») при попытке обратиться к стандартным глобальным коллекциям, например, к менеджеру документов через конструкцию Документы.УстановкаЦенНоменклатуры.СоздатьДокумент().

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

---

Причина ошибки: Конфликт имен и перекрытие глобального контекста

Проанализируем ситуацию, описанную в исходном обращении. Разработчик пытается создать документ из модуля объекта дополнительной обработки, но получает ошибку. Выясняется, что в самой обработке создана табличная часть или реквизит с именем Документы.

В платформе 1С действует строгое правило приоритета областей видимости (контекстов). Локальный контекст модуля (реквизиты объекта, табличные части, локальные переменные) всегда имеет наивысший приоритет над глобальным контекстом.

Когда вы пишете код:

Док = Документы.УстановкаЦенНоменклатуры.СоздатьДокумент();

Платформа видит слово Документы и в первую очередь ищет его внутри локальных реквизитов объекта. Обнаружив табличную часть с именем Документы, компилятор считает, что вы обращаетесь именно к этой табличной части. Разумеется, у табличной части нет свойства (колонки) или метода с именем УстановкаЦенНоменклатуры, из-за чего система выдает ошибку о том, что объект или свойство не найдено.

Именовать реквизиты, табличные части или локальные переменные именами глобальных коллекций (Документы, Справочники, РегистрыСведений, ПланыВидовХарактеристик и т.д.) — это грубейшая ошибка разработки, которая приводит к трудночитаемому и нерабочему коду.

---

Вариант решения 1: Исправление метаданных (Рекомендуемый способ)

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

Разберем по шагам, как это сделать:

  1. Откройте вашу обработку в конфигураторе.
  2. Перейдите на вкладку «Основные» или «Данные».
  3. Найдите табличную часть или реквизит с именем Документы.
  4. Переименуйте его в осмысленное имя, отражающее суть данных, например: ТаблицаДокументов, СписокДокументов или ДокументыДляОбработки.
  5. Выполните глобальный поиск по тексту модулей вашей обработки для замены старого имени Документы на новое имя во всех алгоритмах.

После этого глобальный контекст Документы снова станет доступен в модуле объекта напрямую, и создание документа отработает без ошибок.

---

Вариант решения 2: Обход перекрытия через функцию «Вычислить()»

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

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

Посмотрим на пример кода в модуле объекта:


// Получаем менеджер документа напрямую из глобального контекста
МенеджерДокумента = Вычислить("Документы.УстановкаЦенНоменклатуры");
НовыйДокумент = МенеджерДокумента.СоздатьДокумент();

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

---

Архитектурный вопрос: Вызов процедур формы из модуля объекта

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

Выясним причину этого запрета. Модуль объекта выполняется исключительно на сервере. Он описывает бизнес-логику сущности, которая должна уметь работать в фоновом режиме, в регламентных заданиях, через Web-сервисы или программный вызов из других модулей, когда никакой открытой формы и активного пользователя перед монитором нет вообще.

Попытка вызвать код интерфейса (модуля формы) из объектной логики нарушает паттерн MVC (Model-View-Controller). Форма может обращаться к объекту, но объект ничего не должен знать о форме, которая его вызвала.

Рассмотрим правильные архитектурные варианты переноса и вызова логики.

---

Способ А: Перенос логики в модуль объекта (Правильный подход)

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

Шаг 1. Опишем процедуру создания документа в модуле объекта нашей обработки:


// В модуле объекта
Процедура СоздатьДокументУстановкиЦен(ПараметрыДокумента) Экспорт
    
    НовыйДок = Документы.УстановкаЦенНоменклатуры.СоздатьДокумент();
    НовыйДок.Дата = ТекущаяДата();
    // Заполнение реквизитов из переданных параметров
    // ...
    НовыйДок.Записать(РежимЗаписиДокумента.Запись);
    
КонецПроцедуры

Шаг 2. Вызовем этот метод из модуля управляемой формы при нажатии на кнопку:


// В модуле формы
&НаСервере
Процедура СоздатьДокументНаСервере()
    
    // Преобразуем данные формы в прикладной объект обработки
    ОбъектОбработки = РеквизитФормыВЗначение("Объект");
    
    // Подготовим параметры для создания
    ПараметрыДок = Новый Структура;
    // Заполняем структуру данными с формы
    
    // Вызываем экспортный метод объекта
    ОбъектОбработки.СоздатьДокументУстановкиЦен(ПараметрыДок);
    
КонецПроцедуры

&НаКлиенте
Процедура КомандаСоздатьДокумент(Команда)
    СоздатьДокументНаСервере();
КонецПроцедуры

---

Способ Б: Передача контекста формы в модуль объекта

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

Посмотрим на пример реализации этого механизма.

Шаг 1. В модуле управляемой формы определяем экспортную серверную процедуру, которая готовит или обрабатывает данные:


// В модуле формы
&НаСервере
Функция ПолучитьДополнительныеДанныеФормы() Экспорт
    // Возвращаем структуру нужных нам данных, доступных только на форме
    Возврат Новый Структура("Склад, Ответственный", Объект.Склад, ПараметрыСеанса.ТекущийПользователь);
КонецФункции

&НаСервере
Процедура ВыполнитьОбработкуНаСервере()
    ОбъектОбработки = РеквизитФормыВЗначение("Объект");
    // Передаем форму (ЭтаФорма) в качестве параметра
    ОбъектОбработки.ВыполнитьДействие(ЭтаФорма);
КонецПроцедуры

Шаг 2. В модуле объекта принимаем форму как параметр и работаем с ее экспортными методами:


// В модуле объекта
Процедура ВыполнитьДействие(ФормаКонтекст) Экспорт
    
    // Мы можем прочитать данные, вызвав экспортную функцию формы
    ДанныеФормы = ФормаКонтекст.ПолучитьДополнительныеДанныеФормы();
    
    // Создаем документ, используя полученные данные
    НовыйДок = Документы.УстановкаЦенНоменклатуры.СоздатьДокумент();
    НовыйДок.Дата = ТекущаяДата();
    НовыйДок.Склад = ДанныеФормы.Склад;
    НовыйДок.Ответственный = ДанныеФормы.Ответственный;
    
    НовыйДок.Записать();
    
КонецПроцедуры

---

Особенности для дополнительных обработок (БСП)

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

В этом случае в модуле объекта обязательно присутствует экспортная процедура ВыполнитьКоманду. Обратите внимание на то, как БСП передает параметры запуска:


// В модуле объекта дополнительной обработки
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполнения) Экспорт
    
    // ПараметрыВыполнения - это структура БСП.
    // В ней содержится ссылка на форму, из которой была запущена команда.
    Если ПараметрыВыполнения.Свойство("ЭтаФорма") Тогда
        ВызывающаяФорма = ПараметрыВыполнения.ЭтаФорма;
        // Теперь у нас есть доступ к контексту формы-владельца
    КонецЕсли;
    
    // Реализация логики создания документа
    Если ИдентификаторКоманды = "СоздатьДокументУстановки" Тогда
        // Код создания документа...
    КонецЕсли;
    
КонецПроцедуры

Важное правило при работе с БСП: Никогда не пытайтесь открыть форму созданного документа непосредственно из кода модуля объекта (сервер не работает с интерфейсом напрямую). Вместо этого запишите созданный документ, получите его ссылку и верните эту ссылку обратно на клиент через параметры выполнения команды. Клиентская часть БСП сама корректно откроет форму нового документа пользователю на клиенте.

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

← На главную