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