Как реализовать аналог метода ЗначениеВРеквизитФормы в обычных формах 1С?

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

При переходе от разработки на управляемых формах (УФ) к работе с обычными формами (ОФ) многие программисты сталкиваются с вопросом: как программно поместить объект (например, СправочникОбъект или ДокументОбъект) в реквизит формы, если в ОФ отсутствует привычный метод ЗначениеВРеквизитФормы? В данной статье мы подробно разберем, как устроена работа с данными в обычных формах, и выясним, почему в них всё гораздо проще, чем кажется на первый взгляд.

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

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

В обычных формах (ОФ) архитектура принципиально иная. Здесь нет «прослойки» в виде данных формы. Когда вы работаете с реквизитом, имеющим тип СправочникОбъект, вы работаете напрямую с экземпляром этого объекта в оперативной памяти. Это «живой» объект, у которого доступны все свойства и методы без каких-либо дополнительных преобразований.

Основное решение: прямое присваивание

Рассмотрим конкретную ситуацию. У нас есть внешняя обработка на обычных формах. В конфигураторе для основного реквизита (обычно это ОбработкаОбъект) мы вручную изменили тип с ВнешняяОбработкаОбъект.Имя на СправочникОбъект.Валюты. Теперь мы хотим, чтобы при определенных действиях в этот реквизит попадали данные из конкретной ссылки на валюту.

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


// Предположим, у нас есть ссылка на справочник
СсылкаНаВалюту = Справочники.Валюты.НайтиПоКоду("810");

// Чтобы поместить данные в реквизит формы "ОбработкаОбъект", 
// просто получаем объект из ссылки и присваиваем его напрямую
ОбработкаОбъект = СсылкаНаВалюту.ПолучитьОбъект();

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

Обновление отображения данных на форме

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

Посмотрим на пример дополненного кода:


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

Нюансы работы с типами реквизитов

Выясним важный момент: можно ли менять тип реквизита «на лету»? В обычных формах состав реквизитов и их типы определяются в конфигураторе. Если вы хотите, чтобы один и тот же реквизит мог принимать объекты разных типов (например, то СправочникОбъект.Валюты, то СправочникОбъект.Контрагенты), вам следует придерживаться следующих правил:

  1. Тип реквизита "Произвольный": В конфигураторе укажите тип реквизита как Произвольный. Это позволит присваивать ему любой объект.
  2. Связь с элементами управления: Учтите, что если вы создали на форме поля ввода (например, Наименование, Код), они должны быть связаны с данными через путь к данным, например, ОбработкаОбъект.Наименование. Если тип объекта изменится на тот, где нет реквизита Наименование, форма может выдать ошибку или поле станет недоступным.
  3. Статичная типизация: Если форма предназначена только для одного вида объектов (как в примере автора вопроса — Валюты), лучше жестко задать тип СправочникОбъект.Валюты. Это обеспечит корректную работу автоподстановки и синтаксического контроля.

Альтернативный метод: копирование данных без замены объекта

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

Проанализируем ситуацию, когда мы хотим обновить текущие данные, не меняя сам «контейнер» объекта:


// 1. Создаем временный объект из ссылки
Источник = СсылкаНаВалюту.ПолучитьОбъект();

// 2. Копируем значения свойств из источника в наш реквизит формы
// Метод ЗаполнитьЗначенияСвойств копирует только совпадающие по именам реквизиты
ЗаполнитьЗначенияСвойств(ОбработкаОбъект, Источник);

// 3. Если есть табличные части, их нужно перенести отдельно
// ОбработкаОбъект.ТабличнаяЧасть1.Загрузить(Источник.ТабличнаяЧасть1.Выгрузить());

ЭтаФорма.Обновить();

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

Итоги

Подведем итог нашему исследованию. В обычных формах 1С 8.3 функционал ЗначениеВРеквизитФормы не требуется, так как работа с объектами происходит напрямую. Для решения задачи автора достаточно:

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

← На главную