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