Как правильно заполнить реквизит управляемой формы объектного типа в 1С 8.3?

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

При разработке в управляемом интерфейсе 1С:Предприятия нередко возникает задача загрузить данные объекта из базы в дополнительный реквизит формы, имеющий тип СправочникОбъект.<Имя> или ДокументОбъект.<Имя>. На клиенте и сервере такой реквизит представлен типом ДанныеФормыСтруктура, из-за чего прямое присвоение ссылки или выгруженного объекта вызывает ошибки типизации и выполнения. Разберем типичные ошибки разработчиков и рассмотрим правильные варианты заполнения таких реквизитов.

Анализ типовых ошибок при конвертации данных

Посмотрим на частые ошибки, с которыми сталкиваются при попытке заполнить реквизит формы прикладным объектом:

  1. Ошибка «Недопустимое значение параметра (параметр номер '1' или '2')» при вызове метода ЗначениеВРеквизитФормы:

    Первый параметр метода должен принимать непосредственно прикладной объект (например, СправочникОбъект), а не ссылку на него (СправочникСсылка). Чтобы передать объект из ссылки, необходимо предварительно вызвать метод ПолучитьОбъект(). Второй параметр принимает строго строковое имя реквизита формы верхнего уровня (например, "ФизическоеЛицо"), обращение через точку к реквизитам объекта ("ФизическоеЛицо.Ссылка") недопустимо.

  2. Ошибка «Нельзя изменять поле, содержащее объект данных формы»:

    Данная ошибка возникает, если реквизит формы с типом ДанныеФормыСтруктура передается в качестве аргумента в серверную процедуру с контекстом (&НаСервере), и внутри этой же процедуры вызывается ЗначениеВРеквизитФормы. Платформа блокирует перезапись реквизита, так как он одновременно передан в параметрах вызова. В контекстных процедурах реквизиты формы доступны напрямую и передавать их аргументами не нужно.

Способ 1. Заполнение в контекстной серверной процедуре (&НаСервере)

Разберем классический вариант с использованием контекста формы. Метод ЗначениеВРеквизитФормы доступен только в модуле формы и работает с контекстом текущего экземпляра формы. Мы не передаем реквизит-приемник в параметрах, а обращаемся к нему по имени:


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

&НаКлиенте
Процедура ФизЛицоПриИзменении(Элемент)
    // Передаем только значение для поиска или ссылку
    ЗаполнитьРеквизитНаСервере(ЭтаФорма.ФизЛицо);
    ЭтаФорма.ОбновитьОтображениеДанных();
КонецПроцедуры

В этом примере реквизит ФизическоеЛицо корректно заполняется всеми полями справочника без конфликтов параметров.

Способ 2. Заполнение в безконтекстной процедуре (&НаСервереБезКонтекста)

Проанализируем ситуацию, когда необходимо минимизировать объем передаваемых данных между клиентом и сервером и выполнить процедуру без передачи контекста всей формы. Метод ЗначениеВРеквизитФормы в директиве &НаСервереБезКонтекста недоступен, поэтому применяется глобальный метод ЗначениеВДанныеФормы:


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

&НаКлиенте
Процедура ФизЛицоПриИзменении(Элемент)
    // Передаем ссылку и целевой реквизит формы типа ДанныеФормыСтруктура
    ЗаполнитьРеквизитБезКонтекста(ЭтаФорма.ФизЛицо, ЭтаФорма.ФизическоеЛицо);
    ЭтаФорма.ОбновитьОтображениеДанных();
КонецПроцедуры

Альтернативные решения и оптимизация

Рассмотрим дополнительные подходы, позволяющие избежать лишних преобразований данных:

  1. Замена типа реквизита на ссылочный: если на форме не планируется редактировать табличные части и реквизиты выбранного объекта, а требуется только отображать или хранить выбор пользователя, измените тип реквизита в редакторе формы на СправочникСсылка.<Имя>. Это полностью исключит вызовы ПолучитьОбъект() и сериализацию данных.
  2. Копирование значений через ЗаполнитьЗначенияСвойств: если нужно перенести только отдельные совпадающие поля, можно скопировать свойства напрямую без перезаписи всей структуры: ЗаполнитьЗначенияСвойств(ФизическоеЛицо, СсылкаНаФизЛицо);

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

← На главную