Как программно обратиться к реквизитам управляемой формы и заполнить их извне

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

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

В чем причина ошибки: Реквизиты объекта vs Реквизиты формы

Проанализируем ситуацию, описанную в теме. Разработчик добавил реквизит Наименование2 непосредственно в редакторе формы, но не добавил его в дерево метаданных самого справочника. Это ключевой момент. В 1С управляемые формы работают по принципу четкого разделения данных:

  1. Реквизиты объекта: Это поля, которые описаны в конфигураторе в дереве метаданных (например, Код, Наименование, ИНН). Они хранятся в таблицах базы данных SQL. Когда вы создаете объект через Справочники.Номенклатура.СоздатьЭлемент(), вы работаете именно с этими данными.
  2. Реквизиты формы: Это временные переменные, которые живут только «внутри» открытого окна. Они создаются для удобства пользователя (например, вспомогательные флажки, расчетные итоги, строковые поля для ввода). Как только форма закрывается, значения этих реквизитов исчезают, если их не сохранить принудительно в другое место.

Рассмотрим пример из сообщения автора. Попытка написать НовСправочник.Наименование2 = "777" ошибочна, так как у объекта в базе данных нет такого поля. Программа справедливо сообщает, что реквизит не найден. Чтобы решить задачу, нам нужно научиться работать с контекстом формы, а не только с объектом.

Способ 1. Использование параметров формы (Рекомендуемый метод)

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

Во внешней обработке или другом объекте подготовим структуру параметров:


&НаКлиенте
Процедура ОткрытьФормуСПараметрами(Команда)
    
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("ЗначениеДляНаименования2", "Тестовая строка");
    
    ОткрытьФорму("Справочник.Справочник1.ФормаЭлемента", ПараметрыФормы);
    
КонецПроцедуры

Теперь в модуле самой формы справочника нам нужно перехватить этот параметр. Рассмотрим, как это сделать в обработчике ПриСозданииНаСервере:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Проверяем, передан ли наш параметр
    Если Параметры.Свойство("ЗначениеДляНаименования2") Тогда
        // Присваиваем значение реквизиту формы напрямую
        Наименование2 = Параметры.ЗначениеДляНаименования2;
    КонецЕсли;
    
КонецПроцедуры

Этот метод хорош тем, что он работает в рамках стандарта 1С и не требует нарушения инкапсуляции данных формы.

Способ 2. Экспортные процедуры в модуле формы

Выясним причину, по которой прямое обращение к Форма.Наименование2 извне часто не срабатывает. Управляемая форма — это сложный объект, и прямое изменение её реквизитов из другого контекста может не привести к обновлению интерфейса или вызвать ошибку доступа. Более надежный вариант — создать в форме специальную экспортную процедуру.

В модуле формы справочника напишем следующий код:


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

Теперь из внешней обработки мы можем вызвать этот метод. Обратите внимание, что сначала нужно получить форму, а потом вызвать процедуру:


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

Важный нюанс: В управляемых формах вы не можете просто так обращаться к элементам через ЭлементыФормы, как это было в 8.2 (обычные формы). Нужно обращаться либо к реквизиту (данным), либо к коллекции Элементы (для изменения видимости или доступности), но не для записи значений в связанные поля.

Способ 3. Работа с данными через ДополнительныеСвойства

Если ваша задача — передать данные из кода создания объекта в процедуру записи, чтобы потом форма их «подхватила», рассмотрите использование коллекции ДополнительныеСвойства. Это особенно полезно, если создание объекта происходит в фоновом задании или в глубоком серверном вызове.

В коде создания объекта:


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

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

Где на самом деле хранить «Реквизиты формы»?

Проанализируем сообщение 5 из обсуждения. Часто под «реквизитом формы» скрываются данные, которые логически принадлежат объекту, но не вынесены в его структуру для экономии места или по требованиям архитектуры. Например, контактная информация или настройки доступа.

Если вам нужно, чтобы Наименование2 сохранялось между сеансами работы, у вас есть три пути:

Типичные ошибки, которых следует избегать

Разберем по шагам, что точно делать нельзя:

  1. Использовать ПолучитьФорму().Элементы... для записи данных. Коллекция Элементы предназначена для управления визуальным состоянием (сделать кнопку невидимой, покрасить поле в красный цвет). Для записи текста или чисел используйте реквизиты.
  2. Пытаться настроить RLS (права доступа) на реквизит формы. Как правильно замечено в обсуждении, права доступа на уровне записей работают только для данных в БД. Если вы хотите скрыть Наименование2 от части пользователей, это придется делать программно в процедуре ПриСозданииНаСервере, управляя свойством Видимость.
  3. Путать контексты &НаКлиенте и &НаСервере. Помните, что обращение к реквизитам формы напрямую (Наименование2 = "...") работает только внутри модуля этой самой формы. При попытке сделать это из модуля объекта или внешней обработки вы получите ошибку.

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

← На главную