Как программно получить цену номенклатуры в 1С:Бухгалтерии 3.0 на управляемых формах?

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет Торговля и дистрибуция
← На главную

Разработка внешних печатных форм, ценников и этикеток в среде 1С:Предприятие 8 — одна из самых частых задач, с которой сталкиваются начинающие разработчики и системные администраторы. При работе с конфигурацией «1С:Бухгалтерия предприятия 8, редакция 3.0» на управляемых формах многие сталкиваются с трудностью: как вывести цену конкретного товара на печать? Прямое обращение через точку к реквизитам номенклатуры (например, НоменклатураСсылка.Цена) вызывает ошибку системы «Поле объекта не обнаружено».

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

Почему нельзя получить цену напрямую из номенклатуры?

Давайте проанализируем архитектуру хранения данных в 1С. Справочник Номенклатура содержит только постоянные характеристики товара: наименование, артикул, единицу измерения, ставку НДС и текстовое описание. Однако цена — это динамический показатель. Сегодня товар стоит 250 рублей, завтра на него действует скидка, а через месяц цена увеличивается из-за инфляции.

Если бы цена хранилась непосредственно внутри карточки номенклатуры, система не смогла бы хранить историю изменений цен. Поэтому в решениях на платформе 1С:Предприятие цены всегда выносятся в отдельную таблицу — периодический регистр сведений. В 1С:Бухгалтерии 3.0 этот регистр называется ЦеныНоменклатуры.

Чтобы получить цену на определенную дату (например, на сегодня или на дату создания документа), нам нужно обратиться к этому регистру сведений и выполнить так называемый «срез последних» по нужному товару и типу цен.

Ниже мы рассмотрим два основных метода решения этой задачи: использование стандартного общего модуля конфигурации и написание оптимального SQL-подобного запроса.

---

Способ 1. Использование типового общего модуля «Ценообразование»

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

Давайте разберем параметры этой функции:

  1. Номенклатура — Ссылка на элемент справочника Номенклатура, для которого мы хотим узнать цену.
  2. ТипЦен — Ссылка на элемент справочника ТипыЦенНоменклатуры (например, «Розничная», «Оптовая» или «Закупочная»).
  3. Дата — Дата, на которую запрашивается цена (обычно это текущая дата или дата документа).
  4. Валюта — Валюта, в которой нужно вернуть цену (необязательный параметр).

Рассмотрим пример кода, который мы можем использовать в нашей внешней обработке печати этикеток для получения розничной цены товара:


// 1. Сначала определим ссылку на номенклатуру (товар)
НоменклатураСсылка = Шапка.ОС; // Замените на фактический путь к вашей номенклатуре

// 2. Найдем нужный тип цен в справочнике
ТипЦенСсылка = Справочники.ТипыЦенНоменклатуры.НайтиПоНаименованию("Розничная");

Если ЗначениеЗаполнено(ТипЦенСсылка) Тогда
    
    // 3. Вызываем функцию общего модуля для получения числового значения цены
    АктуальнаяДата = ТекущаяДата();
    ЦенаЧислом = Ценообразование.ПолучитьЦенуНоменклатуры(НоменклатураСсылка, ТипЦенСсылка, АктуальнаяДата);
    
    // 4. Форматируем числовое значение в красивую строку (например, 250,00)
    СтрокаЦены = Формат(ЦенаЧислом, "ЧЦ=15; ЧДЦ=2; ЧГ=0");
    
    // 5. Выводим результат в параметр макета нашей этикетки
    Область.Параметры.Артикул = "Артикул: " + СокрЛП(НоменклатураСсылка.Артикул) + ", " 
                                + СокрЛП(НоменклатураСсылка.Наименование) + Символы.ПС 
                                + "Цена: " + СтрокаЦены + " руб. за " + СокрЛП(НоменклатураСсылка.ЕдиницаИзмерения);
Иначе
    ВызватьИсключение "В системе не найден тип цен с наименованием 'Розничная'!";
КонецЕсли;

Этот способ идеален, если вы печатаете этикетку для одного конкретного товара из формы или карточки номенклатуры. Метод гарантирует, что цена будет получена с учетом всех внутренних валютных пересчетов и правил конфигурации.

---

Способ 2. Оптимальное получение цен с помощью запроса

Если вам необходимо распечатать этикетки или ценники сразу для большого списка товаров (например, из табличной части документа «Поступление товаров и услуг» или «Реализация»), использование первого способа в цикле крайне нежелательно. Это приведет к отправке множества мелких одиночных запросов к базе данных, что существенно замедлит работу программы (так называемая проблема N+1 запросов).

В сценариях пакетной печати правильным решением будет написание одного общего запроса к виртуальной таблице СрезПоследних регистра сведений ЦеныНоменклатуры.

Давайте пошагово реализуем этот алгоритм. Сначала напишем функцию на сервере, которая принимает ссылку на номенклатуру и возвращает числовое значение цены:


&НаСервере
Функция ПолучитьЦенуТовараЗапросом(ТоварСсылка, ДатаСреза) Экспорт

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

    // Ищем необходимый тип цен в базе данных
    РозничныйТипЦен = Справочники.ТипыЦенНоменклатуры.НайтиПоНаименованию("Розничная");

    Запрос.УстановитьПараметр("Номенклатура", ТоварСсылка);
    Запрос.УстановитьПараметр("ТипЦен", РозничныйТипЦен);
    Запрос.УстановитьПараметр("ДатаСреза", ДатаСреза);

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

    Если Выборка.Следующий() Тогда
        Возврат Выборка.Цена;
    КонецЕсли;

    Возврат 0; // Возвращаем ноль, если цена на указанную дату не установлена

КонецФункции

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


НоменклатураСсылка = Шапка.ОС; // Получаем ссылку на товар
РабочаяДата = ТекущаяДата();  // Устанавливаем дату среза цен

// Вызываем нашу функцию получения цены
ЦенаЧислом = ПолучитьЦенуТовараЗапросом(НоменклатураСсылка, РабочаяДата);

// Выполняем красивое форматирование цены и единицы измерения
СтрокаЦены = Формат(ЦенаЧислом, "ЧЦ=15; ЧДЦ=2; ЧГ=0");
ЕдиницаИзмерения = ?(ЗначениеЗаполнено(НоменклатураСсылка.ЕдиницаИзмерения), 
                     " за " + СокрЛП(НоменклатураСсылка.ЕдиницаИзмерения), 
                     "");

// Заполняем область макета данными
Область.Параметры.Артикул = "Артикул: " + СокрЛП(НоменклатураСсылка.Aртикул) + ", " 
                            + СокрЛП(НоменклатураСсылка.Наименование) + Символы.ПС 
                            + "Цена: " + СтрокаЦены + " руб." + ЕдиницаИзмерения;

---

Полезные советы при работе с ценами в печатных формах

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

  1. Всегда форматируйте числовые значения. Если цена товара составляет ровно 250 рублей, то без явного преобразования функция СокрЛП() превратит её в строку "250". На ценнике это выглядит некрасиво. Используйте функцию Формат(Цена, "ЧДЦ=2"), чтобы гарантировать отображение копеек: "250,00".
  2. Проверяйте заполнение типа цен. Если в вашей базе данных тип цен называется не "Розничная", а, например, "Розничные цены", поиск по точному наименованию вернет пустую ссылку. Сделайте вывод предупреждения пользователю, если тип цен в системе не обнаружен.
  3. Обрабатывайте нулевые цены. Если для какого-то товара забыли установить цену в программе, на ценнике отобразится "Цена: 0,00 руб.". Рекомендуется добавить проверку: если цена равна 0, выводить вместо нее текст "Цена не установлена" или временно скрывать ценник от печати.
  4. Динамически выводите единицу измерения. Избегайте жесткого написания текста "за шт" в коде. Разные товары могут продаваться в метрах, килограммах или литрах. Получайте единицу измерения динамически через реквизит номенклатуры Номенклатура.ЕдиницаИзмерения.

Используя предложенные методики, вы сможете легко автоматизировать вывод актуальных цен в любые внешние обработки печати в конфигурации 1С:Бухгалтерия 3.0 на управляемых формах.

← На главную