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