Как ограничить пользователям сортировку в динамических списках 1С по индексированным и видимым полям?

Программист 1С v8.3 (Управляемые формы)
← На главную

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

Понимание проблемы: сортировка по полям "через точку" и неиндексированным полям

В любом динамическом списке пользователю доступна "Настройка списка", где на вкладке "Сортировка" он может выбрать любое доступное поле для упорядочивания. Эта возможность позволяет сортировать данные даже по полям, которые не отображаются в списке или получены из связанных таблиц ("через точку", например, Документ.Контрагент.Наименование). Проблема заключается в том, что такая сортировка может быть крайне неэффективной, если выбранное поле:

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

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

Важность индексов для производительности сортировки

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

Как проверить и настроить индексы в 1С

Мы должны убедиться, что поля, по которым мы хотим разрешить сортировку, имеют соответствующие индексы.

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

Методы ограничения сортировки

1. Ограничение через свойства элементов формы и пользовательские настройки (на основе Сообщения 5)

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

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

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

2. Программное управление доступностью полей для сортировки через КомпоновщикНастроек

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

Мы можем получить доступ к объекту КомпоновщикНастроек динамического списка, обычно через свойство Список.КомпоновщикНастроек в модуле формы. В событии формы ПриСозданииНаСервере(), до того как список будет выведен пользователю, мы можем программно изменить коллекцию элементов порядка.

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

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


&НаСервере
Процедура ПриСозданииНаСервере(Отказ)
    // Очищаем текущие настройки порядка, если они есть
    Список.КомпоновщикНастроек.Настройки.Порядок.Элементы.Очистить();

    // Создаем элемент порядка для поля "Код"
    ЭлементПорядкаКод = Список.КомпоновщикНастроек.Настройки.Порядок.Элементы.Добавить(Тип("ПолеКомпоновкиДанных"));
    ЭлементПорядкаКод.Поле = Новый ПолеКомпоновкиДанных("Код"); // Указываем поле
    ЭлементПорядкаКод.ВидСортировки = ВидСортировкиКомпоновкиДанных.Возрастание; // Сортировка по возрастанию
    ЭлементПорядкаКод.Использование = Истина; // Включаем использование
    ЭлементПорядкаКод.Доступность = Истина; // Делаем доступным для пользователя в настройках

    // Создаем элемент порядка для поля "Наименование"
    ЭлементПорядкаНаименование = Список.КомпоновщикНастроек.Настройки.Порядок.Элементы.Добавить(Тип("ПолеКомпоновкиДанных"));
    ЭлементПорядкаНаименование.Поле = Новый ПолеКомпоновкиДанных("Наименование");
    ЭлементПорядкаНаименование.ВидСортировки = ВидСортировкиКомпоновкиДанных.Возрастание;
    ЭлементПорядкаНаименование.Использование = Истина;
    ЭлементПорядкаНаименование.Доступность = Истина; // Делаем доступным для пользователя в настройках

    // Дополнительно можно указать, какие поля доступны для выбора пользователю в настройках.
    // Если мы хотим ограничить пользователя только этими двумя полями,
    // мы можем управлять коллекцией Список.КомпоновщикНастроек.ДоступныеПоляПорядка.
    // Однако более надежным и современным методом является свойство ОграничениеИспользованияВПорядке.
КонецПроцеду

Этот подход дает нам точный контроль, но требует внимательной работы с объектом КомпоновщикНастроек и понимания его структуры.

3. Использование свойства ОграничениеИспользованияВПорядке (Наиболее эффективный подход)

С версии платформы 8.3.10 разработчики 1С представили очень удобное и мощное свойство ОграничениеИспользованияВПорядке для полей компоновки данных. Это свойство позволяет нам напрямую запретить использование указанных полей и всех их дочерних полей в настройках порядка (сортировки).

Как это работает: Когда для поля компоновки данных (например, в запросе динамического списка) устанавливается ОграничениеИспользованияВПорядке = Истина, это поле и любые поля, полученные "через точку" от него, не будут входить в коллекцию доступных полей для сортировки в пользовательских настройках. Это именно то, что нам нужно для борьбы с сортировкой по неоптимальным "полям через точку".

Преимущества:

  1. Простота: Не требуется сложный код для очистки и добавления элементов в коллекцию порядка. Мы просто указываем свойство для нежелательных полей.
  2. Точность: Позволяет очень точно исключить конкретные поля и их дочерние поля.
  3. Производительность: Предотвращает формирование "тяжелых" запросов из-за неявных соединений при попытке сортировки по сложным полям.

Где устанавливается: Это свойство устанавливается в схеме компоновки данных (СКД), которая лежит в основе динамического списка. Мы можем сделать это программно в модуле формы или в модуле объекта, где формируется схема компоновки.

Рассмотрим, как мы можем применить это свойство:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ)
    // Получаем схему компоновки данных динамического списка
    СхемаКомпоновки = Список.КомпоновщикНастроек.ПолучитьМакетКомпоновки().СхемаКомпоновкиДанных;

    // Ищем поле, которое хотим исключить из сортировки.
    // Например, если в запросе есть "Контрагент.Наименование",
    // и мы не хотим по нему сортировать.
    // В данном примере будем искать поле "Контрагент".
    // Если мы хотим запретить сортировку по всем реквизитам контрагента
    // через поле "Контрагент" в нашем списке.

    Для Каждого ПолеСКД Из СхемаКомпоновки.Поля Выбрать
        Если ПолеСКД.Имя = "Контрагент" Тогда // Имя поля в схеме компоновки
            ПолеСКД.ОграничениеИспользованияВПорядке = Истина;
            Прервать;
        КонецЕсли;
    КонецЦикла;

    // Важно: После изменения схемы компоновки, необходимо обновить компоновщик настроек.
    Список.КомпоновщикНастроек.ЗагрузитьНастройки(Список.КомпоновщикНастроек.Настройки);

    // Если мы хотим ограничить сортировку по полю, которое в запросе называется "ДокументПоступления.Номер"
    // и оно добавлено в список как поле "НомерДокументаПоступления",
    // то искать нужно имя поля, как оно определено в схеме СКД (исходное имя или алиас).
    // Если в запросе SELECT ДокументПоступления.Номер КАК НомерДокументаПоступления
    // то мы можем ограничить по "НомерДокументаПоступления" или по "ДокументПоступления".
    // Ограничение по "ДокументПоступления" будет более общим и запретит все его дочерние поля.

    // Пример для поля из другого объекта
    Для Каждого ПолеСКД Из СхемаКомпоновки.Поля Выбрать
        Если ПолеСКД.Имя = "Ссылка.Контрагент.ИНН" Тогда // Если поле добавлено напрямую как Ссылка.Контрагент.ИНН
            ПолеСКД.ОграничениеИспользованияВПорядке = Истина;
            Прервать;
        КонецЕсли;
    КонецЦикла;

    // После модификации схемы, нужно обновить КомпоновщикНастроек.
    Список.КомпоновщикНастроек.ЗагрузитьНастройки(Список.КомпоновщикНастроек.Настройки);

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

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

4. Управление свойством НастройкаПорядка для колонок табличного поля

Этот метод позволяет управлять доступностью сортировки для конкретных колонок динамического списка, которые визуально представлены на форме. Мы можем разрешить или запретить сортировку по заголовку колонки.

Свойство НастройкаПорядка доступно для каждой колонки табличного поля. Мы можем обратиться к нему и изменить его доступность программно. Например, если у нас есть динамический список, представленный табличным полем РегистрСведенийСписок, и в нем есть колонка НомерСоглашения, мы можем управлять ее доступностью для сортировки:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ)
    // Разрешаем сортировку по колонке "НомерСоглашения"
    ЭлементыФормы.РегистрСведенийСписок.НастройкаПорядка.НомерСоглашения.Доступность = Истина;

    // Запрещаем сортировку по колонке "Комментарий"
    ЭлементыФормы.РегистрСведенийСписок.НастройкаПорядка.Комментарий.Доступность = Ложь;

    // Важно: это управляет только интерактивной сортировкой по заголовку колонки,
    // но не влияет на список полей в "Настройках списка" для продвинутой сортировки.
    // Для полного контроля необходимо комбинировать методы.
КонецПроцеду

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

Заключительные рекомендации

Для достижения наилучшего результата и обеспечения высокой производительности при работе с динамическими списками, мы рекомендуем комплексный подход:

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

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

← На главную