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