При разработке на управляемых формах в 1С мы часто сталкиваемся с необходимостью выполнить методы, доступные только прикладному объекту (документу или справочнику), но недоступные в контексте ДанныеФормыСтруктура. Для этого используется механизм конвертации данных формы в полноценный объект, при котором крайне важна правильная оптимизация взаимодействия клиента и сервера в 1С 8.3 для минимизации нагрузки на систему. К слову, именно соблюдение стандартов при разработке позволяет достичь высокого быстродействия даже в очень крупных информационных базах.
Однако этот процесс ресурсоемкий и иногда приводит к ошибкам, которые сложно диагностировать. В этой статье мы подробно разберем ситуацию, когда вызов функции РеквизитФормыВЗначение приводит к падению с ошибкой "Ошибка при вызове метода контекста", а также проанализируем особенности работы с методами РеквизитФормыВЗначение и ЗначениеВРеквизитФормы.
Рассмотрим ситуацию: при работе с формой документа (например, при нажатии кнопки для заполнения счетов учета) происходит аварийное завершение работы кода на сервере.
Ошибка выглядит следующим образом:
Ошибка при вызове метода контекста (РеквизитФормыВЗначение).
В коде это происходит на строке:
ДокументОбъект = РеквизитФормыВЗначение("Объект");
Давайте разберемся, почему это происходит и какие подводные камни скрывает этот код.
Метод РеквизитФормыВЗначение выполняет десериализацию данных из формы и создает в памяти сервера экземпляр объекта (например, ДокументОбъект.ПоступлениеТоваровУслуг). Ошибка в этой строке чаще всего означает одно из двух:
Произвольный, метод вернет ошибку.Давайте посмотрим на код, представленный в обсуждении, и найдем в нем не только возможную причину ошибки, но и серьезные логические недочеты. Подобный разбор задач часто включает в себя методический материал для собеседования, помогающий оценить уровень квалификации разработчика.
&НаСервере
Процедура ЗаполнитьСчетаУчетаВТабЧасти()
// 1. Конвертация данных формы в объект
ДокументОбъект = РеквизитФормыВЗначение("Объект");
// 2. Вызов экспортных методов объекта
ДокументОбъект.ЗаполнитьСчетаУчетаВТабЧасти(Объект.Товары, "Товары", Истина, Объект.ОтражатьВНалоговомУчете);
// ... другие вызовы ...
КонецПроцедуры
В этом фрагменте есть три момента, на которые стоит обратить внимание:
В строке ДокументОбъект = ... используется имя переменной, совпадающее с именем типа данных платформы. Хотя платформа 1С позволяет это делать, это считается дурным тоном. Профессиональные стандарты разработки 1С: правила именования переменных и чистота кода рекомендуют использовать готовые шаблоны для применения стандартов, где имена отражают суть, например: ТекущийДокумент или ПрикладнойОбъект.
Это самая критичная проблема приведенного кода. Мы создаем объект в памяти, модифицируем его, но не возвращаем изменения обратно на форму. Переменная существует только в пределах процедуры, и после ее завершения все заполненные данные исчезнут. Чтобы изменения отобразились, необходимо использовать парный метод ЗначениеВРеквизитФормы.
Так как операция конвертации сложная, ее рекомендуется контролировать, особенно если в журнале регистрации недостаточно данных. Для автоматизации оформления таких конструкций удобно использовать оформитор модулей 1С, который помогает поддерживать структуру кода в чистоте.
Давайте перепишем процедуру так, чтобы она была надежной, сохраняла данные и соответствовала стандартам разработки. Чтобы быстро привести существующий код к каноническому виду, можно применить Code formatter 1C — инструмент для анализа и автоматического редактирования модулей.
&НаСервере
Процедура ЗаполнитьСчетаУчетаВТабЧасти()
// Используем Попытку для диагностики проблем при создании объекта
Попытка
// Правильное имя переменной, не перекрывающее типы платформы
РеквизитОбъект = РеквизитФормыВЗначение("Объект");
Исключение
// Выводим подробное описание ошибки
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Не удалось создать объект документа. Подробности: " + ОписаниеОшибки();
Сообщение.Сообщить();
Возврат;
КонецПопытки;
// Выполняем действия с объектом
РеквизитОбъект.ЗаполнитьСчетаУчетаВТабЧасти(РеквизитОбъект.Товары, "Товары", Истина, РеквизитОбъект.ОтражатьВНалоговомУчете);
РеквизитОбъект.ЗаполнитьСчетаУчетаВТабЧасти(РеквизитОбъект.Услуги, "Услуги", Истина, РеквизитОбъект.ОтражатьВНалоговомУчете);
// ВАЖНО: Возвращаем измененные данные обратно в форму
ЗначениеВРеквизитФормы(РеквизитОбъект, "Объект");
КонецПроцедуры
Если после добавления Попытки вы видите сообщение с текстом ошибки, внимательно прочитайте его.
Для корректной работы с объектной моделью из управляемой формы:
РеквизитФормыВЗначение и ЗначениеВРеквизитФормы.