Как исправить ошибку «Метод объекта не обнаружен» при вызове УстановитьНовыйНомер в управляемой форме 1С

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

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

Почему возникает ошибка: разбираем теорию

Для начала проанализируем причину возникновения ошибки. В управляемой форме реквизит Объект (основной реквизит формы) имеет тип ДанныеФормыСтруктура. Это не полноценный ДокументОбъект, а его «легкая» копия, предназначенная для передачи данных между сервером и клиентом. Платформа 1С разделяет данные в интерфейсе и данные для работы с базой данных.

Метод УстановитьНовыйНомер() принадлежит классу ДокументОбъект. У структуры данных формы (типа ДанныеФормыСтруктура) просто нет такого метода, поэтому система и сообщает о его отсутствии. Чтобы вызвать этот метод, нам необходимо получить полноценный объект на стороне сервера.

Способ 1. Конвертация данных формы в объект (РеквизитФормыВЗначение)

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


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

Разберем подробнее, что здесь происходит. Мы используем метод РеквизитФормыВЗначение(), чтобы временно создать в памяти сервера объект документа. После вызова УстановитьНовыйНомер(), мы не записываем весь объект целиком (это может быть избыточно), а просто переносим сформированный номер обратно в Объект.Номер. Это позволяет пользователю увидеть новый номер в форме до момента записи.

Способ 2. Установка номера с префиксом

Часто требуется не просто установить номер, а задать специфический префикс в зависимости от условий (например, от вида договора или организации). Метод УстановитьНовыйНомер() принимает строковый параметр Префикс. Проанализируем ситуацию, когда префикс зависит от реквизита документа:


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

Важный нюанс: Если вы используете конфигурации на базе БСП (Библиотеки Стандартных Подсистем), например УТ 11, ERP или БП 3.0, ручная установка префикса может конфликтовать со встроенными механизмами префиксации. В этом случае рекомендуется использовать возможности модуля ПрефиксацияОбъектов.

Способ 3. Использование событий модуля объекта (Правильный подход)

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

Рассмотрим событие ПриУстановкеНовогоНомера в модуле объекта документа. Это событие вызывается платформой автоматически при создании нового номера.


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

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


&НаКлиенте
Процедура ВидДоговораПриИзменении(Элемент)
    // Очищаем номер, чтобы при записи он сформировался заново
    Объект.Номер = ""; 
КонецПроцедуры

Анализ рисков и производительности

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

Рекомендации по оптимизации:

  1. Избегайте вызова установки номера при каждом изменении реквизитов (событие ПриИзменении). Лучше делать это один раз перед записью или по явной команде пользователя.
  2. Используйте Модифицированность = Ложь, если вы программно перечитали объект, но не хотите, чтобы система считала форму измененной и предлагала сохранение при закрытии (если это уместно в вашем сценарии).
  3. Помните о «дырках» в нумерации. Каждый вызов УстановитьНовыйНомер резервирует число в базе данных. Если пользователь 10 раз изменит параметр, влияющий на префикс, и 10 раз вызовется метод, в счетчике системы могут возникнуть пропуски.

Особенности периодичности нумерации

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

Посмотрим на пример комплексного решения в модуле формы для случая смены даты:


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

В данном примере мы используем ЗначениеВРеквизитФормы, чтобы обновить все данные формы из объекта. Это полезно, если в процедуре ПередЗаписью или ПриУстановкеНовогоНомера модуля объекта происходит еще какая-то логика, которую нужно отобразить пользователю немедленно.

Подводя итог, можно сказать: ошибка «Метод объекта не обнаружен» — это сигнал о том, что вы пытаетесь работать с интерфейсными данными как с объектом базы данных. Используйте серверный контекст и методы конвертации или, что еще лучше, переносите логику нумерации в модуль объекта, используя стандартные события платформы.

← На главную