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

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

Как получить все элементы справочника в 1С

Способы получить все элементы справочника 1С: Выбрать(), запрос, ВыбратьИерархически(). Примеры кода, обход групп, отбор, типичные ошибки и проверка результата.

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

Выбор способа влияет на производительность и корректность результата. Например, выборка через Выбрать() удобна для простого перебора, а запрос — когда нужны отборы, сортировка и соединения с другими таблицами. Ошибка в выборе механизма на больших справочниках приводит к заметному замедлению работы.

Ниже разобраны основные способы получения элементов справочника на встроенном языке 1С, особенности работы с иерархическими справочниками, отборы и типичные ошибки, которые допускают разработчики.

Способ 1. Получение элементов через метод Выбрать()

Самый простой способ перебрать все элементы справочника — метод Выбрать() менеджера справочника. Он возвращает объект типа «Выборка из справочника», который обходится в цикле методом Следующий(). Каждая итерация даёт ссылку на элемент, а реквизиты доступны через точку.

Выборка = Справочники.Номенклатура.Выбрать();

Пока Выборка.Следующий() Цикл

Сообщить("Элемент: " + Выборка.Наименование + ", ссылка: " + Выборка.Ссылка);

КонецЦикла;

Метод Выбрать() принимает три необязательных параметра: родитель (для иерархических справочников), владелец (для подчинённых) и отбор (структура с условиями по реквизитам). Если параметры не указаны, выбираются все элементы верхнего уровня — для неиерархического справочника это и есть все элементы.

Важная особенность: выборка читает данные порциями по мере обхода, поэтому она экономична по памяти. Однако обращение к реквизитам через точку внутри цикла может порождать дополнительные обращения к базе, если реквизит не входит в выборку. Для массовых обработок лучше получать объект методом ПолучитьОбъект() только там, где нужно изменение данных.

Способ 2. Получение элементов запросом

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

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

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

"ВЫБРАТЬ

| Номенклатура.Ссылка КАК Ссылка,

| Номенклатура.Наименование КАК Наименование

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|ГДЕ

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

|УПОРЯДОЧИТЬ ПО

| Наименование";

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

Пока Результат.Следующий() Цикл

Сообщить(Результат.Наименование);

КонецЦикла;

Обратите внимание на условие НЕ ПометкаУдаления. Запрос по умолчанию возвращает и помеченные на удаление элементы — это частая причина «лишних» строк в обработках. Метод Выбрать() также возвращает помеченные элементы, если отдельно не задать отбор.

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

Сравнение способов получения элементов

Выбрать()

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

Запрос

Сложные отборы, сортировка, соединения, итоги. Требует написания текста запроса, но быстрее на больших объёмах.

ВыбратьИерархически()

Обход иерархии в порядке дерева групп. Подходит только для иерархических справочников.

Способ 3. Обход иерархического справочника

Для иерархических справочников (например, «Номенклатура» с группами товаров) обычный Выбрать() без параметров вернёт только элементы верхнего уровня. Чтобы получить все элементы с учётом вложенности, есть два подхода.

Первый — метод ВыбратьИерархически(). Он обходит справочник в порядке иерархии: сначала группа, затем её элементы и подгруппы. Внутри цикла признак группы проверяется свойством ЭтоГруппа.

Выборка = Справочники.Номенклатура.ВыбратьИерархически();

Пока Выборка.Следующий() Цикл

Если Выборка.ЭтоГруппа Тогда

Продолжить; // пропускаем группы, нужны только элементы

КонецЕсли;

Сообщить(Выборка.Наименование);

КонецЦикла;

Второй подход — запрос с условием ЭтоГруппа = ЛОЖЬ либо соединение с таблицей иерархии. Если нужны элементы конкретной группы с учётом всех вложенных подгрупп, в запросе используют оператор В ИЕРАРХИИ:

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

"ВЫБРАТЬ Ссылка, Наименование

|ИЗ Справочник.Номенклатура

|ГДЕ Ссылка В ИЕРАРХИИ(&Группа) И НЕ ЭтоГруппа";

Запрос.УстановитьПараметр("Группа", ГруппаОтбора);

Отбор и фильтрация элементов

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

Отбор = Новый Структура;

Отбор.Вставить("Владелец", КонтрагентСсылка);

Выборка = Справочники.ДоговорыКонтрагентов.Выбрать(, КонтрагентСсылка);

Для подчинённых справочников (например, «Договоры контрагентов») все элементы конкретного владельца получают передачей владельца вторым параметром Выбрать() или условием Владелец = &Владелец в запросе. Это стандартный способ получить, например, все договоры одного контрагента или все единицы измерения одной номенклатурной позиции.

Если условия сложнее равенства — диапазоны, «содержит», «не равно», несколько условий «ИЛИ» — используйте только запрос. Попытка выбрать всё через Выбрать() и фильтровать в цикле на большом справочнике приводит к чтению лишних данных и замедлению обработки.

Порядок действий при выборе способа
  1. 1
    Определите, иерархический ли справочник и нужны ли группы в результате
  2. 2
    Если нужен простой перебор без условий — используйте Выбрать() или ВыбратьИерархически()
  3. 3
    Если нужны отборы, сортировка или соединения — напишите запрос
  4. 4
    Добавьте условие на ПометкаУдаления, если помеченные элементы не нужны
  5. 5
    Проверьте результат на тестовой базе: количество элементов и корректность отбора

Изменение элементов при обходе

Частая задача — не просто прочитать, а изменить все элементы справочника: заполнить новый реквизит, переназначить группу, обновить наименования. В этом случае для каждого элемента получают объект методом ПолучитьОбъект(), изменяют и записывают.

Выборка = Справочники.Номенклатура.Выбрать();

Пока Выборка.Следующий() Цикл

Если Выборка.ЭтоГруппа Тогда

Продолжить;

КонецЕсли;

Объект = Выборка.Ссылка.ПолучитьОбъект();

Объект.Комментарий = "Обработано";

Объект.Записать();

КонецЦикла;

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

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

Типичные ошибки и проверка результата

Разработчики при получении элементов справочника регулярно сталкиваются с одними и теми же проблемами. Знание их заранее экономит время отладки.

Типичные ошибки
01
Обход Выбрать() без параметров в иерархическом справочнике — получены только элементы верхнего уровня, вложенные потеряны
02
Отсутствие отбора по ПометкаУдаления — в результат попадают помеченные на удаление элементы
03
Вызов ПолучитьОбъект() для чтения данных — лишняя нагрузка, объект нужен только для изменения
04
Фильтрация в цикле вместо условий запроса — читаются лишние данные, обработка работает медленно
05
Изменение данных справочника внутри цикла обхода той же выборки без учёта повторного чтения — возможны пропуски или зацикливание

Отдельно стоит упомянуть права доступа. Если обработка выполняется под пользователем с ограниченными правами, выборка может вернуть не все элементы из-за RLS (ограничения доступа на уровне записей). Для административных обработок, где нужны гарантированно все данные, код выполняют в привилегированном модуле или используют УстановитьПривилегированныйРежим(Истина).

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

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

Количество полученных элементов
Норма

Совпадает с количеством в списке справочника с теми же отборами

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

Меньше ожидаемого — проверьте иерархию, отборы и права доступа

Помеченные на удаление
Норма

Исключены, если не нужны, либо осознанно включены

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

Помеченные элементы попадают в обработку и отчёты

Скорость выполнения
Норма

Обработка справочника завершается за приемлемое время

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

Заметные паузы — вероятно, ПолучитьОбъект() или запрос в цикле

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

Чем отличается Выбрать() от ВыбратьИерархически()?

Метод Выбрать() без параметров возвращает элементы одного уровня (по умолчанию — верхнего). ВыбратьИерархически() обходит весь справочник в порядке дерева: группы и их содержимое с учётом вложенности. Для неиерархического справочника разницы нет.

Как получить только элементы без групп?

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

Почему выборка возвращает больше элементов, чем видно в списке справочника?

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

Что быстрее: Выбрать() или запрос?

Для простого полного перебора разница невелика. Запрос выигрывает при отборах, сортировке и соединениях, так как всё выполняется одним обращением к СУБД. Выборка удобнее, когда не нужно заранее загружать весь результат в память.

Как получить все элементы подчинённого справочника по владельцу?

Передайте ссылку владельца вторым параметром: Справочники.Договоры.Выбрать(, ВладелецСсылка). Либо используйте запрос с условием «Владелец = &Владелец». Без указания владельца будут выбраны элементы всех владельцев.

Можно ли получить элементы справочника без программирования?

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

Итог

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

Простой перебор — Выбрать() с циклом Пока Следующий(). Иерархия — ВыбратьИерархически() или условие В ИЕРАРХИИ в запросе. Отборы и сортировка — запрос. Всегда учитывайте ПометкаУдаления, признак ЭтоГруппа и права доступа, а массовую запись выполняйте только после резервного копирования.