Разработка и Конфигурация · 11 мин
Как получить все объекты справочника в 1С
Как получить все объекты справочника в 1С: запрос, Выбрать(), ВыборкаИзРегистраСведений, обход элементов, отборы и типичные ошибки. Примеры кода.
Задача получить все объекты справочника возникает в 1С постоянно: при выгрузке данных, синхронизации с внешними системами, массовой обработке элементов, построении отчётов и проверке целостности базы. В зависимости от цели применяются разные механизмы — запрос, метод Выбрать(), программный обход через СправочникиМенеджер или получение ссылок без загрузки самих объектов.
Ключевой момент, который нужно понять сразу: «все объекты» и «все ссылки» — не одно и то же по производительности. Ссылка — это лёгкий указатель на элемент, а объект — полная загрузка данных элемента в память. Для перебора тысяч элементов правильный выбор инструмента определяет, выполнится операция за секунды или за минуты.
Материал ориентирован на встроенный язык 1С:Предприятие 8.3. Примеры работают как в толстом, так и в тонком клиенте, на сервере и в фоновых заданиях. Отдельно разобраны варианты для иерархических справочников, отборов и обхода помеченных на удаление элементов.
Какие способы получить элементы справочника существуют
В платформе 1С есть четыре основных подхода к получению всех элементов справочника. Первый — запрос на встроенном языке запросов: он возвращает таблицу данных и оптимален для чтения. Второй — метод Выбрать() менеджера справочника, который формирует выборку для последовательного обхода. Третий — получение таблицы через СКД или динамический список, что удобно для вывода пользователю. Четвёртый — обменные механизмы (планы обмена, выгрузка в XML), когда нужна не просто выборка, а передача данных.
Выбор зависит от сценария. Если нужно прочитать данные — используйте запрос, это самый производительный путь. Если нужно изменить каждый элемент — подойдёт Выбрать() с последующим ПолучитьОбъект(). Если задача — показать список пользователю с отбором и сортировкой — правильнее динамический список формы.
Сравнение способов
Самый быстрый способ чтения. Подходит для отчётов, выгрузок, проверок. Не позволяет напрямую изменять элементы.
Удобен для последовательной обработки с изменением элементов. Медленнее запроса на больших объёмах.
Для отображения пользователю с отборами и сортировкой. Не предназначен для пакетной обработки в коде.
Нужен только при изменении данных. На больших справочниках без необходимости — грубая ошибка производительности.
Получение всех элементов запросом
Запрос — основной и рекомендуемый способ. Минимальный вариант выглядит так:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Код КАК Код,
| Номенклатура.Наименование КАК Наименование
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Наименование);
КонецЦикла;
Такой запрос вернёт все элементы, включая помеченные на удаление. Если помеченные не нужны, добавьте условие ГДЕ НЕ Номенклатура.ПометкаУдаления. Для иерархических справочников часто исключают группы условием ГДЕ НЕ Номенклатура.ЭтоГруппа — но только если вид иерархии справочника «иерархия групп и элементов».
Если нужна таблица значений для дальнейшей работы, используйте Результат.Выгрузить() вместо обхода выборки. Это удобно для передачи в табличное поле или построения отчёта.
Перебор элементов через метод Выбрать()
Метод Выбрать() менеджера справочника создаёт выборку, которую можно обходить в цикле. Он принимает параметры: отбор, порядок и родителя для иерархических справочников.
Выборка = Справочники.Контрагенты.Выбрать();
Пока Выборка.Следующий() Цикл
Если Выборка.ЭтоГруппа Тогда
Продолжить;
КонецЕсли;
Сообщить(Выборка.Наименование);
КонецЦикла;
Обратите внимание: элементы выборки — это объекты типа СправочникВыборка, они уже содержат основные реквизиты, и вызывать ПолучитьОбъект() для чтения не нужно. ПолучитьОбъект() требуется только для записи изменений:
Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
Объект = Выборка.ПолучитьОбъект();
Объект.Комментарий = "Обработано";
Объект.Записать();
КонецЦикла;
Такой код на справочнике в десятки тысяч элементов будет работать долго и нагружать сервер. Для массовых изменений лучше сначала запросом отобрать только нужные ссылки, а затем изменять именно их.
Отбор элементов по условию
Редко нужны действительно все элементы — чаще требуется подмножество. В запросе отбор задаётся секцией ГДЕ с параметрами:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Контрагенты.Ссылка КАК Ссылка
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|ГДЕ
| НЕ Контрагенты.ПометкаУдаления
| И Контрагенты.Родитель = &Родитель";
Запрос.УстановитьПараметр("Родитель", НужнаяГруппа);
Выборка = Запрос.Выполнить().Выбрать();
В методе Выбрать() отбор передаётся структурой, но с ограничением: отбирать можно только по реквизитам, для которых в конфигураторе включена индексация (или по стандартным полям вроде Родитель и Владелец). Попытка отбора по неиндексированному реквизиту вызовет ошибку.
Отбор = Новый Структура;
Отбор.Вставить("Владелец", ОрганизацияСсылка);
Выборка = Справочники.ДоговорыКонтрагентов.Выбрать(, , Отбор);
Особенности иерархических и подчинённых справочников
Иерархический справочник можно обойти целиком одним запросом, а можно рекурсивно — по уровням. Для получения элементов конкретной группы со всеми вложенными подгруппами в запросе используется оператор В ИЕРАРХИИ:
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка В ИЕРАРХИИ(&Группа)
| И НЕ Номенклатура.ЭтоГруппа";
Запрос.УстановитьПараметр("Группа", ГруппаНоменклатуры);
Для подчинённых справочников (например, договоры, подчинённые контрагентам) все элементы получают либо запросом без условий, либо выборкой с отбором по владельцу. Помните, что элемент подчинённого справочника не существует осмысленно без владельца — при выгрузке обычно требуется выгружать и ссылку на владельца.
- 1Определите цель: чтение данных, изменение элементов или вывод пользователю.
- 2Для чтения составьте запрос с нужными полями и условиями (пометка удаления, группы, иерархия).
- 3Выполните запрос и обойдите выборку или выгрузите результат в таблицу значений.
- 4Для изменения элементов получайте объект только внутри цикла и только для отобранных ссылок.
- 5Проверьте результат: количество обработанных элементов, отсутствие помеченных на удаление и групп там, где их быть не должно.
Производительность и ограничения на больших объёмах
На справочниках в сотни тысяч элементов разница между подходами становится критичной. Запрос с выборкой нескольких полей выполняется на уровне СУБД и передаёт в память только результат. Метод Выбрать() с ПолучитьОбъект() в цикле выполняет отдельное чтение на каждый элемент — это самый медленный сценарий.
Для очень больших выгрузок разбивайте обработку на порции: например, обрабатывайте элементы пачками по несколько тысяч, выбирая их с ограничением и смещением или по диапазону кодов. В фоновых заданиях это также позволяет отслеживать прогресс и не блокировать сеанс надолго.
Отдельное ограничение — права доступа. Запрос без ключевого слова РАЗРЕШЕННЫЕ вернёт ошибку, если у пользователя нет прав на часть данных. В регламентных операциях код обычно выполняется в привилегированном режиме, но в пользовательских обработках добавляйте РАЗРЕШЕННЫЕ, чтобы получать только доступные элементы.
Как проверить результат
Совпадает с числом элементов в списке справочника (с учётом отборов по пометке удаления и группам)
Меньше ожидаемого без явных отборов — проверьте права и условия запроса
Нет помеченных на удаление и групп, если они исключались
Присутствуют группы или удалённые элементы — условие ГДЕ не сработало
Запрос на чтение выполняется за секунды даже на крупном справочнике
Минуты выполнения — вероятно, в цикле вызывается ПолучитьОбъект() без необходимости
Проверка результата и типичные ошибки
После получения выборки полезно убедиться, что результат соответствует ожиданиям. Простейшая проверка — сравнить количество строк результата с количеством элементов, видимых в форме списка справочника при аналогичных отборах. Расхождение обычно означает лишнее или недостающее условие в запросе.
Частая ошибка новичков — обращение к реквизиту через точку от ссылки в цикле: Выборка.Ссылка.СтавкаНДС. Если реквизит не выбран в запросе, каждое такое обращение — отдельный запрос к базе. Правильно — добавить нужный реквизит в список полей запроса один раз.
Ещё одна проблема — обход выборки внутри транзакции с записью: длинная транзакция держит блокировки и мешает другим пользователям. Безопасный шаблон — сначала запросом получить все ссылки, затем обрабатывать их порциями, фиксируя транзакцию на каждой порции.
Что важно запомнить
Для чтения всех элементов справочника используйте запрос — это быстро и безопасно. Выбрать() применяйте для последовательной обработки, а ПолучитьОбъект() — только когда элемент нужно изменить. Всегда явно решайте, нужны ли помеченные на удаление и группы, и проверяйте результат по количеству и составу выборки.
Частые вопросы
Как получить количество элементов справочника без их перебора?
Запросом с агрегатной функцией: «ВЫБРАТЬ КОЛИЧЕСТВО(Ссылка) КАК Количество ИЗ Справочник.Номенклатура». Это выполняется на уровне СУБД и не требует обхода элементов. Добавьте условие ГДЕ, если нужно исключить помеченные на удаление или группы.
Как получить только элементы, не помеченные на удаление?
Добавьте в запрос условие «ГДЕ НЕ Справочник.ПометкаУдаления». В методе Выбрать() отдельного параметра для этого нет — фильтруйте внутри цикла проверкой свойства ПометкаУдаления выборки или используйте запрос.
Чем отличается Выбрать() от ВыбратьИерархически()?
Выбрать() возвращает элементы одного уровня (по умолчанию — всего справочника без учёта структуры), а ВыбратьИерархически() обходит дерево с учётом родителей: сначала группа, затем её содержимое. Для плоской обработки разницы в результате почти нет, для вывода дерева нужен именно иерархический обход.
Как получить элементы справочника, подчинённого другому справочнику?
Отберите по владельцу: в запросе условие «ГДЕ Договоры.Владелец = &Контрагент», в Выбрать() — структура отбора с ключом Владелец. Поле Владелец стандартное и индексированное, поэтому такой отбор работает быстро.
Почему запрос возвращает меньше элементов, чем видно в списке?
Наиболее вероятные причины: у пользователя ограничены права на уровне записей (RLS) — тогда часть строк отсекается; в запросе стоит лишнее условие; либо в списке отображаются помеченные на удаление, а запрос их исключает. Проверьте запрос в консоли запросов под полными правами.
Можно ли получить все объекты справочника без запроса и Выбрать()?
Да, например через динамический список формы или выгрузку в XML через планы обмена и стандартную сериализацию. Но для программной обработки в коде запрос и Выбрать() — стандартные и самые управляемые инструменты; экзотические способы оправданы только в специфических задачах интеграции.