Как программно настроить фильтрацию записей регистра сведений в табличном поле на обычных формах?

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

При разработке интерфейсов в среде 1С:Предприятие 8 (особенно при работе с обычными формами) часто возникает задача синхронизации двух списков. Например, когда при выборе определенной позиции в справочнике Номенклатура нам необходимо мгновенно отобразить связанные с ней данные из регистра сведений (например, аналоги товара, цены или штрихкоды) в отдельном табличном поле на той же форме.

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

Постановка задачи и выбор события формы

Рассмотрим ситуацию: на форме списка или в форме элемента справочника у нас есть основной список (например, список номенклатуры) и дополнительное табличное поле, данные которого подтянуты из регистра сведений. Тип значения этого табличного поля — РегистрСведенийСписок.[ИмяРегистра].

Для того чтобы данные во втором списке обновлялись «на лету» при перемещении по основному списку, нам необходимо использовать обработчик события ПриАктивизацииСтроки. Это событие генерируется каждый раз, когда пользователь кликает мышкой по строке или перемещается по списку с помощью клавиатуры.

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

Разбор программного метода установки отбора

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


Процедура СправочникСписокПриАктивизацииСтроки(Элемент)
    
    // Получаем текущую ссылку на номенклатуру
    ТекущаяНоменклатура = Элемент.ТекущаяСтрока;
    
    // Проверяем, что строка действительно выбрана (не пустая)
    Если ТекущаяНоменклатура = Неопределено Тогда
        Возврат;
    КонецЕсли;

    // Обращаемся к коллекции отборов табличного поля регистра
    НашОтбор = ЭлементыФормы.ТабличноеПолеАналоги.Отбор;
    
    // Устанавливаем параметры фильтрации по измерению "Номенклатура"
    НашОтбор["Номенклатура"].Использование = Истина;
    НашОтбор["Номенклатура"].Значение      = ТекущаяНоменклатура;
    
    // Выбираем вид сравнения в зависимости от того, группа это или элемент
    Если ТекущаяНоменклатура.ЭтоГруппа Тогда
        НашОтбор["Номенклатура"].ВидСравнения = ВидСравнения.ВСпискеПоИерархии;
    Иначе
        НашОтбор["Номенклатура"].ВидСравнения = ВидСравнения.Равно;
    КонецЕсли;

КонецПроцедуры

Проанализируем этот код подробнее. Мы используем индексатор ["Номенклатура"] для доступа к конкретному полю отбора. Это позволяет избежать ошибок, если структура регистра изменится, но имя измерения останется прежним. Свойство Использование отвечает за то, будет ли фильтр активен в данный момент. Если установить его в Ложь, список снова отобразит все записи регистра.

Использование метода Установить() для лаконичности

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


// Вместо трех строк присвоения используем одну
ЭлементыФормы.ТабличноеПолеАналоги.Отбор.Номенклатура.Установить(ТекущаяНоменклатура, Истина);

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

Архитектурные нюансы: РегистрСведенийСписок против ТаблицыЗначений

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

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

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

Оптимизация: Индексирование данных

Чтобы отбор работал мгновенно, необходимо убедиться, что в метаданных регистра сведений для измерения, по которому идет фильтрация (в нашем случае Номенклатура), включено индексирование. Рассмотрим два ключевых свойства измерения:

Типичные ошибки при реализации

Проанализируем ситуацию, упомянутую в обсуждении, когда метод Установить «не обнаруживается». Это происходит в следующих случаях:

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

Таким образом, для реализации качественного и быстрого интерфейса в обычных формах 1С 8.3 следует придерживаться использования динамических списков и программного управления их коллекцией Отбор через событие активации строки.

← На главную