Как вывести дополнительные реквизиты веса номенклатуры во внешнюю печатную форму

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

При разработке внешних печатных форм, таких как Товарно-транспортная накладная (ТТН), часто возникает необходимость вывода специфических данных, которые не хранятся в основных реквизитах справочника Номенклатура. В современных редакциях 1С (например, Бухгалтерия 2.0 или 3.0) для этого используются дополнительные реквизиты. Рассмотрим подробнее, как правильно извлечь эти данные и интегрировать их в алгоритм печати, избегая типичных ошибок производительности.

Постановка задачи и анализ структуры данных

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

Проанализируем, где могут храниться дополнительные реквизиты в зависимости от версии конфигурации:

  1. Табличная часть ДополнительныеРеквизиты — характерна для конфигураций на базе БСП (Библиотеки стандартных подсистем).
  2. Регистр сведений ЗначенияСвойствОбъектов — использовался в более старых редакциях (например, в оригинальной 1С:Бухгалтерия 2.0 до перехода на механизмы БСП).

Вариант 1. Оптимальный метод извлечения данных через запрос

Выясним причину, почему прямое обращение к полю в запросе через точку (например, Номенклатура.ДополнительныеРеквизиты.Значение) не работает корректно. Поскольку ДополнительныеРеквизиты — это табличная часть, обращение к ней возвращает коллекцию, а не конкретное значение. Чтобы получить значение определенного свойства, нам необходимо использовать Левое соединение.

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


Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|	РеализацияТовары.Номенклатура КАК Номенклатура,
|	РеализацияТовары.Количество КАК Количество,
|	РеализацияТовары.Коэффициент КАК КоэффициентСтроки,
|	ЕСТЬNULL(НоменклатураВес.Значение, 0) КАК ВесЧислом
|ИЗ
|	Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТовары
|		ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК НоменклатураВес
|		ПО РеализацияТовары.Номенклатура = НоменклатураВес.Ссылка
|			И НоменклатураВес.Свойство = &ПараметрВес
|ГДЕ
|	РеализацияТовары.Ссылка = &ТекущийДокумент";

// Важно правильно найти ссылку на само свойство
СвойствоВес = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Вес");
Запрос.УстановитьПараметр("ПараметрВес", СвойствоВес);
Запрос.УстановитьПараметр("ТекущийДокумент", СсылкаНаДокумент);

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

В этом примере мы используем ЛЕВОЕ СОЕДИНЕНИЕ. Условие связи включает не только ссылку на номенклатуру, но и фильтр по конкретному свойству. Использование функции ЕСТЬNULL позволяет избежать ошибок, если для какой-то позиции номенклатуры вес не был указан — в этом случае в результат попадет 0.

Вариант 2. Работа с данными через объектную модель (для небольших документов)

Если по каким-то причинам использование сложного запроса затруднено, можно воспользоваться методом поиска в табличной части объекта. Однако проанализируем ситуацию: этот метод является менее производительным. Если в документе сотни строк, выполнение метода Найти() в цикле приведет к существенным задержкам, так как при каждом обращении к Выборка.Номенклатура.ДополнительныеРеквизиты система может подгружать объект из базы данных.

Рассмотрим пример кода, который часто используют начинающие разработчики:


// Внутри цикла обхода строк документа
ДопСвойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Вес");
СтрокаВеса = ВыборкаСтрок.Номенклатура.ДополнительныеРеквизиты.Найти(ДопСвойство, "Свойство");

Если СтрокаВеса <> Неопределено Тогда
    ВесЕдиницы = СтрокаВеса.Значение;
Иначе
    ВесЕдиницы = 0;
КонецЕсли;

ОбластьМакета.Параметры.Масса = ВесЕдиницы * ВыборкаСтрок.Количество;

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

Расчет итоговых показателей и учет коэффициентов

Выясним, как правильно рассчитать общую массу. В документе РеализацияТоваровУслуг товар может быть указан в упаковках (например, в ящиках), в то время как вес в дополнительном реквизите обычно указывается для базовой единицы (например, за 1 кг или 1 штуку). Для корректного расчета нам понадобится реквизит Коэффициент из табличной части документа.

Рассмотрим формулу расчета:

ИтоговаяМасса = ВесИзРеквизита * Количество * Коэффициент

Проанализируем пример реализации итогов в цикле вывода областей макета:


ИтогоМасса = 0;
Пока Выборка.Следующий() Цикл
    // Получаем вес (предположим, он уже есть в выборке запроса)
    ЗначениеВеса = Выборка.ВесЧислом;
    
    // Рассчитываем массу строки
    МассаСтроки = ЗначениеВеса * Выборка.Количество * Выборка.КоэффициентСтроки;
    
    // Заполняем параметры макета
    ОбластьСтрока.Параметры.Масса = МассаСтроки;
    
    // Суммируем итог
    ИтогоМасса = ИтогоМасса + МассаСтроки;
    
    ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;

// Вывод подвала с итогами
ОбластьПодвал.Параметры.ВсегоМасса = ИтогоМасса;
ТабДок.Вывести(ОбластьПодвал);

Типичные ошибки и способы их исправления

При работе с дополнительными реквизитами разработчики часто сталкиваются со следующими проблемами:

  1. Ошибка «Ожидается имя таблицы» в запросе. Появляется, если вы пытаетесь обратиться к ДополнительныеРеквизиты, но в вашей версии конфигурации данные хранятся в регистре сведений. В этом случае вместо табличной части справочника в соединении нужно использовать РегистрСведений.ЗначенияСвойствОбъектов.
  2. Тип значения «Произвольный». Дополнительные реквизиты имеют составной тип данных. Если вы планируете выполнять арифметические операции прямо в запросе, используйте конструкцию ВЫРАЗИТЬ(НоменклатураВес.Значение КАК ЧИСЛО(15, 3)). Это гарантирует, что система воспримет данные как число.
  3. Пустые значения (NULL). Если у товара не заполнен доп. реквизит, запрос вернет NULL. Умножение на NULL всегда дает NULL, что приведет к пустоте в печатной форме. Всегда оборачивайте такие поля в функцию ЕСТЬNULL().

Подведем итог: наиболее правильным и быстрым способом является использование ЛЕВОГО СОЕДИНЕНИЯ в основном запросе печатной формы. Это позволяет получить все данные за один раз, корректно обработать пустые значения и выполнить все необходимые математические расчеты без лишней нагрузки на сервер 1С.

← На главную