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