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