Как в 1С найти строки в таблице значений по условию неравенства?

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

При работе с объектом ТаблицаЗначений разработчики часто сталкиваются с необходимостью отфильтровать строки по нескольким условиям, одно из которых — не строгое равенство (например, значение числового поля не равно нулю или больше нуля).

Штатный метод НайтиСтроки() принимает в качестве параметра структуру отбора, где все поля сравниваются исключительно на строгое равенство. Передать в структуру условие НЕ РАВНО или БОЛЬШЕ невозможно. Разберем основные и наиболее эффективные способы решения этой задачи без лишней нагрузки на СУБД.

Способ 1. Использование ПостроителяОтчета или ПостроителяЗапроса

Объект ПостроительОтчета позволяет быстро профильтровать готовую таблицу значений в оперативной памяти без обращения к серверу баз данных. В его свойствах можно гибко настроить виды сравнения для отбора (ВидСравнения.НеРавно, ВидСравнения.Больше, ВидСравнения.ВСписке и др.).

Важное требование: колонки исходной таблицы значений обязательно должны быть типизированы (содержать ОписаниеТипов), иначе платформа выдаст ошибку при инициализации источника данных.

Рассмотрим пример программной фильтрации через ПостроительОтчета:


// Создаем и типизируем таблицу
МассивТиповНоменклатура = Новый Массив;
МассивТиповНоменклатура.Добавить(Тип("СправочникСсылка.Номенклатура"));
ОписаниеТипаНоменклатура = Новый ОписаниеТипов(МассивТиповНоменклатура);

МассивТиповЧисло = Новый Массив;
МассивТиповЧисло.Добавить(Тип("Число"));
КвалификаторыЧисла = Новый КвалификаторыЧисла(10, 0);
ОписаниеТипаЧисло = Новый ОписаниеТипов(МассивТиповЧисло, , , КвалификаторыЧисла);

ТаблицаИсточника = Новый ТаблицаЗначений;
ТаблицаИсточника.Колонки.Добавить("Номенклатура", ОписаниеТипаНоменклатура);
ТаблицаИсточника.Колонки.Добавить("Уровень", ОписаниеТипаЧисло);

// Настраиваем построитель для фильтрации
Построитель = Новый ПостроительОтчета;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТаблицаИсточника);

// Добавляем отбор по равенству номенклатуры
ЭлементНоменклатура = Построитель.Отбор.Добавить("Номенклатура");
ЭлементНоменклатура.ВидСравнения = ВидСравнения.Равно;
ЭлементНоменклатура.Значение = ИскомаяНоменклатура;
ЭлементНоменклатура.Использование = Истина;

// Добавляем отбор по уровню (не равен 0 или больше 0)
ЭлементУровень = Построитель.Отбор.Добавить("Уровень");
ЭлементУровень.ВидСравнения = ВидСравнения.Больше;
ЭлементУровень.Значение = 0;
ЭлементУровень.Использование = Истина;

Построитель.Выполнить();
ТаблицаРезультата = Построитель.Результат.Выгрузить();

Аналогичным образом можно применить объект ПостроительЗапроса, передав в него ОписаниеИсточникаДанных(ТаблицаИсточника).

Способ 2. Комбинированный подход: НайтиСтроки() и обход массива

Если таблица содержит большой объем данных, а результат отбора должен возвращать ссылки на исходные строки таблицы (а не новую копию данных), наиболее производительным решением является связка метода НайтиСтроки() с последующей быстрой фильтрацией в цикле.

Разберем алгоритм по шагам:

  1. Добавляем индекс по колонке Номенклатура для ускорения поиска.
  2. С помощью НайтиСтроки() отбираем массив строк по точному совпадению номенклатуры.
  3. Обходим полученный массив и отсеиваем строки с нулевым уровнем.

Посмотрим на пример кода:


// Индексируем колонку для быстрого поиска
ТаблицаИсточника.Индексы.Добавить("Номенклатура");

// Получаем строки по точному равенству
Отбор = Новый Структура("Номенклатура", ИскомаяНоменклатура);
НайденныеСтроки = ТаблицаИсточника.НайтиСтроки(Отбор);

// Фильтруем массив по дополнительному условию
ИтоговыйМассив = Новый Массив;
Для Каждого Стр Из НайденныеСтроки Цикл
    Если Стр.Уровень <> 0 Тогда
        ИтоговыйМассив.Добавить(Стр);
    КонецЕсли;
КонецЦикла;

Преимущество метода: элементы в массиве ИтоговыйМассив остаются типа СтрокаТаблицыЗначений, что позволяет менять их значения с автоматическим обновлением исходной таблицы.

Способ 3. Прямой цикл или удаление с конца

Для небольших таблиц значений создание вспомогательных объектов может оказаться избыточным по накладным расходам памяти. В таких ситуациях проще всего использовать прямой цикл.

Если требуется сформировать новую таблицу:


ТаблицаРезультата = ТаблицаИсточника.СкопироватьКолонки();

Для Каждого Стр Из ТаблицаИсточника Цикл
    Если Стр.Номенклатура = ИскомаяНоменклатура И Стр.Уровень <> 0 Тогда
        ЗаполнитьЗначенияСвойств(ТаблицаРезультата.Добавить(), Стр);
    КонецЕсли;
КонецЦикла;

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


КоличествоСтрок = ТаблицаИсточника.Количество();
Для Счетчик = -КоличествоСтрок + 1 По 0 Цикл
    Индекс = -Счетчик;
    Стр = ТаблицаИсточника[Индекс];
    
    Если Стр.Номенклатура <> ИскомаяНоменклатура Или Стр.Уровень = 0 Тогда
        ТаблицаИсточника.Удалить(Индекс);
    КонецЕсли;
КонецЦикла;

Способ 4. Добавление вычисляемой булевой колонки на этапе формирования

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


ТаблицаИсточника.Колонки.Добавить("ЭтоНенулевойУровень", Новый ОписаниеТипов("Булево"));

// При заполнении строк:
НоваяСтрока = ТаблицаИсточника.Добавить();
НоваяСтрока.Номенклатура = ТекущаяНоменклатура;
НоваяСтрока.Уровень = ТекущийУровень;
НоваяСтрока.ЭтоНенулевойУровень = (ТекущийУровень <> 0);

// Теперь можно использовать штатный метод НайтиСтроки:
Отбор = Новый Структура;
Отбор.Вставить("Номенклатура", ИскомаяНоменклатура);
Отбор.Вставить("ЭтоНенулевойУровень", Истина);

РезультатПоиска = ТаблицаИсточника.НайтиСтроки(Отбор);

Сравнение методов и рекомендации

Проанализируем, какой вариант выбрать в зависимости от условий:

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