Как выбрать номенклатуру из определенной группы справочника и заполнить документ в 1С

Программист 1С v8.3 (Обычные формы) Управленческий учет
← На главную

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

Разбор типичной ошибки: Элемент формы vs Значение реквизита

Рассмотрим ситуацию, когда при выполнении запроса система выдает ошибку "Неверные параметры" или сообщает, что переменная не определена. Чаще всего это происходит в обычных формах (платформа 8.2 или 8.3 в режиме совместимости), когда разработчик пытается передать в запрос непосредственно элемент управления с формы.

Проанализируем пример ошибочного кода:

Запрос.УстановитьПараметр("Папка", ЭлементыФормы.ПолеВводаРодитель); // ОШИБКА!

Выясним причину: ЭлементыФормы.ПолеВводаРодитель — это объект типа ПолеВвода, то есть визуальный элемент интерфейса. Запрос же ожидает ссылку на объект базы данных (тип СправочникСсылка.Номенклатура). Чтобы исправить ситуацию, необходимо обращаться либо напрямую к реквизиту объекта, с которым связана форма, либо извлекать значение из элемента управления.

Правильный вариант обращения будет выглядеть так:


// Если ПолеВводаРодитель — это имя реквизита формы:
Запрос.УстановитьПараметр("Папка", ПолеВводаРодитель); 

// Или явное обращение к значению элемента формы:
Запрос.УстановитьПараметр("Папка", ЭлементыФормы.ПолеВводаРодитель.Значение);

Работа с иерархией в запросах: оператор В ИЕРАРХИИ

Для того чтобы выбрать не только элементы, находящиеся непосредственно в указанной папке, но и содержимое всех дочерних подпапок, в языке запросов 1С используется специальный оператор В ИЕРАРХИИ. В отличие от обычного равенства (Родитель = &Папка), этот оператор заставляет систему рекурсивно обходить дерево групп.

Рассмотрим структуру правильного запроса для выбора элементов:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Номенклатура.Ссылка КАК Номенклатура
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |	Номенклатура.Ссылка В ИЕРАРХИИ(&Папка)
    |	И Номенклатура.ЭтоГруппа = ЛОЖЬ";

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

Обратим внимание на важное условие Номенклатура.ЭтоГруппа = ЛОЖЬ. Если его не добавить, запрос вернет в том числе и сами группы (папки), что при заполнении табличной части "Товары" в документе обычно не требуется и может привести к ошибкам проведения.

Заполнение табличной части документа на основе результата запроса

После того как мы получили список нужных товаров, их необходимо добавить в документ. Разберем по шагам наиболее эффективный способ заполнения табличной части (например, Материалы или Товары).

Проанализируем программный цикл добавления строк:


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

Пока Выборка.Следующий() Цикл
    // Добавляем новую строку в табличную часть документа
    НоваяСтрока = Материалы.Добавить();
    
    // Используем универсальный метод заполнения по именам полей
    ЗаполнитьЗначенияСвойств(НоваяСтрока, Выборка);
    
    // Если в запросе поле названо так же, как колонка в ТЧ ("Номенклатура"), 
    // значение перенесется автоматически.
КонецЦикла;

Использование метода ЗаполнитьЗначенияСвойств значительно сокращает код и уменьшает количество ошибок, связанных с опечатками в именах реквизитов.

Продвинутый уровень: Получение остатков по выбранной группе и складу

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

Рассмотрим, как изменить запрос для получения остатков:


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

Запрос.УстановитьПараметр("Папка", ПолеВводаРодитель);
Запрос.УстановитьПараметр("Склад", ВыбранныйСклад);
Запрос.УстановитьПараметр("Период", ТекущаяДата()); // или МоментВремени() документа

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

Важный нюанс: Условие В ИЕРАРХИИ мы помещаем непосредственно в параметры виртуальной таблицы Остатки. Это работает гораздо быстрее, чем если бы мы сначала выбрали все остатки, а потом фильтровали их через ГДЕ в основном теле запроса.

Альтернативный метод: Использование объектной модели

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

Пример использования объектного метода:


Выборка = Справочники.Номенклатура.ВыбратьИерархически(ПолеВводаРодитель);
Пока Выборка.Следующий() Цикл
    Если Выборка.ЭтоГруппа Тогда
        Продолжить;
    КонецЕсли;
    Сообщить("Обработка элемента: " + Выборка.Наименование);
КонецЦикла;

Подведем итоги

Для корректного выбора элементов из группы и заполнения документа следует придерживаться следующих правил:

  1. Всегда проверяйте, что в параметры запроса передается Ссылка, а не элемент управления формы.
  2. Для работы с вложенными папками используйте оператор В ИЕРАРХИИ.
  3. Обязательно фильтруйте результат по полю ЭтоГруппа = ЛОЖЬ, чтобы исключить папки из списка товаров.
  4. Для получения остатков используйте виртуальные таблицы регистров накопления с наложением фильтра по иерархии внутри параметров таблицы.
  5. Для массового копирования данных из выборки в строку документа применяйте ЗаполнитьЗначенияСвойств().

Соблюдение этих рекомендаций позволит вам создавать надежные и быстрые механизмы автоматизации в любых конфигурациях на платформе 1С.

← На главную