Работа со списками в 1С 8.3: от запроса до формы
Содержание
Список в 1С 8.3 собирают тремя способами: запросом к базе (Запрос → Выбрать или Выгрузить), вручную в объекте ТаблицаЗначений и динамическим списком прямо на форме. Выбор зависит от того, где данные лежат и сколько их.
Запрос нужен, когда строки берутся из справочников, документов или регистров. Таблица значений — когда данные собираются в коде из разных источников или рассчитываются на лету. Динамический список — когда пользователю надо показать тысячи записей из базы с прокруткой, отбором и сортировкой без выгрузки всего массива в память.
Разберём каждый способ с рабочими примерами кода, покажем отборы, вывод на форму и приёмы, без которых большой список будет тормозить.
Чем отличаются таблица значений, список значений и динамический список
Прежде чем писать код, определитесь с типом объекта. В платформе их несколько, и путаница здесь — частая причина переделок.
- 📋
ТаблицаЗначений— таблица в памяти с произвольными колонками. Живёт на сервере или на клиенте, строится в коде. Подходит для расчётов, промежуточных данных, выгрузки результата запроса. - 📝
СписокЗначений— одномерный набор элементов (значение + представление + пометка). Удобен для выбора из нескольких вариантов, множественного выбора, хранения небольшого перечня. - 🗂
ДинамическийСписок— специальный реквизит формы. Сам читает данные из базы постранично, умеет отбор, сортировку, условное оформление. Это то, что видит пользователь в журнале документов или списке справочника. - 📊 Результат запроса — не хранится как список, а обходится выборкой (
Выбрать) или выгружается вТаблицаЗначенийметодомВыгрузить. - 🧾 Табличная часть документа или справочника — это уже готовый список строк внутри объекта. Отдельно его формировать не нужно: строки добавляются методом
Добавитьу самой табличной части, а для показа она выводится на форму как таблица.
Простое правило: данные из базы для показа пользователю — динамический список; данные для обработки в коде — таблица значений; короткий перечень вариантов — список значений.
Как собрать список запросом к базе
Запрос — основной инструмент, когда строки берутся из справочников, документов или регистров. Текст пишется на языке запросов, затем результат либо обходится построчно, либо выгружается в таблицу значений.
Пример: собрать список номенклатуры без пометки удаления и без групп, упорядоченный по наименованию.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Товары.Ссылка КАК Номенклатура,
| Товары.Наименование КАК Наименование,
| Товары.Артикул КАК Артикул
|ИЗ
| Справочник.Номенклатура КАК Товары
|ГДЕ
| НЕ Товары.ПометкаУдаления
| И НЕ Товары.ЭтоГруппа
|УПОРЯДОЧИТЬ ПО
| Наименование";
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Наименование + " / " + Выборка.Артикул);
КонецЦикла;
Если список нужен не для обхода, а как таблица для дальнейшей работы, замените две последние конструкции на одну строку:
ТаблицаТоваров = Запрос.Выполнить().Выгрузить();
Выгрузить вернёт готовую ТаблицаЗначений с колонками Номенклатура, Наименование, Артикул — ровно теми, что перечислены в секции ВЫБРАТЬ с псевдонимами КАК.
Как передать условия через параметры
Жёстко прописывать даты и значения в тексте запроса нельзя — используйте параметры. Их подставляют через &ИмяПараметра в тексте и задают методом УстановитьПараметр.
Запрос.Текст =
"ВЫБРАТЬ
| Продажи.Номенклатура КАК Номенклатура,
| Продажи.Количество КАК Количество
|ИЗ
| РегистрНакопления.Продажи КАК Продажи
|ГДЕ
| Продажи.Период МЕЖДУ &ДатаНачала И &ДатаКонца";
Запрос.УстановитьПараметр("ДатаНачала", НачалоДня(ДатаОтчёта));
Запрос.УстановитьПараметр("ДатаКонца", КонецДня(ДатаОтчёта));
Параметры — единственный безопасный способ подставить значения в запрос. Склейка текста запроса со значениями через строки ломается на спецсимволах и небезопасна.
Как построить таблицу значений вручную
Когда данных в базе нет или их надо рассчитать, таблицу собирают в коде. Сначала объявляют колонки с типами, потом добавляют строки.
Список = Новый ТаблицаЗначений;
Список.Колонки.Добавить("Наименование", Новый ОписаниеТипов("Строка"));
Список.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
Список.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));
Строка = Список.Добавить();
Строка.Наименование = "Бумага А4";
Строка.Количество = 10;
Строка.Сумма = 3500;
Строка = Список.Добавить();
Строка.Наименование = "Картридж";
Строка.Количество = 2;
Строка.Сумма = 8400;
Указывать ОписаниеТипов для колонки не обязательно — без него колонка примет любой тип. Но типизированная колонка работает быстрее и защищает от случайной записи строки в числовое поле.
Итоги, свёртка и сортировка
У таблицы значений есть встроенные методы, которые закрывают большинство задач без ручных циклов:
| Метод | Что делает | Пример |
|---|---|---|
Итог | сумма по колонке | Список.Итог("Сумма") → 11900 |
Свернуть | группировка с суммированием | Список.Свернуть("Наименование", "Количество, Сумма") |
Сортировать | упорядочивание | Список.Сортировать("Сумма Убыв") |
НайтиСтроки | отбор по условию | см. ниже |
Найти | поиск одного значения | Список.Найти("Картридж", "Наименование") |
Свернуть первым параметром принимает колонки группировки, вторым — колонки, которые суммируются. После свёртки строки с одинаковым наименованием схлопнутся в одну с суммой количеств.
Получить итоги прямо в запросе
Если группировка нужна на данных из базы, не выгружайте таблицу ради Свернуть — посчитайте итоги в самом запросе секцией ИТОГИ. Это работает на стороне СУБД и не гоняет лишние строки:
Запрос.Текст =
"ВЫБРАТЬ
| Продажи.Номенклатура КАК Номенклатура,
| Продажи.Количество КАК Количество
|ИЗ
| РегистрНакопления.Продажи КАК Продажи
|ИТОГИ
| СУММА(Количество)
|ПО
| Номенклатура";
Обход такого результата дают методы Выбрать с группировкой либо ВыгрузитьКолонку для отдельного столбца.
Как сформировать список значений для выбора
СписокЗначений нужен там, где ТаблицаЗначений избыточна: предложить пользователю выбрать один вариант из нескольких, собрать перечень для множественного выбора или передать набор значений в параметр отбора.
Строится он в коде методом Добавить, у каждого элемента есть само значение, строковое представление и пометка:
Варианты = Новый СписокЗначений;
Варианты.Добавить(1, "Приход");
Варианты.Добавить(2, "Расход");
Варианты.Добавить(3, "Перемещение");
Выбранный = Варианты.ВыбратьЭлемент("Укажите тип операции");
Если Выбранный <> Неопределено Тогда
Сообщить(Выбранный.Представление);
КонецЕсли;
Метод ВыбратьЭлемент сам показывает окно выбора и возвращает выбранный элемент или Неопределено, если пользователь отказался. Для множественного выбора используйте ОтметитьЭлементы, затем обходите список и проверяйте свойство Пометка у каждого элемента.
Список значений удобно наполнять из таблицы значений: обойдите строки циклом и добавляйте нужную колонку через Добавить. Так получается перечень для отбора без лишних объектов.
Как применить отбор и динамическую фильтрацию
Фильтровать список можно на трёх уровнях — выбирайте в зависимости от того, где данные.
В запросе — самый быстрый вариант. Условие в секции ГДЕ отсекает лишние строки ещё на сервере СУБД, до передачи данных. Всегда фильтруйте здесь, если данные приходят из базы.
В таблице значений — когда данные уже собраны. Метод НайтиСтроки принимает структуру «колонка → значение» и возвращает массив подходящих строк:
Отбор = Новый Структура("Наименование", "Картридж");
НайденныеСтроки = Список.НайтиСтроки(Отбор);
Для Каждого Стр Из НайденныеСтроки Цикл
Сообщить(Стр.Количество);
КонецЦикла;
В динамическом списке — отбор задаётся через настройки компоновки. В коде это выглядит так:
ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Организация");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = ВыбраннаяОрганизация;
ЭлементОтбора.Использование = Истина;
Отбор динамического списка применяется к данным в базе, а не к уже загруженным строкам. Поэтому он работает одинаково быстро и на сотне, и на миллионе записей — читаются только подходящие строки.
Пользователь настраивает отбор сам: в командной панели списка меню «Еще» содержит команды настройки списка, где задаются отбор, сортировка и группировки. Эти настройки платформа сохраняет для конкретного пользователя.
Как вывести список на форму
Способ вывода зависит от типа объекта.
Динамический список добавляется как реквизит формы. В конфигураторе откройте форму, добавьте реквизит типа ДинамическийСписок и в его свойствах укажите основную таблицу, например Справочник.Номенклатура. Если нужен нестандартный набор колонок — включите свойство «Произвольный запрос» и впишите текст запроса. Затем перетащите реквизит в дерево элементов формы — платформа создаст таблицу с колонками.
Таблицу значений на форме показывают через реквизит формы соответствующего типа. Собранную на сервере таблицу переносят в реквизит методом ЗначениеВРеквизитФормы:
&НаСервере
Процедура ЗаполнитьСписок()
ТаблицаТоваров = СформироватьТаблицу(); // ваш код сборки ТЗ
ЗначениеВРеквизитФормы(ТаблицаТоваров, "СписокНаФорме");
КонецПроцедуры
Обратное преобразование — РеквизитФормыВЗначение, когда таблицу с формы надо обработать на сервере.
Реакция на действия пользователя
Для интерактивности у таблицы на форме есть события. Чаще всего используют:
ПриАктивизацииСтроки— курсор встал на строку (показать детали, пересчитать);Выбор— двойной щелчок илиEnterпо строке;ПередНачаломИзменения— пользователь начал редактировать ячейку.
Обработчик добавляется в палитре свойств элемента таблицы, на вкладке событий.
ПриСозданииНаСервере или по команде) и что ЗначениеВРеквизитФормы отработало.НЕ ПометкаУдаления и НЕ ЭтоГруппа. Для справочников с иерархией добавьте оба.ОписаниеТипов.Как ускорить работу с большими списками
На сотне строк разницы нет, но на десятках тысяч неудачный код подвешивает форму. Несколько приёмов, которые реально влияют на скорость.
- 🚀 Для больших данных — динамический список, а не выгрузка в ТЗ. Он читает из базы только видимые на экране строки и подгружает остальные при прокрутке. Выгрузка миллиона записей в таблицу значений на клиент положит сеанс.
- 🧮 Фильтруйте в запросе, а не после. Условие в
ГДЕотрабатывает на сервере СУБД. Выгрузить всё, а потом отсеятьНайтиСтроки— значит зря перегнать данные по сети. - 🔗 Избегайте обращения к реквизитам через точку в больших выборках. Конструкция
Товары.ОсновнойПоставщик.Наименованиев запросе по тысячам строк порождает неявные соединения. Лучше соединить таблицы явно черезЛЕВОЕ СОЕДИНЕНИЕ. - 🗜 Индексируйте временные таблицы. Если запрос использует временные таблицы и соединяет их по полю — добавьте
ИНДЕКСИРОВАТЬ ПОэтому полю. - 📦 Не держите большие таблицы значений на клиенте. Расчёты делайте на сервере, на клиент передавайте только итог или готовую к показу форму.
Если форма со списком открывается медленно — посмотрите, не выполняется ли тяжёлый запрос в ПриСозданииНаСервере. Тяжёлую сборку выносите в фоновое задание или в команду по кнопке.
Частые вопросы
Чем `Выбрать` отличается от `Выгрузить` у результата запроса?
Выбрать возвращает выборку для построчного обхода в цикле — данные читаются по одной записи, память экономится. Выгрузить сразу формирует всю таблицу значений в памяти. Для обхода берите Выбрать, для дальнейшей обработки таблицей — Выгрузить.Можно ли сформировать список значений из таблицы значений?
Добавить. Обратно — наоборот, перебором элементов списка.Как получить итоги по группам без ручного цикла?
Свернуть: первым параметром — колонки группировки, вторым — суммируемые колонки. Платформа сама схлопнет одинаковые строки и сложит числа. Для данных из базы те же итоги даёт секция ИТОГИ в запросе.Почему динамический список не показывает колонку из запроса?
ВЫБРАТЬ с псевдонимом.Как отфильтровать таблицу значений по нескольким условиям сразу?
НайтиСтроки структуру с несколькими ключами — метод вернёт строки, удовлетворяющие всем условиям одновременно (логическое «И»). Для более сложной логики обходите строки циклом с нужным условием.