Работа со списками в 1С 8.3: от запроса до формы

· 9 мин

Содержание

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

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

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

Чем отличаются таблица значений, список значений и динамический список

Прежде чем писать код, определитесь с типом объекта. В платформе их несколько, и путаница здесь — частая причина переделок.

  • 📋 ТаблицаЗначений — таблица в памяти с произвольными колонками. Живёт на сервере или на клиенте, строится в коде. Подходит для расчётов, промежуточных данных, выгрузки результата запроса.
  • 📝 СписокЗначений — одномерный набор элементов (значение + представление + пометка). Удобен для выбора из нескольких вариантов, множественного выбора, хранения небольшого перечня.
  • 🗂 ДинамическийСписок — специальный реквизит формы. Сам читает данные из базы постранично, умеет отбор, сортировку, условное оформление. Это то, что видит пользователь в журнале документов или списке справочника.
  • 📊 Результат запроса — не хранится как список, а обходится выборкой (Выбрать) или выгружается в ТаблицаЗначений методом Выгрузить.
  • 🧾 Табличная часть документа или справочника — это уже готовый список строк внутри объекта. Отдельно его формировать не нужно: строки добавляются методом Добавить у самой табличной части, а для показа она выводится на форму как таблица.

Простое правило: данные из базы для показа пользователю — динамический список; данные для обработки в коде — таблица значений; короткий перечень вариантов — список значений.

Как собрать список запросом к базе

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

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

Запрос = Новый Запрос;
Запрос.Текст =
    "ВЫБРАТЬ
    |   Товары.Ссылка КАК Номенклатура,
    |   Товары.Наименование КАК Наименование,
    |   Товары.Артикул КАК Артикул
    |ИЗ
    |   Справочник.Номенклатура КАК Товары
    |ГДЕ
    |   НЕ Товары.ПометкаУдаления
    |   И НЕ Товары.ЭтоГруппа
    |УПОРЯДОЧИТЬ ПО
    |   Наименование";

Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
    Сообщить(Выборка.Наименование + " / " + Выборка.Артикул);
КонецЦикла;

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

ТаблицаТоваров = Запрос.Выполнить().Выгрузить();

Выгрузить вернёт готовую ТаблицаЗначений с колонками Номенклатура, Наименование, Артикул — ровно теми, что перечислены в секции ВЫБРАТЬ с псевдонимами КАК.

Как передать условия через параметры

Жёстко прописывать даты и значения в тексте запроса нельзя — используйте параметры. Их подставляют через &ИмяПараметра в тексте и задают методом УстановитьПараметр.

Запрос.Текст =
    "ВЫБРАТЬ
    |   Продажи.Номенклатура КАК Номенклатура,
    |   Продажи.Количество КАК Количество
    |ИЗ
    |   РегистрНакопления.Продажи КАК Продажи
    |ГДЕ
    |   Продажи.Период МЕЖДУ &ДатаНачала И &ДатаКонца";

Запрос.УстановитьПараметр("ДатаНачала", НачалоДня(ДатаОтчёта));
Запрос.УстановитьПараметр("ДатаКонца",  КонецДня(ДатаОтчёта));

Параметры — единственный безопасный способ подставить значения в запрос. Склейка текста запроса со значениями через строки ломается на спецсимволах и небезопасна.

Как построить таблицу значений вручную

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

Список = Новый ТаблицаЗначений;
Список.Колонки.Добавить("Наименование", Новый ОписаниеТипов("Строка"));
Список.Колонки.Добавить("Количество",  Новый ОписаниеТипов("Число"));
Список.Колонки.Добавить("Сумма",       Новый ОписаниеТипов("Число"));

Строка = Список.Добавить();
Строка.Наименование = "Бумага А4";
Строка.Количество   = 10;
Строка.Сумма        = 3500;

Строка = Список.Добавить();
Строка.Наименование = "Картридж";
Строка.Количество   = 2;
Строка.Сумма        = 8400;

Указывать ОписаниеТипов для колонки не обязательно — без него колонка примет любой тип. Но типизированная колонка работает быстрее и защищает от случайной записи строки в числовое поле.

Итоги, свёртка и сортировка

У таблицы значений есть встроенные методы, которые закрывают большинство задач без ручных циклов:

МетодЧто делаетПример
Итогсумма по колонкеСписок.Итог("Сумма") → 11900
Свернутьгруппировка с суммированиемСписок.Свернуть("Наименование", "Количество, Сумма")
СортироватьупорядочиваниеСписок.Сортировать("Сумма Убыв")
НайтиСтрокиотбор по условиюсм. ниже
Найтипоиск одного значенияСписок.Найти("Картридж", "Наименование")

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

Получить итоги прямо в запросе

Если группировка нужна на данных из базы, не выгружайте таблицу ради Свернуть — посчитайте итоги в самом запросе секцией ИТОГИ. Это работает на стороне СУБД и не гоняет лишние строки:

Запрос.Текст =
    "ВЫБРАТЬ
    |   Продажи.Номенклатура КАК Номенклатура,
    |   Продажи.Количество КАК Количество
    |ИЗ
    |   РегистрНакопления.Продажи КАК Продажи
    |ИТОГИ
    |   СУММА(Количество)
    |ПО
    |   Номенклатура";

Обход такого результата дают методы Выбрать с группировкой либо ВыгрузитьКолонку для отдельного столбца.

Как сформировать список значений для выбора

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

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

Варианты = Новый СписокЗначений;
Варианты.Добавить(1, "Приход");
Варианты.Добавить(2, "Расход");
Варианты.Добавить(3, "Перемещение");

Выбранный = Варианты.ВыбратьЭлемент("Укажите тип операции");
Если Выбранный <> Неопределено Тогда
    Сообщить(Выбранный.Представление);
КонецЕсли;

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

Список значений удобно наполнять из таблицы значений: обойдите строки циклом и добавляйте нужную колонку через Добавить. Так получается перечень для отбора без лишних объектов.

Как применить отбор и динамическую фильтрацию

Фильтровать список можно на трёх уровнях — выбирайте в зависимости от того, где данные.

В запросе — самый быстрый вариант. Условие в секции ГДЕ отсекает лишние строки ещё на сервере СУБД, до передачи данных. Всегда фильтруйте здесь, если данные приходят из базы.

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

Отбор = Новый Структура("Наименование", "Картридж");
НайденныеСтроки = Список.НайтиСтроки(Отбор);
Для Каждого Стр Из НайденныеСтроки Цикл
    Сообщить(Стр.Количество);
КонецЦикла;

В динамическом списке — отбор задаётся через настройки компоновки. В коде это выглядит так:

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

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

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

Как вывести список на форму

Способ вывода зависит от типа объекта.

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

Таблицу значений на форме показывают через реквизит формы соответствующего типа. Собранную на сервере таблицу переносят в реквизит методом ЗначениеВРеквизитФормы:

&НаСервере
Процедура ЗаполнитьСписок()
    ТаблицаТоваров = СформироватьТаблицу(); // ваш код сборки ТЗ
    ЗначениеВРеквизитФормы(ТаблицаТоваров, "СписокНаФорме");
КонецПроцедуры

Обратное преобразование — РеквизитФормыВЗначение, когда таблицу с формы надо обработать на сервере.

Реакция на действия пользователя

Для интерактивности у таблицы на форме есть события. Чаще всего используют:

  • ПриАктивизацииСтроки — курсор встал на строку (показать детали, пересчитать);
  • Выбор — двойной щелчок или Enter по строке;
  • ПередНачаломИзменения — пользователь начал редактировать ячейку.

Обработчик добавляется в палитре свойств элемента таблицы, на вкладке событий.

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

Как ускорить работу с большими списками

На сотне строк разницы нет, но на десятках тысяч неудачный код подвешивает форму. Несколько приёмов, которые реально влияют на скорость.

  1. 🚀 Для больших данных — динамический список, а не выгрузка в ТЗ. Он читает из базы только видимые на экране строки и подгружает остальные при прокрутке. Выгрузка миллиона записей в таблицу значений на клиент положит сеанс.
  2. 🧮 Фильтруйте в запросе, а не после. Условие в ГДЕ отрабатывает на сервере СУБД. Выгрузить всё, а потом отсеять НайтиСтроки — значит зря перегнать данные по сети.
  3. 🔗 Избегайте обращения к реквизитам через точку в больших выборках. Конструкция Товары.ОсновнойПоставщик.Наименование в запросе по тысячам строк порождает неявные соединения. Лучше соединить таблицы явно через ЛЕВОЕ СОЕДИНЕНИЕ.
  4. 🗜 Индексируйте временные таблицы. Если запрос использует временные таблицы и соединяет их по полю — добавьте ИНДЕКСИРОВАТЬ ПО этому полю.
  5. 📦 Не держите большие таблицы значений на клиенте. Расчёты делайте на сервере, на клиент передавайте только итог или готовую к показу форму.

Если форма со списком открывается медленно — посмотрите, не выполняется ли тяжёлый запрос в ПриСозданииНаСервере. Тяжёлую сборку выносите в фоновое задание или в команду по кнопке.

Проверка перед выводом большого списка
Выполнено: 0 / 5

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

Чем `Выбрать` отличается от `Выгрузить` у результата запроса?
Выбрать возвращает выборку для построчного обхода в цикле — данные читаются по одной записи, память экономится. Выгрузить сразу формирует всю таблицу значений в памяти. Для обхода берите Выбрать, для дальнейшей обработки таблицей — Выгрузить.
Можно ли сформировать список значений из таблицы значений?
Напрямую метода нет, но это делается циклом: обойдите строки таблицы и добавляйте нужную колонку в список значений через Добавить. Обратно — наоборот, перебором элементов списка.
Как получить итоги по группам без ручного цикла?
Используйте Свернуть: первым параметром — колонки группировки, вторым — суммируемые колонки. Платформа сама схлопнет одинаковые строки и сложит числа. Для данных из базы те же итоги даёт секция ИТОГИ в запросе.
Почему динамический список не показывает колонку из запроса?
Колонку из произвольного запроса надо вручную добавить в состав видимых колонок таблицы на форме — автоматически появляются не все поля. Проверьте также, что поле есть в секции ВЫБРАТЬ с псевдонимом.
Как отфильтровать таблицу значений по нескольким условиям сразу?
Передайте в НайтиСтроки структуру с несколькими ключами — метод вернёт строки, удовлетворяющие всем условиям одновременно (логическое «И»). Для более сложной логики обходите строки циклом с нужным условием.