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

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

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

Анализ проблемы: почему переменная «очищается»?

Разберем типичную ситуацию, описанную в обращении. Разработчик передает ссылку на бизнес-процесс в параметры формы, сохраняет её в переменную модуля в процедуре ПриСозданииНаСервере, а затем пытается использовать эту переменную в другой серверной процедуре. Однако при выполнении команды система выдает ошибку.

Проанализируем причину. В управляемом приложении между вызовами «Клиент — Сервер — Клиент» состояние формы сохраняется только для тех данных, которые добавлены в список Реквизитов формы (вкладка «Реквизиты» в редакторе формы конфигуратора). Обычные переменные, объявленные в разделе Перем модуля формы, инициализируются заново (сбрасываются в Неопределено) при каждом новом переходе с клиента на сервер.

Таким образом, когда мы вызываем процедуру ИзменитьБизнесПроцесс, переменная БизнесПроцесс уже не содержит ссылку, полученную ранее. Метод ПолучитьОбъект() вызывается у пустого значения, что и приводит к аварийному завершению программы.

Решение №1: Использование реквизитов формы

Самый простой и правильный способ сохранить данные между вызовами процедур — использование реквизитов формы. Давайте посмотрим на исправленный код, который будет работать стабильно.

Для начала создадим в форме реквизит (например, с именем СсылкаНаПроцесс) и типом БизнесПроцессСсылка.ИмяВашегоПроцесса.


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // Сохраняем ссылку из параметров в реквизит формы, 
    // который «выживет» после возврата на клиент
    Объект.СсылкаНаПроцесс = Параметры.БП; 
КонецПроцедуры

&НаКлиенте
Процедура ЗаписатьИзменения(Команда)
    ИзменитьБизнесПроцессНаСервере();
КонецПроцедуры

&НаСервере
Процедура ИзменитьБизнесПроцессНаСервере()
    // Теперь мы берем данные из реквизита формы
    Если Не Объект.СсылкаНаПроцесс.Пустая() Тогда
        БП_Объект = Объект.СсылкаНаПроцесс.ПолучитьОбъект();
        БП_Объект.Контрагент = Контрагент; // Берем данные из другого реквизита формы
        БП_Объект.Записать();
    КонецЕсли;
КонецПроцедуры

Решение №2: Использование методов преобразования (для основных форм)

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

Выясним, как работают методы преобразования данных:

  1. РеквизитФормыВЗначение("Объект") — преобразует данные, отображаемые на форме, в полноценный прикладной объект, у которого есть методы Записать(), Заполнить() и другие.
  2. ЗначениеВРеквизитФормы(Объект, "Объект") — выполняет обратное действие, обновляя данные на экране пользователя после программных изменений.

Пример использования этих методов в контекстной серверной процедуре:


&НаСервере
Процедура ИзменитьТекущийОбъект()
    // Преобразуем данные формы в объект бизнес-процесса
    БП_Объект = РеквизитФормыВЗначение("Объект");
    
    // Выполняем необходимые действия
    БП_Объект.Контрагент = ПоискКонтрагента();
    
    // Если нужно обновить данные в интерфейсе формы:
    ЗначениеВРеквизитФормы(БП_Объект, "Объект");
    
    // Если нужно просто записать в базу без изменения текущей экранной формы:
    // БП_Объект.Записать();
КонецПроцедуры

Оптимизация: Контекстные и бесконтекстные вызовы

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

Если для изменения данных нам нужна только ссылка, лучше использовать &НаСервереБезКонтекста. В этом случае мы передаем ссылку как параметр, что значительно ускоряет выполнение:


&НаКлиенте
Процедура КомандаВыполнить(Команда)
    // Передаем ссылку напрямую из реквизита формы в бесконтекстный метод
    ИзменитьБизнесПроцессБезКонтекста(Объект.СсылкаНаПроцесс);
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ИзменитьБизнесПроцессБезКонтекста(СсылкаНаБП)
    // Проверка на пустую ссылку — залог стабильной работы
    Если СсылкаНаБП.Пустая() Тогда
        Возврат;
    КонецЕсли;
    
    БП_Объект = СсылкаНаБП.ПолучитьОбъект();
    // Блокируем объект перед изменением для обеспечения целостности данных
    БП_Объект.Заблокировать(); 
    БП_Объект.ДатаЗавершения = ТекущаяДата();
    БП_Объект.Записать();
КонецПроцедуры

Важные нюансы работы с бизнес-процессами

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

Помните:

Резюме и рекомендации

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

  1. Никогда не храните состояние в переменных модуля (через Перем), если планируете обращаться к ним после выполнения текущей процедуры. Используйте Реквизиты формы.
  2. Проверяйте ссылки на пустоту перед вызовом ПолучитьОбъект(). Это предотвратит внезапные падения системы.
  3. Выбирайте правильный контекст. Если данные формы на сервере не нужны — используйте &НаСервереБезКонтекста.
  4. Используйте типизацию параметров. При передаче данных через Параметры.БП убедитесь, что там действительно ссылка нужного типа, используя функцию ТипЗнч() или проверку метаданных.

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

← На главную