К статье
Практический материал

Разработка и Конфигурация · 12 мин

1С: как обойти ограничения динамического списка

Как обойти ограничения динамического списка в 1С: произвольный запрос, временные таблицы, отборы, группировки и альтернативы. Практические приемы и типичные ошибки.

Динамический список в 1С — удобный механизм отображения данных в формах, но у него жесткие ограничения: нельзя использовать временные таблицы в произвольном запросе без дополнительной настройки, нельзя напрямую менять состав выборки кодом, сложно программно добавлять строки и колонки. Когда типовых возможностей не хватает, разработчику приходится «обходить» динамический список — либо корректно настраивая его скрытые параметры, либо заменяя другим механизмом.

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

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

Что именно ограничивает динамический список

Прежде чем обходить механизм, полезно четко понять, какие ограничения встроены в платформу. Динамический список строится на запросе, который платформа выполняет сама, порционно подгружая данные при прокрутке. Из-за этого к тексту запроса предъявляются требования: он должен быть «прокручиваемым» и сортироваться платформой.

Основные ограничения, с которыми сталкиваются на практике:

  • нельзя использовать конструкции, несовместимые с динамической выборкой (например, итоги с обобщением, некоторые виды соединений без ключевых полей);
  • временные таблицы в произвольном запросе требуют явного указания ключевого поля и корректной настройки, иначе список работает нестабильно;
  • нельзя программно добавить или удалить строку — список всегда отражает результат запроса;
  • нельзя выводить вычисляемые «на лету» колонки, которых нет в запросе;
  • группировки и итоги поддерживаются ограниченно и не всегда дают ожидаемый результат.

Если задача упирается хотя бы в два пункта из этого списка, скорее всего, динамический список — неподходящий инструмент, и «обход» превратится в борьбу с платформой. В таких случаях правильнее сразу перейти к альтернативе, описанной в последних разделах.

Обход 1: произвольный запрос и временные таблицы

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

Порядок действий в конфигураторе или программно:

Настройка произвольного запроса
  1. 1
    Установите у динамического списка свойство «ПроизвольныйЗапрос» = Истина
  2. 2
    Впишите текст запроса в свойство «ТекстЗапроса»
  3. 3
    Укажите «Основную таблицу», если нужны стандартные команды (создать, изменить, открыть)
  4. 4
    Задайте ключевые поля выборки — платформа использует их для позиционирования и обновления строк
  5. 5
    Проверьте, что запрос не содержит конструкций, несовместимых с динамической выборкой

Пример программной установки запроса с временной таблицей:

Список.ПроизвольныйЗапрос = Истина;

Список.ТекстЗапроса =

"ВЫБРАТЬ

| Продажи.Номенклатура КАК Номенклатура,

| СУММА(Продажи.Количество) КАК Количество

|ПОМЕСТИТЬ ВТ_Продажи

|ИЗ

| РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК Продажи

|СГРУППИРОВАТЬ ПО

| Продажи.Номенклатура

|;

|ВЫБРАТЬ

| ВТ_Продажи.Номенклатура КАК Номенклатура,

| ВТ_Продажи.Количество КАК Количество

|ИЗ

| ВТ_Продажи КАК ВТ_Продажи";

Список.Параметры.УстановитьЗначениеПараметра("НачалоПериода", НачалоМесяца(ТекущаяДатаСеанса()));

Список.Параметры.УстановитьЗначениеПараметра("КонецПериода", КонецМесяца(ТекущаяДатаСеанса()));

Ключевой момент: у итоговой выборки должно быть поле, однозначно идентифицирующее строку. Если такого поля нет (например, после группировки), список может дублировать строки при прокрутке или терять текущую позицию. В таком случае добавьте в запрос уникальный идентификатор — например, ссылку на сгруппированное значение.

Обход 2: программное изменение запроса, отборов и параметров

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

Установка отбора программно:

ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));

ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Организация");

ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;

ЭлементОтбора.ПравоеЗначение = ТекущаяОрганизация;

ЭлементОтбора.Использование = Истина;

Частая ошибка — устанавливать отбор через Список.КомпоновщикНастроек.Настройки.Отбор и удивляться, почему пользователь его не видит или он сбрасывается. Отбор, заданный через Список.Отбор, является «фиксированным» и не доступен пользователю для редактирования, а настройки компоновщика пользователь может менять. Выбирайте место установки отбора осознанно: служебные ограничения (например, по правам доступа) — в Список.Отбор, пользовательские фильтры — в настройки компоновщика.

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

Обход 3: отключение автоматического обновления и контроль чтения данных

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

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

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

Обход 4: замена динамического списка таблицей значений

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

Схема простая: создаете реквизит формы типа «ТаблицаЗначений» с нужными колонками, при создании формы или по команде выполняете запрос (в том числе пакетный, с временными таблицами и расчетами), загружаете результат в таблицу и при необходимости дозаполняете вычисляемые колонки в цикле.

Запрос = Новый Запрос;

Запрос.Текст = "..."; // любой сложный запрос

РезультатЗапроса = Запрос.Выполнить().Выгрузить();

ЗначениеВРеквизитФормы(РезультатЗапроса, "ТаблицаДанных");

Цена решения: вы теряете порционную подгрузку (все данные читаются сразу), автоматическое обновление и стандартные команды работы со списком. Для выборок в тысячи строк это обычно приемлемо, для сотен тысяч — уже нет, и стоит подумать о постраничном выводе или отчете на СКД вместо таблицы на форме.

Что выбрать вместо обхода

Произвольный запрос в динамическом списке

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

Таблица значений

Подходит для расчетных колонок, ручного добавления строк, данных из разных источников. Ограничение — нет порционной подгрузки и автообновления.

Дерево значений

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

Отчет на СКД

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

Типичные ошибки при обходе динамического списка

Большинство проблем возникает не из-за ограничений платформы, а из-за неверных предположений о том, как список работает. Разберем самые частые.

Типичные ошибки
01
Группировка без уникального ключа — строки дублируются при прокрутке, текущая позиция теряется
02
Установка отбора в КомпоновщикНастроек вместо Список.Отбор — пользователь случайно сбрасывает служебный отбор и видит лишние данные
03
Смена текста запроса без переустановки параметров — ошибка исполнения или данные за неправильный период
04
Попытка добавить строку в динамический список кодом — механизм этого не поддерживает в принципе, нужна таблица значений
05
Тяжелый запрос с лишними соединениями — список тормозит при каждом автоматическом обновлении

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

Как проверить, что обход сработал

После настройки произвольного запроса или замены механизма проверьте поведение списка по контрольным точкам, а не только «открылось — не открылось».

Контрольные точки

Как проверить результат

Прокрутка списка до конца и обратно
Норма

Строки не дублируются, порядок стабилен

Тревожный признак

Появляются повторы или строки «прыгают»

Открытие и изменение записи из списка
Норма

После записи список показывает обновленную строку на той же позиции

Тревожный признак

Запись пропадает или список не обновляется

Применение и сброс пользовательских отборов
Норма

Служебный отбор сохраняется, пользовательский меняется

Тревожный признак

Сброс отборов показывает лишние данные

Время открытия формы и обновления
Норма

Форма открывается без заметной паузы

Тревожный признак

Секунды ожидания при каждом обновлении

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

Итог

Что важно запомнить

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

Частые вопросы

Можно ли использовать временные таблицы в динамическом списке?

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

Почему в динамическом списке с группировкой дублируются строки?

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

Как программно добавить строку в динамический список?

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

Чем отличается отбор в Список.Отбор от отбора в настройках компоновщика?

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

Как ускорить медленный динамический список?

Начните с самого запроса: уберите лишние поля и соединения, проверьте индексы по полям отбора и сортировки. Затем рассмотрите отключение автоматического обновления с ручным обновлением по кнопке. Если данных очень много — перенесите аналитику в отчет на СКД.

Когда лучше сразу отказаться от динамического списка?

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