Как сохранить и восстановить отбор строк табличной части во внешней обработке 1С?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При разработке внешних обработок в обычном приложении 1С часто возникает задача сохранить текущий фильтр, установленный пользователем в табличной части, и восстановить его при следующем запуске или по нажатию кнопки. Однако попытка прямого присвоения выгруженного отбора обратно табличному полю приводит к ошибке времени выполнения: «Поле объекта недоступно для записи (ОтборСтрок)». Разберем причины возникновения этой ошибки и рассмотрим корректные способы сохранения и применения настроек фильтрации.

Причина ошибки при восстановлении отбора

Проанализируем исходный код, вызывающий исключение. При сохранении отбора разработчик помещает объект отбора в системное хранилище:


ХранилищеОбщихНастроек.Сохранить(КлючОбъекта, "ОтборСтрокВТаблицеТоварыОбработка", ЭлементыФормы.ТоварыПродажиИОстатки.ОтборСтрок);

При обратном чтении из ХранилищеОбщихНастроек и попытке присвоения:


Отбор = ХранилищеОбщихНастроек.Загрузить(КлючОбъекта, "ОтборСтрокВТаблицеТоварыОбработка");
ЭлементыФормы.ТоварыПродажиИОстатки.ОтборСтрок = Отбор; // Ошибка: Поле объекта недоступно для записи (ОтборСтрок)

Выясним причину такого поведения платформы. Свойство ОтборСтрок у табличного поля доступно только для чтения. Оно возвращает существующий системный объект коллекции Отбор, связанный с конкретным элементом формы. Заменить эту коллекцию целиком другим объектом нельзя — платформа позволяет лишь модифицировать свойства входящих в нее элементов отбора.

Решение: поэлементный перенос свойств отбора

Для корректного применения сохраненных настроек необходимо обойти полученную коллекцию в цикле и обновить свойства каждого поля отбора в таблице. Важно переносить не только само значение, но также вид сравнения и признак активности фильтра.

Посмотрим на пример базового восстановления через обход коллекции:


Для Каждого ЭлементОтбора Из Отбор Цикл
    ЭлементыФормы.ТоварыПродажиИОстатки.ОтборСтрок[ЭлементОтбора.Имя].ВидСравнения  = ЭлементОтбора.ВидСравнения;
    ЭлементыФормы.ТоварыПродажиИОстатки.ОтборСтрок[ЭлементОтбора.Имя].Значение      = ЭлементОтбора.Значение;
    ЭлементыФормы.ТоварыПродажиИОстатки.ОтборСтрок[ЭлементОтбора.Имя].Использование = ЭлементОтбора.Использование;
КонецЦикла;

Разберем по шагам, почему необходимо устанавливать все три параметра:

  1. ВидСравнения — определяет условие фильтрации (Равно, НеРавно, ВСписке, Содержит и т.д.). Без явного указания вид сравнения может остаться по умолчанию (Равно), что исказит сложную фильтрацию.
  2. Значение — содержит данные для фильтрации (ссылка на элемент, строка, число, дата или СписокЗначений).
  3. Использование — флаг включения отбора (состояние флажка в окне настройки). Если его не переносить, при установке значения платформа может автоматически активировать фильтр даже по тем колонкам, которые пользователь не планировал отбирать.

Оптимальный и безопасный алгоритм восстановления

При практической эксплуатации базового варианта можно столкнуться с ситуациями, когда состав колонок табличной части изменился, либо в таблице остались включенными старые отборы, отсутствующие в загружаемом наборе. Доработаем алгоритм для обеспечения максимальной надежности.

Рассмотрим безопасный код загрузки отбора с предварительным сбросом текущих фильтров и поиском элементов:


Отбор = ХранилищеОбщихНастроек.Загрузить(КлючОбъекта, "ОтборСтрокВТаблицеТоварыОбработка");

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

Важные нюансы при работе с внешними обработками

Обратим внимание на особенности, которые критичны при сохранении настроек внешних обработок:

  1. Формирование ключа объекта: вызов Строка(ЭтотОбъект) для внешних обработок часто возвращает одинаковую системную строку (например, "Внешняя обработка"). В результате настройки разных внешних обработок будут перезаписывать друг друга в хранилище. Рекомендуется использовать фиксированное уникальное имя, например: ЭтотОбъект.Метаданные().Имя либо уникальный строковый идентификатор.
  2. Метод Сбросить(): вызов ОтборСтрок.Сбросить() перед загрузкой обязателен, так как он снимает активность с ранее включенных пользователем фильтров, которых нет в загружаемой настройке.
  3. Штатное сохранение настроек: в обычных формах также можно воспользоваться стандартным механизмом платформы: установить свойство формы СохранятьЗначения и настроить автоматическое сохранение реквизитов и элементов управления без ручного написания кода для работы с ХранилищеОбщихНастроек.
← На главную