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