Как обойти элементы подчиненного справочника и настроить отбор при открытии формы в 1С 7.7

Программист 1С v7.7 Управленческий учет Торговля и дистрибуция
← На главную

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

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

Анализ проблемы: почему нельзя обойти форму списка

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

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

Способ 1. Получение выборки элементов с учетом владельца

Выясним, как правильно обойти элементы подчиненного справочника в модуле формы списка при ее открытии. В контексте формы подчиненного справочника доступна функция ИспользоватьВладельца() без параметров, которая возвращает текущего владельца открытого списка.

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


Спр = СоздатьОбъект("Справочник." + Вид());
Спр.ИспользоватьВладельца(ИспользоватьВладельца());
Спр.ВыбратьЭлементы();
Пока Спр.ПолучитьЭлемент() = 1 Цикл
    // Обработка текущего элемента подчиненного справочника
    Сообщить("Найден элемент: " + Спр.ТекущийЭлемент());
КонецЦикла;

Обратите внимание на распространенную избыточную ошибку: попытку выполнить поиск владельца через конструкцию Н.НайтиЭлемент(ИспользоватьВладельца()). Метод ИспользоватьВладельца() уже возвращает готовую ссылку на элемент-владелец, поэтому дополнительный поиск через НайтиЭлемент не требуется.

Опасности записи реквизитов «на лету» при открытии

Иногда для фильтрации прибегают к подходу, когда в цикле обхода реквизиту элемента присваивается признак видимости (например, Показать = 1), вызывается метод Записать(), а затем накладывается штатный УстановитьОтбор("Показать", 1). Рассмотрим подробнее, почему такой подход категорически не рекомендуется использовать в реальных рабочих базах:

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

Способ 2. Безопасная фильтрация через ИспользоватьСписокЭлементов()

Штатным и безопасным способом динамического ограничения видимости элементов в форме списка 1С 7.7 является использование метода ИспользоватьСписокЭлементов(). Он не требует изменения реквизитов и записи объектов в базу данных.

Разберем по шагам реализацию этого метода в процедуре ПриОткрытии() формы списка подчиненного справочника:

  1. Проверяем набор прав или роль текущего пользователя.
  2. Создаем список значений, в который будем помещать только те элементы, которые разрешено видеть пользователю.
  3. Организуем выборку подчиненного справочника по текущему владельцу.
  4. В цикле выборки проверяем условия доступности и добавляем разрешенные элементы в список значений методом ДобавитьЗначение().
  5. Передаем сформированный список в метод формы ИспользоватьСписокЭлементов().

Посмотрим на практический пример кода:


Процедура ПриОткрытии()
    Если НазваниеНабораПрав() = "Филиал" Тогда
        СпРазрешенных = СоздатьОбъект("СписокЗначений");
        
        Цены = СоздатьОбъект("Справочник.Цены");
        Цены.ИспользоватьВладельца(ИспользоватьВладельца());
        Цены.ВыбратьЭлементы();
        
        Пока Цены.ПолучитьЭлемент() = 1 Цикл
            // Проверяем доступность типа цены для филиала
            Если Цены.ТипЦен.ДоступноУве = 1 Тогда
                СпРазрешенных.ДобавитьЗначение(Цены.ТекущийЭлемент());
            КонецЕсли;
        КонецЦикла;
        
        // Устанавливаем фильтр списка
        ИспользоватьСписокЭлементов(СпРазрешенных);
        
        // Скрываем ненужные элементы интерфейса
        Форма.Процент.Видимость(0);
    КонецЕсли;
КонецПроцедуры

Важное замечание: метод ИспользоватьСписокЭлементов() отлично работает при небольшом и среднем количестве строк (в пределах десятков или сотен записей подчиненного справочника). Если список содержит тысячи элементов, навигация по форме списка может замедлиться.

Способ 3. Отображение данных через Таблицу Значений

Если требуется полностью изолировать интерфейс просмотра и редактирования от стандартных механизмов справочника, наиболее надежным решением является отказ от стандартной формы списка в пользу элемента формы ТаблицаЗначений.

Проанализируем преимущества такого подхода:

  1. Полный контроль над строками и колонками: на форму номенклатуры или отдельной обработки выводится объект «ТаблицаЗначений», в который программно выгружаются только те типы цен, которые разрешены текущему пользователю.
  2. Исключение случайной утечки данных: при сбое штатного отбора пользователь стандартной формы списка теоретически может увидеть скрытые записи. В случае с таблицей значений конфиденциальные данные вовсе не считываются в клиентскую таблицу.
  3. Отсутствие блокировок: чтение данных происходит без транзакций изменения, что гарантирует стабильность и высокую производительность базы данных при многопользовательской работе.
← На главную