Почему метод ПолучитьФорму() не возвращает свойство Объект и как правильно изменить данные справочника

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

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

Причины, по которым форма не возвращает свойство Объект

Рассмотрим основные технические причины, из-за которых обращение к свойству Объект у полученной формы вызывает исключение или ведет себя неожиданно:

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

Архитектурные ограничения: почему нельзя использовать ПолучитьФорму() в цикле

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


Для Каждого ТабЧСтрока ИЗ Объект.СотрудникДолжность Цикл
    СотрОбъект = ТабЧСтрока.Сотрудник;
    НужнаяФорма = Новый Структура("Ключ", СотрОбъект);
    ДанныеФормыСотрудника = ПолучитьФорму("Справочник.Сотрудники.ФормаОбъекта", НужнаяФорма);
КонецЦикла;

Такой подход является грубейшим нарушением стандартов разработки платформы 1С по следующим причинам:

  1. Тяжелый клиент-серверный трафик. Каждый вызов метода ПолучитьФорму() порождает контекстный вызов сервера, где происходит полное построение структуры формы, инициализация элементов управления и отработка серверных событий. Если в табличной части десятки или сотни строк, клиентский сеанс зависнет.
  2. Нецелевое использование интерфейсных механизмов. Управляемая форма и связанные с ней структуры данных формы предназначены исключительно для интерактивного отображения информации пользователю на экране. Использовать визуальный интерфейс для пакетной фоновой записи данных категорически недопустимо.
  3. Устаревший метод. Метод ПолучитьФорму() в управляемом интерфейсе признан устаревшим. Для интерактивного взаимодействия штатно применяется процедура ОткрытьФорму().

Решение 1. Пакетное обновление данных на сервере через ПолучитьОбъект()

Выясним правильный порядок работы с существующими элементами информационной базы. Любая модификация данных должна выполняться на стороне сервера в процедуре без обращения к экранным формам.

Перенесем обработку табличной части в серверный контекст, получим объектную сущность каждого элемента справочника с помощью метода ПолучитьОбъект(), изменим требуемые реквизиты и вызовем метод Записать():


&НаСервере
Процедура ОбновитьДанныеСотрудниковНаСервере(ТабличнаяЧасть)
    
    Для Каждого СтрокаТЧ Из ТабличнаяЧасть Цикл
        
        Если Не ЗначениеЗаполнено(СтрокаТЧ.Сотрудник) Тогда
            Продолжить;
        КонецЕсли;
        
        // Получаем объект справочника по ссылке для изменения
        ОбъектСотрудник = СтрокаТЧ.Сотрудник.ПолучитьОбъект();
        
        Если ОбъектСотрудник <> Неопределено Тогда
            // Заполняем необходимые реквизиты
            ОбъектСотрудник.Реквизит1 = СтрокаТЧ.НовоеЗначение;
            
            // Фиксируем изменения в базе данных
            ОбъектСотрудник.Записать();
        КонецЕсли;
        
    КонецЦикла;
    
КонецПроцедуры

Посмотрим на преимущества этого решения: операция выполняется за один серверный вызов, не создает интерфейсной нагрузки, не расходует память клиента и полностью гарантирует целостность записи транзакции.

Решение 2. Интерактивное открытие формы с предзаполнением

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

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

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

Важно помнить: разделение ответственности между клиентом и сервером — фундаментальный принцип управляемого приложения. Формы служат для ввода данных человеком, а запись и модификация сущностей базы данных должны осуществляться через прикладные объекты СправочникОбъект или ДокументОбъект непосредственно на сервере.

← На главную