Динамический список, запрос и СписокЗначений: три способа вывести данные списком в 1С 8.3

· 9 мин

Содержание

Чтобы создать список в 1С 8.3 на управляемой форме, добавьте в форму реквизит типа ДинамическийСписок, укажите основную таблицу (например, Справочник.Номенклатура) и перетащите реквизит в дерево элементов: платформа сама создаст таблицу с колонками. Если нужен список в коде, а не на экране, используйте Новый СписокЗначений и метод Добавить().

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

Какой список нужен под вашу задачу

В 1С словом «список» называют несколько разных вещей. Ошибка в выборе типа потом стоит переделки формы.

ТипГде хранит данныеКогда братьОграничения
ДинамическийСписокВ базе, читает порциямиФорма списка справочника, журнал документов, выборка по запросуТолько на форме, в произвольном коде не создаётся
СписокЗначенийВ памятиВарианты выбора, пометки, передача набора значений на клиентНеудобен для сотен строк с несколькими полями
ТаблицаЗначенийВ памяти, только на сервереРасчёты, обработка выборкиНа форме превращается в ДанныеФормыКоллекция
МассивВ памятиПростой набор ссылок для параметра запросаНет представлений и пометок
Что вы хотите получить?

Создание списка на управляемой форме

Форма списка объекта через конструктор

Для справочника, документа или регистра платформа умеет собрать форму списка сама:

  1. Откройте объект в Конфигураторе двойным щелчком.
  2. Перейдите на вкладку «Формы».
  3. Рядом с полем «Список» нажмите кнопку создания новой формы.
  4. В конструкторе формы выберите тип «Форма списка» и нажмите «Готово».

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

Если форму списка не создавать вовсе, платформа построит её на лету. Свою форму делают, когда нужны отбор по умолчанию, дополнительные колонки или своё оформление.

Динамический список на любой форме

Список можно вывести и на форме обработки, документа или рабочего места:

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

Основная таблица важна. По ней список понимает, что открывать двойным щелчком и что создавать по кнопке «Создать».

Список по своему запросу: конструктор и параметры

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

Как включить произвольный запрос

  1. Откройте свойства реквизита Список и нажмите ссылку «Открыть» у пункта «Настройка списка».
  2. В окне настроек установите флажок «Произвольный запрос».
  3. Нажмите кнопку конструктора запроса и соберите запрос мышью: таблицы, поля, связи, условия.
  4. Проверьте, что поле «Основная таблица» осталось заполненным.

Пример текста запроса. Имя регистра остатков зависит от конфигурации, здесь это иллюстрация:

ВЫБРАТЬ
    Номенклатура.Ссылка КАК Ссылка,
    Номенклатура.Наименование КАК Наименование,
    Номенклатура.Артикул КАК Артикул,
    ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток
ИЗ
    Справочник.Номенклатура КАК Номенклатура
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(, Склад = &Склад) КАК Остатки
        ПО Остатки.Номенклатура = Номенклатура.Ссылка
ГДЕ
    НЕ Номенклатура.ЭтоГруппа

Два приёма из этого запроса стоит запомнить:

  • 🔹 ЕСТЬNULL нужен из-за левого соединения: у товара без остатка поле будет NULL, а не ноль.
  • 🔹 Условие по складу стоит в параметрах виртуальной таблицы Остатки(, Склад = &Склад), а не в ГДЕ. Так платформа считает остатки только по одному складу.

Как передать значение параметра

Параметры динамического списка задают при создании формы и меняют при изменении поля на форме:

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

&НаКлиенте
Процедура СкладПриИзменении(Элемент)
    Список.Параметры.УстановитьЗначениеПараметра("Склад", Склад);
КонецПроцедуры

После установки параметра список перечитает данные сам, вызывать Элементы.Список.Обновить() не нужно.

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

Отбор и сортировка списка из кода

Отбор динамического списка строится на механизме компоновки данных. Значит, и в коде работают объекты компоновки:

&НаСервере
Процедура УстановитьОтборПоОрганизации(Организация)
    ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Организация");
    ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
    ЭлементОтбора.ПравоеЗначение = Организация;
    ЭлементОтбора.Использование = Истина;
КонецПроцедуры

Такой отбор пользователь увидит и сможет снять. Если отбор должен быть жёстким, добавляйте элемент в Список.КомпоновщикНастроек.ФиксированныеНастройки.Отбор: он работает, но в интерфейсе не виден.

В типовых конфигурациях на БСП короче вызвать готовую процедуру:

ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
    Список, "Организация", Организация, ВидСравненияКомпоновкиДанных.Равно, , Истина);

Она не плодит дубли: если отбор по полю уже есть, процедура обновит его значение.

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

Создание списка значений в коде

СписокЗначений создают конструктором и наполняют методом Добавить(Значение, Представление). Второй параметр — то, что увидит пользователь.

Выбор варианта без модальных окон

&НаКлиенте
Процедура ВыбратьРежим(Команда)
    Варианты = Новый СписокЗначений;
    Варианты.Добавить("ОСН", "Общая система");
    Варианты.Добавить("УСН", "Упрощённая система");
    Варианты.Добавить("АУСН", "Автоматизированная УСН");

    Оповещение = Новый ОписаниеОповещения("ВыборРежимаЗавершение", ЭтотОбъект);
    Варианты.ПоказатьВыборЭлемента(Оповещение, "Режим налогообложения");
КонецПроцедуры

&НаКлиенте
Процедура ВыборРежимаЗавершение(ВыбранныйЭлемент, ДополнительныеПараметры) Экспорт
    Если ВыбранныйЭлемент = Неопределено Тогда
        Возврат; // пользователь закрыл окно
    КонецЕсли;
    Сообщить("Выбран режим: " + ВыбранныйЭлемент.Представление);
КонецПроцедуры

Процедура-обработчик обязательно Экспорт, иначе оповещение её не найдёт. Для выбора нескольких вариантов с флажками есть ПоказатьОтметкуЭлементов: отмеченные элементы получат Пометка = Истина.

Полезные методы

ЗадачаМетод
Заполнить из массиваЗагрузитьЗначения(Массив) — заменяет содержимое
Получить массивВыгрузитьЗначения()
Найти элементНайтиПоЗначению(Значение) — вернёт Неопределено, если нет
ОтсортироватьСортироватьПоПредставлению() или СортироватьПоЗначению()
Вставить в позициюВставить(Индекс, Значение, Представление)
Ограничить типсвойство ТипЗначения

Удаление элементов в цикле

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

Всего = Варианты.Количество();
Для Сч = 1 По Всего Цикл
    Элемент = Варианты[Всего - Сч];
    Если НЕ ЗначениеЗаполнено(Элемент.Значение) Тогда
        Варианты.Удалить(Элемент);
    КонецЕсли;
КонецЦикла;

При трёх элементах цикл пройдёт индексы 2, 1, 0. Удаление элемента с большим индексом не сдвигает меньшие, поэтому ни одна строка не теряется.

Список выбора у поля формы

Если варианты нужны в выпадающем поле, не создавайте отдельный реквизит. Заполните список выбора самого элемента:

Элементы.РежимНалогообложения.СписокВыбора.Очистить();
Элементы.РежимНалогообложения.СписокВыбора.Добавить("ОСН", "Общая система");
Элементы.РежимНалогообложения.СписокВыбора.Добавить("УСН", "Упрощённая система");

Свойство СписокВыбора имеет тот же тип СписокЗначений, так что все методы выше работают и здесь.

Колонки и оформление списка

Внешний вид таблицы настраивают в свойствах элементов формы, а не в реквизите.

Свойства колонок

  • 📏 «Ширина» и «Растягивать по горизонтали» — чтобы наименование забирало свободное место, а код и дата оставались узкими.
  • 🧩 Группа колонок с группировкой «В ячейке» — два поля в одной ячейке, например артикул под наименованием.
  • 🔢 «Формат» — ЧДЦ=2 для сумм, ДФ=dd.MM.yyyy для дат без времени.
  • 👁 «Видимость» и «Пользовательская видимость» — колонка скрыта, но пользователь может включить её сам.
  • ➕ «Подвал» у таблицы и «Путь к данным подвала» у колонки — итог под таблицей. Для динамического списка значение итога вы считаете сами в реквизит формы.

Пользователь в режиме «Такси» может поменять состав колонок через Ещё → Изменить форму. Его настройки сохраняются отдельно и перекрывают ваши изменения в Конфигураторе.

Условное оформление

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

Оформление = Список.УсловноеОформление.Элементы.Добавить();
Оформление.Оформление.УстановитьЗначениеПараметра("ЦветТекста", WebЦвета.Серый);

Условие = Оформление.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Условие.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Остаток");
Условие.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
Условие.ПравоеЗначение = 0;

Товары с нулевым остатком станут серыми. То же самое настраивается без кода на вкладке условного оформления в окне «Настройка списка».

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

Медленный список почти всегда упирается в запрос. Что проверить по порядку:

  1. ⚡ Динамическое считывание данных. Флажок в настройках списка должен быть включён. Тогда платформа читает строки порциями по мере прокрутки.
  2. 🗂 Основная таблица. Без неё список с произвольным запросом теряет стандартные команды и позиционирование на текущей ссылке.
  3. 🧮 Параметры виртуальных таблиц. Условия на склад, организацию и период ставьте в скобки Остатки(...), а не в ГДЕ.
  4. 🔗 Разыменование через точку. Каждое Ссылка.Контрагент.ИНН — скрытое соединение. Нужное поле лучше явно присоединить в запросе.
  5. 📇 Индексы. Поля, по которым пользователи часто сортируют и отбирают, индексируйте в свойствах реквизита объекта (Индексировать).
  6. 🌳 Режим дерева. Для справочника на десятки тысяч элементов иерархический вид «Дерево» заметно тяжелее, чем «Иерархический список».

Вычисляемые колонки без подзапросов

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

&НаСервереБезКонтекста
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, Настройки, Строки)
    Для Каждого КлючИСтрока Из Строки Цикл
        ДанныеСтроки = КлючИСтрока.Значение;
        ДанныеСтроки.Данные.Пометка = (ДанныеСтроки.Данные.Остаток > 0);
    КонецЦикла;
КонецПроцедуры

Поле Пометка в этом примере должно быть в запросе списка (например, ЛОЖЬ КАК Пометка). Поля, которых нет в видимых колонках, включите в выборку через Список.УстановитьОбязательноеИспользование("Остаток", Истина).

Не делайте в этом событии запрос на каждую строку. При порции в 50–100 строк это 50–100 обращений к базе при каждой прокрутке. Соберите ключи в массив и прочитайте данные одним запросом.

Когда динамический список не нужен

Если на форме должно быть 20–30 строк, которые пользователь редактирует, берите реквизит ТаблицаЗначений. Заполнение 50 000 строк в таблицу значений, наоборот, ошибка: форма будет открываться секундами, а все данные уйдут на клиент.

Ошибки при создании списков и как их исправить

Диагностика: выберите симптом

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

Можно ли создать динамический список полностью из кода?
Да. На сервере добавьте реквизит формы методом ИзменитьРеквизиты с типом ДинамическийСписок, затем таблицу формы через Элементы.Добавить. Для постоянных форм проще сделать это в редакторе.
Чем список значений отличается от массива?
У элемента списка значений есть представление, пометка и картинка, а у массива только значение. Для параметра запроса подходят оба.
Как вывести список в Excel?
В режиме «Такси» откройте Ещё → Вывести список, выберите колонки и сохраните полученный табличный документ в формате xlsx.
Почему при выборе из поля открывается не та форма?
У объекта может быть отдельная основная форма выбора. Если её нет, платформа берёт форму списка. Проверьте вкладку «Формы» объекта.
Можно ли в одном списке показать справочник и документы?
Можно через произвольный запрос с ОБЪЕДИНИТЬ ВСЕ, но основная таблица будет одна. Команды открытия для строк второй таблицы придётся писать самому.