Как сократить длинное условие с множеством вариантов ИЛИ в 1С 8.3?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке алгоритмов на платформе 1С:Предприятие часто возникает задача проверить, совпадает ли значение реквизита с одним из элементов заданного списка. Если вариантов много, классическая конструкция с логическими операторами ИЛИ быстро разрастается, ухудшая читаемость и поддержку программного кода:


Если Элемент.Сумма = 100 ИЛИ Элемент.Сумма = 200 ИЛИ Элемент.Сумма = 300 ИЛИ Элемент.Сумма = 400 Тогда
    Сообщить("ОК");
КонецЕсли;

Разберем подробнее, какими более компактными, удобными и производительными способами можно заменить подобные громоздкие цепочки условий, а также выясним, почему условие может не отрабатывать даже при видимом совпадении данных.

Способ 1. Использование массива и метода Найти

Самый распространенный и наглядный подход во встроенном языке 1С — предварительно поместить все допустимые значения в объект Массив и воспользоваться его встроенным методом поиска. Метод Найти() возвращает индекс найденного элемента (начиная с 0) либо значение Неопределено, если совпадение отсутствует.

Рассмотрим по шагам реализацию данного варианта:

  1. Инициализируем коллекцию Массив и наполняем ее нужными значениями.
  2. Вызываем метод Найти(), передавая проверяемое значение.
  3. Сравниваем результат с Неопределено.

МассивСумм = Новый Массив;
МассивСумм.Добавить(100);
МассивСумм.Добавить(200);
МассивСумм.Добавить(300);
МассивСумм.Добавить(400);

Если МассивСумм.Найти(Элемент.Сумма) <> Неопределено Тогда
    Сообщить("ОК");
КонецЕсли;

Если в конфигурации подключена Библиотека Стандартных Подсистем (БСП), можно сделать код еще компактнее, воспользовавшись функциями общего модуля:


// Формирование массива из строки без многократных вызовов Добавить()
МассивСумм = СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок("100,200,300,400", ",");

// Проверка наличия значения функцией БСП
Если ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(Элемент.Сумма, МассивСумм) Тогда
    Сообщить("ОК");
КонецЕсли;

Способ 2. Использование объекта Соответствие для ускорения поиска

Проанализируем производительность: поиск по массиву перебирает элементы последовательно. Если проверяемый список состоит из сотен или тысяч записей и проверка выполняется внутри большого цикла, эффективнее использовать объект Соответствие. Поиск по ключу в объекте Соответствие происходит практически мгновенно благодаря хешированию.


// Инициализация соответствия эталонных значений
ДопустимыеСуммы = Новый Соответствие;
ДопустимыеСуммы.Вставить(100, Истина);
ДопустимыеСуммы.Вставить(200, Истина);
ДопустимыеСуммы.Вставить(300, Истина);
ДопустимыеСуммы.Вставить(400, Истина);

// Проверка вхождения по ключу
Если ДопустимыеСуммы[Элемент.Сумма] <> Неопределено Тогда
    Сообщить("ОК");
КонецЕсли;

Способ 3. Фильтрация данных с помощью языка запросов

Если задача заключается в переборе большой таблицы документов или строк таблицы значений для последующей обработки (например, пакетное копирование или проведение), проверку условий целесообразно вынести из цикла в запрос. Платформа 1С оптимизирует такие выборки на уровне СУБД с помощью конструкции В (&СписокЗначений).

Посмотрим на пример обработки таблицы значений в запросе:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    ТЗ.Документ КАК Документ,
    |    ТЗ.Сумма КАК Сумма
    |ПОМЕСТИТЬ ВтПредварительно
    |ИЗ
    |    &ТаблицаДокументов КАК ТЗ
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |    ВтПредварительно.Документ КАК Документ,
    |    ВтПредварительно.Сумма КАК Сумма
    |ИЗ
    |    ВтПредварительно КАК ВтПредварительно
    |ГДЕ
    |    ВтПредварительно.Сумма В (&МассивСумм)";

Запрос.УстановитьПараметр("ТаблицаДокументов", ТаблицаДокументов);
Запрос.УстановитьПараметр("МассивСумм", МассивСумм);

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    // Обрабатываем уже отфильтрованные данные
КонецЦикла;

Важно: Передача таблицы значений в качестве источника временной таблицы запроса (&ТаблицаДокументов КАК ТЗ) поддерживается только в серверном контексте и требует обязательной типизации всех колонок таблицы.

Способ 4. Встроенные методы Таблицы Значений (Скопировать и НайтиСтроки)

Если таблица значений уже находится в памяти и ее не требуется передавать в запрос, можно применить стандартные методы коллекции без ручного перебора циклом:


// Отбор строк с установленным флагом через структуру отбора
Отбор = Новый Структура("Выгружать", Истина);
СтрокиДляОбработки = ТаблицаДокументов.Скопировать(Отбор);

Почему условие не срабатывает: типичные ошибки типизации

Часто разработчики сталкиваются с ситуацией, когда в отладчике значение выглядит одинаково (например, 100), но метод Найти() возвращает Неопределено или условие равенства не выполняется. Выделим основные причины такого поведения:

  1. Несовпадение базовых типов данных: При поиске в коллекциях платформа 1С строго сопоставляет тип. Если в массиве хранятся значения типа Число, а в проверяемом реквизите находится Строка (или наоборот), сравнение вернет ложь. Для решения проблемы значение необходимо явно привести к числу с помощью функции Число().
  2. Обращение к элементу интерфейса вместо реквизита: В управляемых формах обращение к свойству через коллекцию элементов формы может возвращать объект интерфейса (например, ПолеФормы), а не само прикладное значение. Необходимо обращаться напрямую к реквизиту формы или реквизиту объекта.
  3. Ошибки округления и скрытые знаки: Если число получено в результате расчетных операций, оно может содержать скрытые знаки после запятой. В таких случаях перед сравнением рекомендуется использовать функцию Окр(Значение, 2).

// Пример гарантированного приведения типа перед поиском в массиве
СуммаЧислом = Число(Элемент.Сумма);

Если МассивСумм.Найти(СуммаЧислом) <> Неопределено Тогда
    // Условие гарантированно сработает
КонецЕсли;
← На главную