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