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