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