При разработке печатных форм в 1С программисты часто сталкиваются с ситуацией, когда данные для вывода (например, розничная цена) отсутствуют в табличной части документа. В этом случае информацию необходимо получать из регистров сведений. Однако на этом пути новичков подстерегает множество ловушек: от неоптимальных запросов до банальных ошибок в оформлении макета. Разберем детально, как решить эту задачу правильно и эффективно.
Рассмотрим ситуацию: разработчик пытается получить цену через запрос к виртуальной таблице СрезПоследних, но данные не отображаются в табличном документе. Основная ошибка часто кроется в неправильной передаче параметров и неверном обращении к метаданным. Проанализируем типичный пример кода с ошибками:
// Ошибочный подход
ТекстЗапроса = "ВЫБРАТЬ Цена ИЗ РегистрСведений.ЦеныНоменклатуры.СрезПоследних Где Номенклатура = &Номенклатура и ТипЦен = &ТипЦен";
Запрос.УстановитьПараметр("ТипЦен", Справочники.Номенклатура.НайтиПоНаименованию("Розничная"));
В данном примере допущены две критические ошибки. Во-первых, условия в виртуальных таблицах крайне желательно передавать в параметры самой таблицы, а не в секцию ГДЕ. Во-вторых, поиск типа цен ведется в справочнике Номенклатура, хотя типы цен обычно хранятся в справочнике ТипыЦенНоменклатуры.
Для корректного получения цены нам необходимо использовать параметры виртуальной таблицы СрезПоследних. Это позволит платформе сразу отсечь ненужные записи на уровне СУБД. Выясним причину, почему это важно: использование секции ГДЕ после получения среза может привести к тому, что система сначала получит последние цены для всех товаров, а потом начнет их фильтровать, что крайне непроизводительно.
Рассмотрим правильный вариант запроса:
ТекстЗапроса =
"ВЫБРАТЬ
| ЦеныНоменклатурыСрезПоследних.Цена КАК Цена
|ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&ДатаСреза, Номенклатура = &Номенклатура И ТипЦен = &ТипЦен) КАК ЦеныНоменклатурыСрезПоследних";
Запрос = Новый Запрос(ТекстЗапроса);
Запрос.УстановитьПараметр("ДатаСреза", ТекущаяДата()); // Или дата документа
Запрос.УстановитьПараметр("Номенклатура", СсылкаНаТовар);
Запрос.УстановитьПараметр("ТипЦен", Справочники.ТипыЦенНоменклатуры.НайтиПоНаименованию("Розничная"));
РезультатЗапроса = Запрос.Выполнить();
Если запрос возвращает данные (это можно проверить в отладчике, посмотрев РезультатЗапроса.Пустой()), но в печатной форме все равно пусто, проблему нужно искать в макете. Проанализируем основные моменты:
ЦенаТовара) полностью совпадает с тем, что вы пишете в коде: Область.Параметры.ЦенаТовара = .... Регистр букв имеет значение.Одной из самых грубых ошибок является выполнение запроса к ценам внутри цикла обхода строк документа. Если в документе 100 строк, программа сделает 100 обращений к базе данных, что существенно замедлит печать. Разберем, как сделать это правильно с помощью пакетной выборки или условия В ИЕРАРХИИ.
Рассмотрим алгоритм эффективного получения цен:
Соответствие для быстрого доступа.Пример кода для массового получения цен:
// Собираем массив уникальных ссылок номенклатуры
МассивНоменклатуры = СсылкаНаОбъект.Товары.ВыгрузитьКолонку("Номенклатура");
ОбщегоНазначенияКлиентСервер.СвернутьМассив(МассивНоменклатуры);
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Цены.Номенклатура КАК Номенклатура,
| Цены.Цена КАК Цена
|ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Дата, Номенклатура В (&МассивНоменклатуры) И ТипЦен = &ТипЦен) КАК Цены";
Запрос.УстановитьПараметр("Дата", СсылкаНаОбъект.Дата);
Запрос.УстановитьПараметр("МассивНоменклатуры", МассивНоменклатуры);
Запрос.УстановитьПараметр("ТипЦен", НужныйТипЦен);
// Выгружаем в соответствие для удобного поиска в цикле
ТаблицаЦен = Запрос.Выполнить().Выгрузить();
СоответствиеЦен = Новый Соответствие;
Для Каждого Стр Из ТаблицаЦен Цикл
СоответствиеЦен.Вставить(Стр.Номенклатура, Стр.Цена);
КонецЦикла;
Теперь при выводе строк макета достаточно просто обратиться к соответствию: Область.Параметры.Цена = СоответствиеЦен[ТекущаяСтрока.Номенклатура];. Это в десятки раз быстрее, чем одиночные запросы.
В современных конфигурациях 1С (УТ 11, ERP, КА) цена часто зависит не только от номенклатуры, но и от характеристики. Если вы не укажете характеристику в параметрах виртуальной таблицы, запрос может вернуть несколько цен или не вернуть ни одной. Всегда проверяйте, ведется ли в базе учет по характеристикам.
Также важно красиво оформить числовое значение цены. Используем функцию Формат(), чтобы цена выглядела профессионально (с двумя знаками после запятой и разделителем тысяч):
Область.Параметры.Цена = Формат(ЗначениеЦены, "ЧЦ=15; ЧДЦ=2; ЧРГ=' '");
Если цена не выводится, пройдите по шагам:
Ссылку, а не сам Объект?НайтиПоНаименованию) вообще что-то возвращает. Помните, что поиск по строке ненадежен — лучше использовать предопределенные элементы или настройки.Поход.Количество()).&Дата) цены действительно установлены в регистре.Следуя этим рекомендациям, мы не только решим задачу вывода цены, но и обеспечим высокую скорость работы нашей программы.