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