В работе с платформами 1С 8.3, особенно при разработке внешних обработок и форм документов, часто возникает необходимость отбора данных в табличных частях. Одним из распространенных сценариев является фильтрация строк табличной части по списку значений определенного реквизита, например, по списку контрагентов. Казалось бы, для этого существует свойство ОтборСтрок у элемента формы Таблица. Однако, как выясняется на практике, стандартный функционал ОтборСтрок имеет определенные ограничения, которые не позволяют напрямую решить эту задачу так просто, как этого хотелось бы. Давайте подробно разберем, почему возникает эта проблема и какие эффективные методы мы можем использовать для ее решения.
Автор исходного сообщения столкнулся с ситуацией, когда отбор по одному контрагенту с помощью ЭтаФорма.Элементы.СписокДокументов.ОтборСтрок = Новый ФиксированнаяСтруктура("Контрагент", Справочники.Контрагенты.НайтиПоКоду("")) работает идеально. Но при попытке передать в ФиксированнуюСтруктуру список значений (например, Новый СписокЗначений или массив), отбор перестает работать.
Причина кроется в том, что свойство ОтборСтрок элемента формы Таблица (который отображает табличную часть или таблицу значений) не является аналогом механизмов отбора динамического списка или системы компоновки данных (СКД). Оно предназначено для относительно простых условий фильтрации, таких как "равно", "меньше", "больше", "содержит" (для строковых значений) и не поддерживает напрямую сравнение типа "ВСписке" (ВидСравнения.ВСписке). Попытка передать список значений в качестве значения для отбора приводит к тому, что система не может корректно интерпретировать условие и отбор не применяется.
Это фундаментальное ограничение, которое необходимо учитывать при разработке. Табличная часть на форме, не являющаяся динамическим списком, не обладает встроенными механизмами для сложной фильтрации, аналогичными СКД. Следовательно, для решения задачи отбора по списку значений нам потребуется применить обходные пути или программные решения.
Мы рассмотрим несколько подходов, каждый из которых имеет свои преимущества и недостатки. Выбор метода будет зависеть от конкретных требований к производительности, сложности логики отбора и готовности изменять структуру табличной части на форме.
Этот метод является одним из наиболее универсальных и распространенных, когда стандартный ОтборСтрок не справляется с задачей. Его суть заключается в том, что мы не пытаемся фильтровать отображение текущей табличной части, а программно формируем новую таблицу данных, содержащую только нужные строки, и затем этой новой таблицей заменяем или заполняем текущую табличную часть на форме.
Один из вариантов реализации такого подхода был предложен участниками форума и выражен в виде функции ОтобратьСтрокиПоКритериям. Давайте разберем ее структуру и принцип работы.
Функция ОтобратьСтрокиПоКритериям(Источник, СтруктураКритериев, СтруктураСложныхКритериев = Неопределено) Экспорт
Перем ВидСравненияСложный;
Если СтруктураСложныхКритериев = Неопределено Тогда
СтруктураСложныхКритериев = Новый Структура;
КонецЕсли;
ПостроительЗапроса = Новый ПостроительЗапроса;
ПостроительЗапроса.ИсточникДанных = Новый ОписаниеИсточникаДанных(Источник);
Для Каждого Критерий Из СтруктураКритериев Цикл
НовыйОтбор = ПостроительЗапроса.Отбор.Добавить(Критерий.Ключ);
СтруктураСложныхКритериев.Свойство(Критерий.Ключ, ВидСравненияСложный);
Если ВидСравненияСложный = Неопределено Тогда
НовыйОтбор.Установить(Критерий.Значение);
Иначе
НовыйОтбор.Использование = Истина;
НовыйОтбор.ВидСравнения = ВидСравненияСложный;
НовыйОтбор.Значение = Критерий.Значение;
КонецЕсли;
КонецЦикла;
Возврат ПостроительЗапроса.Результат;
КонецФункции // ОтобратьСтрокиПоКритериям
Эта функция принимает на вход Источник (обычно это ТаблицаЗначений или другой объект, который может быть обернут в ОписаниеИсточникаДанных), СтруктураКритериев для простых условий и СтруктураСложныхКритериев для указания типа сравнения (например, "ВСписке", "НеРавно" и т.д.).
Проанализируем ее работу по шагам:
ПостроительЗапроса. Этот объект обычно используется для конструирования запросов к базе данных, но его также можно эффективно применять для фильтрации таблиц значений в памяти, используя объект ОписаниеИсточникаДанных.ПостроителяЗапроса мы указываем нашу исходную таблицу значений, которую необходимо отфильтровать: ПостроительЗапроса.ИсточникДанных = Новый ОписаниеИсточникаДанных(Источник);СтруктуруКритериев. Для каждого критерия добавляется новый элемент отбора в ПостроительЗапроса.Отбор.СтруктураСложныхКритериев. Если ВидСравненияСложный указан (например, ВидСравнения.ВСписке), то мы явно устанавливаем его для элемента отбора, иначе используется стандартное сравнение "Равно".ПостроительЗапроса, мы просто получаем результат: Возврат ПостроительЗапроса.Результат;. Метод Результат ПостроителяЗапроса в данном случае вернет новую таблицу значений, содержащую только те строки из исходного Источника, которые соответствуют заданным условиям отбора.Применение на практике:
Предположим, у нас есть табличная часть формы ЭтаФорма.Элементы.СписокДокументов, данные которой хранятся в свойстве ЭтаФорма.СписокДокументов (если это реквизит формы типа ТаблицаЗначений, привязанный к элементу формы).
СписокКонтрагентовДляОтбора = Новый СписокЗначений();
СписокКонтрагентовДляОтбора.Добавить(Справочники.Контрагенты.НайтиПоКоду("000000001"));
СписокКонтрагентовДляОтбора.Добавить(Справочники.Контрагенты.НайтиПоКоду("000000002"));
// ...добавьте других контрагентов
СтруктураКритериев = Новый Структура("Контрагент", СписокКонтрагентовДляОтбора);
СтруктураСложныхКритериев = Новый Структура("Контрагент", ВидСравнения.ВСписке);
ИсходнаяТаблицаДанных = ЭтаФорма.СписокДокументов; // Предполагаем, что реквизит формы типа ТаблицаЗначений
ОтфильтрованныеДанные = ОтобратьСтрокиПоКритериям(ИсходнаяТаблицаДанных, СтруктураКритериев, СтруктураСложныхКритериев);
ЭтаФорма.СписокДокументов.Очистить();
ЭтаФорма.СписокДокументов.Загрузить(ОтфильтрованныеДанные);
Преимущества данного метода:
ПостроителяЗапроса.ПостроителяЗапроса, который хорошо оптимизирован для фильтрации данных.Недостатки:
Этот подход, предложенный на форуме, является компромиссным решением. Он позволяет использовать стандартный механизм ОтборСтрок, обходя его ограничение на работу со списками, но с небольшой модификацией структуры данных формы.
Шаги реализации:
ТаблицаЗначений, который связан с элементом формы Таблица) программно или через конфигуратор добавляется новая колонка булевого типа, например, с именем "ОтборПоСписку". Важно отметить, что эта колонка добавляется в коллекцию колонок реквизита формы и не влияет на структуру базы данных.
// Предположим, что "МояТЧ" это реквизит формы типа ТаблицаЗначений,
// который связан с элементом формы Таблица.
Если Не МояТЧ.Колонки.Найти("ОтборПоСписку") Тогда
МояТЧ.Колонки.Добавить("ОтборПоСписку", Новый ОписаниеТипов("Булево"));
КонецЕсли;
Истина. Для остальных строк устанавливаем Ложь.
СписокКонтрагентовДляОтбора = Новый СписокЗначений();
СписокКонтрагентовДляОтбора.Добавить(Справочники.Контрагенты.НайтиПоКоду("000000001"));
СписокКонтрагентовДляОтбора.Добавить(Справочники.Контрагенты.НайтиПоКоду("000000002"));
// ...добавьте других контрагентов
Для Каждого СтрокаТЧ Из МояТЧ Цикл
Если СписокКонтрагентовДляОтбора.Содержит(СтрокаТЧ.Контрагент) Тогда
СтрокаТЧ.ОтборПоСписку = Истина;
Иначе
СтрокаТЧ.ОтборПоСписку = Ложь;
КонецЕсли;
КонецЦикла;
ОтборСтрок к элементу формы Таблица, используя нашу вспомогательную булеву колонку:
ЭтаФорма.Элементы.СписокДокументов.ОтборСтрок = Новый ФиксированнаяСтруктура("ОтборПоСписку", Истина);
Преимущества данного метода:
ОтборСтрок, который хорошо оптимизирован для отображения на форме.Недостатки:
Этот метод является мощным инструментом, который позволяет визуально "фильтровать" строки табличной части без изменения ее состава или очистки, а также без добавления вспомогательных колонок. Он особенно полезен, когда требуется сложная логика фильтрации, а цель — не изменить данные, а лишь скрыть часть из них от пользователя.
Принцип работы:
УсловногоОформления позволяет задавать правила форматирования для строк или ячеек табличной части на основе определенных условий. Эти условия могут быть такими же гибкими, как и в системе компоновки данных (СКД), включая отбор по списку значений.Условие этого правила мы задаем, что строка должна быть скрыта, если ее контрагент НЕ входит в наш список для отбора. Например, "Контрагент НЕ В СПИСКЕ (СписокКонтрагентовДляОтбора)".Оформление для этого правила мы устанавливаем Видимость = Ложь для всех полей строки табличной части. Это приведет к тому, что строки, не соответствующие условию, станут невидимыми для пользователя.Шаги реализации (программно):
СписокКонтрагентовДляОтбора).
// Очищаем существующее условное оформление для чистоты эксперимента
// или работаем с уже существующим элементом
ЭтаФорма.УсловноеОформление.Элементы.Очистить();
ЭлементУсловногоОформления = ЭтаФорма.УсловноеОформление.Элементы.Добавить();
ЭлементУсловногоОформления.Использование = Истина;
// 1. Указываем элемент формы, к которому применяется оформление (наша таблица)
ЭлементУсловногоОформления.ЭлементыФормы.Добавить(ЭтаФорма.Элементы.СписокДокументов);
// 2. Создаем условие: Контрагент НЕ В СПИСКЕ
// Этот отбор будет скрывать строки, контрагент которых НЕ входит в СписокКонтрагентовДляОтбора
НовыйЭлементОтбораУсловия = ЭлементУсловногоОформления.Условие.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
НовыйЭлементОтбораУсловия.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Контрагент");
НовыйЭлементОтбораУсловия.ВидСравнения = ВидСравненияКомпоновкиДанных.НеВСписке;
НовыйЭлементОтбораУсловия.ПравоеЗначение = СписокКонтрагентовДляОтбора; // Передаем Новый СписокЗначений
НовыйЭлементОтбораУсловия.Использование = Истина;
// 3. Указываем поля, к которым применяется оформление (все поля строки)
// Пустое поле означает, что оформление применяется ко всей строке
ПолеОформления = ЭлементУсловногоОформления.Поля.Элементы.Добавить();
ПолеОформления.Использование = Истина;
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("");
// 4. Устанавливаем свойство оформления: Видимость = Ложь
ЭлементУсловногоОформления.Оформление.УстановитьЗначениеПараметра("Видимость", Ложь);
Преимущества данного метода:
Недостатки:
ОтборСтрок, особенно если условия отбора динамически меняются и требуют программного создания элементов условного оформления.Выбор оптимального метода зависит от конкретных требований вашей задачи и особенностей работы с табличной частью. Мы рассмотрели три эффективных подхода:
ОтобратьСтрокиПоКритериям будет отличным выбором. Этот метод создает новую отфильтрованную таблицу.ОтборСтрок будет хорошим решением. Этот метод изменяет состояние каждой строки и использует встроенный фильтр.Помните, что ОтборСтрок на элементах формы "Таблица" предназначен для простых условий, и для отбора "ВСписке" вам почти всегда потребуется один из описанных выше обходных путей. Надеемся, что этот подробный разбор поможет вам эффективно работать с табличными частями в 1С 8.3!