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