Как правильно отфильтровать документы по текущему пользователю в форме списка обычного приложения

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

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

Анализ типичных ошибок при работе со списком документов

Рассмотрим основные ошибки, которые возникают при попытке ограничить отображение строк в обычных формах:

  1. Использование свойства ТекущиеДанные в событии ПриОткрытии. Свойство ЭлементыФормы.ДокументСписок.ТекущиеДанные возвращает данные строки, на которой установлен курсор (фокус). На этапе выполнения процедуры ПриОткрытии форма еще не отрисована пользователю, активная строка отсутствует, поэтому обращение к текущим данным всегда возвращает Неопределено. Попытка прочитать реквизит вида ТекущиеДанные.Исполнитель вызовет исключение «Значение не является значением объектного типа».
  2. Попытка скрыть строки через свойство Видимость. Свойство ЭлементыФормы.ДокументСписок.Видимость управляет видимостью самого элемента управления (табличного поля со списком) на форме, а не отдельных его строк. Присвоение значения Ложь просто скроет всю таблицу со всеми документами с экрана.
  3. Сравнение несовместимых типов данных. Параметр сеанса ТекущийПользователь обычно имеет тип ссылки на СправочникСсылка.Пользователи. Если реквизит Исполнитель хранит тип СправочникСсылка.Сотрудники, прямое сравнение на равенство всегда вернет результат Ложь. Необходимо предварительно получить связанного сотрудника через регистр сведений или запрос.

Правильный способ установки простого отбора в списке

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

Проанализируем базовый пример установки отбора в процедуре ПриОткрытии, когда тип реквизита совпадает с типом текущего пользователя:


Процедура ПриОткрытии()
    
    // Быстрая установка отбора с автоматической активацией использования
    ДокументСписок.Отбор.Исполнитель.Установить(ПараметрыСеанса.ТекущийПользователь);
    
КонецПроцедуры

Метод Установить() принимает значение отбора, автоматически включает признак Использование = Истина и задает вид сравнения ВидСравнения.Равно.

Если требуется запретить пользователю вручную отключать данный фильтр через панель настройки списка, отключим доступность элемента отбора:


Процедура ПриОткрытии()
    
    ДокументСписок.Отбор.Исполнитель.Установить(ПараметрыСеанса.ТекущийПользователь);
    ДокументСписок.Отбор.Исполнитель.Доступность = Ложь;
    
КонецПроцедуры

Установка отбора при несовпадении типов и связи через регистры

Рассмотрим более сложную и частую ситуацию, когда в документе исполнителем является сотрудник (справочник Сотрудники или ФизическиеЛица), а текущий пользователь системы привязан к нему через регистр сведений (например, РегистрСведений.ПЛ_ПользователиИБ).

В этом случае сначала получаем связанного сотрудника запросом, а затем передаем полученное значение в отбор:


Процедура ПриОткрытии()
    
    // Проверяем наличие полных прав, чтобы администраторы видели весь список
    Если Не РольДоступна("ПолныеПрава") Тогда
        
        Запрос = Новый Запрос;
        Запрос.Текст = 
            "ВЫБРАТЬ
            |   ПЛ_ПользователиИБ.Сотрудник КАК Сотрудник
            |ИЗ
            |   РегистрСведений.ПЛ_ПользователиИБ КАК ПЛ_ПользователиИБ
            |ГДЕ
            |   ПЛ_ПользователиИБ.Пользователь = &Пользователь";
        
        Запрос.УстановитьПараметр("Пользователь", ПараметрыСеанса.ТекущийПользователь);
        Выборка = Запрос.Выполнить().Выбрать();
        
        Если Выборка.Следующий() Тогда
            // Устанавливаем отбор по найденному сотруднику
            ДокументСписок.Отбор.Исполнитель.ВидСравнения = ВидСравнения.Равно;
            ДокументСписок.Отбор.Исполнитель.Значение = Выборка.Сотрудник;
            ДокументСписок.Отбор.Исполнитель.Использование = Истина;
        Иначе
            // Если сотрудник не сопоставлен, отключаем отбор или выводим пустой список
            ДокументСписок.Отбор.Исполнитель.Использование = Ложь;
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

Работа с составным типом данных и несколькими значениями

Если реквизит Исполнитель имеет составной тип (может содержать как пользователя, так и сотрудника) либо за одним пользователем закреплено несколько сотрудников, фильтрацию по единичному значению использовать нельзя. В таком случае применяют вид сравнения ВидСравнения.ВСписке.

Разберем по шагам заполнение списка значений для отбора:


Процедура ПриОткрытии()
    
    Если Не РольДоступна("ПолныеПрава") Тогда
        
        СписокИсполнителей = Новый СписокЗначений;
        // Добавляем самого пользователя
        СписокИсполнителей.Добавить(ПараметрыСеанса.ТекущийПользователь);
        
        // Получаем всех связанных сотрудников
        Запрос = Новый Запрос;
        Запрос.Текст = 
            "ВЫБРАТЬ
            |   ПЛ_ПользователиИБ.Сотрудник КАК Сотрудник
            |ИЗ
            |   РегистрСведений.ПЛ_ПользователиИБ КАК ПЛ_ПользователиИБ
            |ГДЕ
            |   ПЛ_ПользователиИБ.Пользователь = &Пользователь";
        
        Запрос.УстановитьПараметр("Пользователь", ПараметрыСеанса.ТекущийПользователь);
        Выборка = Запрос.Выполнить().Выбрать();
        
        Пока Выборка.Следующий() Цикл
            СписокИсполнителей.Добавить(Выборка.Сотрудник);
        КонецЦикла;
        
        // Накладываем отбор по списку
        ДокументСписок.Отбор.Исполнитель.ВидСравнения = ВидСравнения.ВСписке;
        ДокументСписок.Отбор.Исполнитель.Значение = СписокИсполнителей;
        ДокументСписок.Отбор.Исполнитель.Использование = Истина;
        
    КонецЕсли;
    
КонецПроцедуры

Важные ограничения и особенности отборов в обычном приложении

При реализации логики отображения документов следует помнить о технических ограничениях платформы 1С:

  1. Реквизиты табличных частей. Стандартный объект ДокументСписок позволяет накладывать отбор только на реквизиты шапки и стандартные реквизиты документа (Дата, Номер, Проведен, ПометкаУдаления). Наложить отбор на реквизит табличной части штатными средствами списка невозможно. Для таких задач используют критерии отбора либо строят список на основе запроса в ТабличноеПоле.
  2. Сохранение настроек пользователя. Если в свойствах формы включено автоматическое сохранение настроек, сохраненные пользователем отборы могут переопределять программные параметры. Чтобы этого избежать, отключайте свойство Доступность у элемента отбора или проверяйте настройки сохранения формы.
  3. Безопасность данных. Программный отбор в форме списка лишь визуально скрывает строки от пользователя. Если требуется гарантированно ограничить доступ к чужим документам на уровне базы данных (в отчетах, запросах и при открытии по прямой ссылке), необходимо настраивать механизм RLS (Ограничение прав на уровне записей) в конфигураторе для роли пользователя.
← На главную