Как в 1С вывести наименование и цены номенклатуры в строку сообщений?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

В данной статье мы разберем, почему попытки использовать ТаблицуЗначений «в лоб» для получения данных — это не лучший путь, и как правильно реализовать задачу с помощью механизмов запросов.

Анализ типичных ошибок начинающих

Рассмотрим ситуацию, когда разработчик пытается создать ТаблицуЗначений, вручную добавить в нее колонки, соответствующие реквизитам справочника, и затем заполнить ее. Проанализируем основные ошибки в таком подходе:

  1. Неверное обращение к метаданным: Использование конструкций вида ТЗ.Колонки.Добавить(Справочники.Номенклатура) ошибочно. Имя колонки в 1С должно быть строкой (например, "Наименование"), а не ссылкой на объект метаданных.
  2. Проблема производительности (N+1 запрос): Если вы получаете ссылку на объект, а затем в цикле обращаетесь к его свойствам через точку (например, ТекСтрока.Номенклатура.ЦенаПокупки), система выполняет отдельный запрос к базе данных на каждой итерации цикла. Если в справочнике 10 000 позиций, программа выполнит 10 000 лишних обращений к БД, что приведет к зависанию системы.
  3. Место хранения цен: В типовых конфигурациях 1С (УТ, ERP, УНФ) цены редко хранятся прямо в реквизитах справочника Номенклатура. Обычно они находятся в периодических регистрах сведений. Обращение к ним требует специальных механизмов получения «среза последних» данных.

Правильное решение: Использование языка запросов

Единственно верным и эффективным способом получения данных в 1С является объект Запрос. Он позволяет одним обращением к базе данных получить все необходимые поля. Разберем по шагам, как построить такой код.

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


&НаСервере
Процедура ВывестиСписокНоменклатурыНаСервере()
    
    // Создаем новый запрос
    Запрос = Новый Запрос;
    
    // Пишем текст запроса. 
    // Выбираем только элементы, исключая группы (папки), так как у папок нет цен.
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Номенклатура.Наименование КАК Наименование,
        |	Номенклатура.ЦенаЗакупки КАК ЦенаЗакупки,
        |	Номенклатура.ЦенаПродажи КАК ЦенаПродажи
        |ИЗ
        |	Справочник.Номенклатура КАК Номенклатура
        |ГДЕ
        |	НЕ Номенклатура.ЭтоГруппа";
    
    // Выполняем запрос и получаем выборку
    РезультатЗапроса = Запрос.Выполнить();
    Выборка = РезультатЗапроса.Выбрать();
    
    // Обходим результаты в цикле
    Пока Выборка.Следующий() Цикл
        
        // Формируем строку для вывода
        ТекстСообщения = СтрШаблон("%1: Закупка - %2, Продажа - %3", 
                                    Выборка.Наименование, 
                                    Выборка.ЦенаЗакупки, 
                                    Выборка.ЦенаПродажи);
        
        // Выводим в окно сообщений
        Сообщить(ТекстСообщения);
        
    КонецЦикла;

КонецПроцедуры

Разбор работы с иерархией

Если ваша задача — вывести номенклатуру не из всего справочника, а только из конкретной папки (например, «Компьютеры»), нам нужно использовать параметры запроса и оператор В ИЕРАРХИИ. Рассмотрим этот пример подробнее:

Проанализируем ситуацию: нам нужно передать в запрос ссылку на группу. Для этого мы используем метод УстановитьПараметр(). Это защищает код от ошибок и делает его более гибким.


&НаСервере
Процедура ВывестиНоменклатуруПоГруппе(СсылкаНаГруппу)
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Номенклатура.Наименование,
        |	Номенклатура.ЦенаЗакупки
        |ИЗ
        |	Справочник.Номенклатура КАК Номенклатура
        |ГДЕ
        |	Номенклатура.Ссылка В ИЕРАРХИИ(&НужнаяГруппа)
        |	И НЕ Номенклатура.ЭтоГруппа";
    
    Запрос.УстановитьПараметр("НужнаяГруппа", СсылкаНаГруппу);
    
    Выборка = Запрос.Выполнить().Выбрать();
    
    Пока Выборка.Следующий() Цикл
        Сообщить(Выборка.Наименование + " -> " + Строка(Выборка.ЦенаЗакупки));
    КонецЦикла;
    
КонецПроцедуры

Сложный случай: Если цены в регистрах сведений

В реальных задачах «ЦенаПокупки» и «ЦенаПродажи» — это записи в регистре сведений ЦеныНоменклатуры. Чтобы вывести их в одну строку с наименованием, нам потребуется механизм ЛЕВОЕ СОЕДИНЕНИЕ. Это позволяет «подклеить» к каждой строке номенклатуры соответствующие ей значения из таблицы цен.

Выясним причину использования функции ЕСТЬNULL: если для товара цена еще не установлена, запрос вернет пустое значение (NULL). Чтобы при выводе в строку не возникло ошибки, мы заменим NULL на ноль.


// Пример запроса с соединением (схематично)
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Номенклатура.Наименование КАК Товар,
    |	ЕСТЬNULL(ЦеныЗакупки.Цена, 0) КАК ЦенаЗакупа,
    |	ЕСТЬNULL(ЦеныПродажи.Цена, 0) КАК ЦенаРозница
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура
    |		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ВидЦены = &ВидЗакуп) КАК ЦеныЗакупки
    |		ПО Номенклатура.Ссылка = ЦеныЗакупки.Номенклатура
    |		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ВидЦены = &ВидРозница) КАК ЦеныПродажи
    |		ПО Номенклатура.Ссылка = ЦеныПродажи.Номенклатура
    |ГДЕ
    |	НЕ Номенклатура.ЭтоГруппа";

Важные моменты при формировании строк:

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

← На главную