При разработке в среде 1С:Предприятие часто возникает задача программного изменения реквизитов элементов справочника или документов на основании строк табличной части. Начинающие разработчики иногда пытаются получить форму объекта на клиенте с помощью метода ПолучитьФорму(), наивно полагая, что через свойство формы Объект можно пакетно изменить значения реквизитов и сохранить их. Однако такой подход приводит к ошибкам вроде «Поле объекта не обнаружено (Объект)», а также создает критические проблемы с быстродействием. Разберем, почему возникает эта ошибка и как архитектурно правильно решать задачу изменения данных.
Рассмотрим основные технические причины, из-за которых обращение к свойству Объект у полученной формы вызывает исключение или ведет себя неожиданно:
Сотрудник, ТекущийОбъект или любое другое имя), либо у формы вовсе может отсутствовать основной реквизит, если это произвольная форма. При попытке обращения к свойству Форма.Объект платформа выдает ошибку, если реквизит с таким именем отсутствует в структуре данных формы.ПриСозданииНаСервере установлен параметр Отказ = Истина (из-за нехватки прав доступа, ограничений на уровне записей RLS или отсутствия обязательных параметров), форма не создается. В этом случае метод ПолучитьФорму() возвращает Неопределено, а обращение к любому его свойству вызывает аварийное завершение работы программы.Объект. В обычном приложении реквизиты объекта доступны через свойство СправочникОбъект.Проанализируем фрагмент клиентского кода, где в цикле обхода табличной части вызывается получение формы:
Для Каждого ТабЧСтрока ИЗ Объект.СотрудникДолжность Цикл
СотрОбъект = ТабЧСтрока.Сотрудник;
НужнаяФорма = Новый Структура("Ключ", СотрОбъект);
ДанныеФормыСотрудника = ПолучитьФорму("Справочник.Сотрудники.ФормаОбъекта", НужнаяФорма);
КонецЦикла;
Такой подход является грубейшим нарушением стандартов разработки платформы 1С по следующим причинам:
ПолучитьФорму() порождает контекстный вызов сервера, где происходит полное построение структуры формы, инициализация элементов управления и отработка серверных событий. Если в табличной части десятки или сотни строк, клиентский сеанс зависнет.ПолучитьФорму() в управляемом интерфейсе признан устаревшим. Для интерактивного взаимодействия штатно применяется процедура ОткрытьФорму().Выясним правильный порядок работы с существующими элементами информационной базы. Любая модификация данных должна выполняться на стороне сервера в процедуре без обращения к экранным формам.
Перенесем обработку табличной части в серверный контекст, получим объектную сущность каждого элемента справочника с помощью метода ПолучитьОбъект(), изменим требуемые реквизиты и вызовем метод Записать():
&НаСервере
Процедура ОбновитьДанныеСотрудниковНаСервере(ТабличнаяЧасть)
Для Каждого СтрокаТЧ Из ТабличнаяЧасть Цикл
Если Не ЗначениеЗаполнено(СтрокаТЧ.Сотрудник) Тогда
Продолжить;
КонецЕсли;
// Получаем объект справочника по ссылке для изменения
ОбъектСотрудник = СтрокаТЧ.Сотрудник.ПолучитьОбъект();
Если ОбъектСотрудник <> Неопределено Тогда
// Заполняем необходимые реквизиты
ОбъектСотрудник.Реквизит1 = СтрокаТЧ.НовоеЗначение;
// Фиксируем изменения в базе данных
ОбъектСотрудник.Записать();
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Посмотрим на преимущества этого решения: операция выполняется за один серверный вызов, не создает интерфейсной нагрузки, не расходует память клиента и полностью гарантирует целостность записи транзакции.
Если цель разработчика заключается в том, чтобы действительно показать пользователю форму элемента справочника с предварительно заполненными реквизитами, использовать получение формы в цикле также не нужно. Разберем по шагам, как интерактивно открыть форму конкретного элемента:
Ключ, а также вспомогательные данные для заполнения.ОткрытьФорму().
&НаКлиенте
Процедура ОткрытьКарточкуСотрудника(СсылкаНаСотрудника)
ПараметрыОткрытия = Новый Структура;
ПараметрыОткрытия.Вставить("Ключ", СсылкаНаСотрудника);
// При необходимости передать значения для автоматического заполнения
ЗначенияЗаполнения = Новый Структура;
ЗначенияЗаполнения.Вставить("Комментарий", "Заполнено программно");
ПараметрыОткрытия.Вставить("ЗначенияЗаполнения", ЗначенияЗаполнения);
ОткрытьФорму("Справочник.Сотрудники.ФормаОбъекта", ПараметрыОткрытия);
КонецПроцедуры
Важно помнить: разделение ответственности между клиентом и сервером — фундаментальный принцип управляемого приложения. Формы служат для ввода данных человеком, а запись и модификация сущностей базы данных должны осуществляться через прикладные объекты СправочникОбъект или ДокументОбъект непосредственно на сервере.