При разработке внешних печатных форм для конфигурации «Управление торговлей» редакции 10.3 (работающей на обычных формах платформы 1С:Предприятие 8) программисты часто сталкиваются со следующей проблемой: в макете печатной формы требуется вывести вес номенклатуры и количество транспортных мест, однако в табличной части самого документа (например, РеализацияТоваровУслуг) таких колонок попросту нет. Попытка вызвать стандартный метод Итог() по несуществующим реквизитам приводит к аварийному завершению работы программы.
В этой статье мы подробно разберем внутреннюю архитектуру хранения данных о весах и упаковках в 1С, выясним, почему стандартные механизмы вызывают ошибки, и разработаем надежное решение для вывода этих параметров и подсчета итогов в печатной форме.
Рассмотрим типичную ошибку начинающего разработчика. Пытаясь заполнить параметры макета напрямую из табличной части документа, программист пишет следующий код:
Для Каждого ТекущаяСтрока Из СсылкаНаОбъект.Товары Цикл
ЗаполнитьЗначенияСвойств(ОбластьСтроки.Параметры, ТекущаяСтрока);
// Попытка напрямую обратиться к весу
ОбластьСтроки.Параметры.Вес = ТекущаяСтрока.Вес;
КонецЦикла;
При выполнении этого кода система выдаст ошибку, сообщающую, что поле объекта Вес не обнаружено. Дело в том, что в типовой конфигурации УТ 10.3 вес не хранится физически в строках табличной части документов. Это сделано в целях нормализации базы данных: вес является характеристикой самой номенклатурной позиции (или ее упаковки), а не конкретной сделки.
Проанализируем структуру хранения данных в конфигурации «Управление торговлей 10.3». Вес привязан к конкретной единице измерения номенклатуры.
Номенклатура есть подчиненный справочник ЕдиницыИзмерения.ЕдиницыИзмерения содержится числовой реквизит Вес. Это позволяет задавать разный вес для различных упаковок товара (например, вес штуки, вес коробки, вес паллеты).Товары документа продажи есть реквизит ЕдиницаИзмерения, который ссылается на элемент этого подчиненного справочника.Таким образом, чтобы получить вес единицы товара в строке, нам необходимо обратиться к нему через точку:
ВесЕдиницы = ТекущаяСтрока.ЕдиницаИзмерения.Вес;
Чтобы рассчитать общий вес по строке табличной части, умножим вес единицы на количество проданного товара:
ОбщийВесСтроки = ТекущаяСтрокаКоличество * ТекущаяСтрока.ЕдиницаИзмерения.Вес;
В «Управлении торговлей» реализована сложная, но гибкая система работы с транспортными местами. В одной строке документа могут фигурировать сразу две разные единицы измерения:
ЕдиницаИзмерения.ЕдиницаМест.Если в документе заполнена колонка ЕдиницаМест, количество мест рассчитывается на основании коэффициентов соотношения этих единиц. Формула пересчета выглядит следующим образом:
Количество мест = (Количество * Коэффициент основной единицы) / Коэффициент единицы мест
В коде печатной формы этот расчет реализуется следующим образом:
КолМест = 0;
Если ЗначениеЗаполнено(ТекущаяСтрока.ЕдиницаМест) Тогда
КоэффициентБазовый = ?(ЗначениеЗаполнено(ТекущаяСтрока.ЕдиницаИзмерения), ТекущаяСтрока.ЕдиницаИзмерения.Коэффициент, 1);
КоэффициентМеста = ТекущаяСтрока.ЕдиницаМест.Коэффициент;
Если КоэффициентМеста <> 0 Тогда
КолМест = (ТекущаяСтрока.Количество * КоэффициентБазовый) / КоэффициентМеста;
КонецЕсли;
КонецЕсли;
Если мы попробуем написать код СсылкаНаОбъект.Товары.Итог("Вес"), платформа выдаст ошибку. Метод Итог() работает только с реально существующими в табличной части числовыми колонками. Поскольку вес и количество мест являются динамически вычисляемыми параметрами, у нас есть два пути решения этой проблемы.
Мы объявляем переменные-аккумуляторы перед началом цикла обхода табличной части, на каждой итерации прибавляем к ним вычисленные показатели строки, а в конце выводим накопленные суммы в область подвала макета.
Если логика вашей печатной формы требует многократной сортировки, группировки или вычисления различных итогов, можно выгрузить табличную часть в объект ТаблицаЗначений, программно добавить туда колонки «Вес» и «КоличествоМест», рассчитать их в цикле, а затем спокойно использовать стандартный метод ТЗ.Итог("Вес").
Рассмотрим подробный пример реализации первого (наиболее надежного и быстрого) варианта непосредственно в модуле вашей внешней печатной формы. Этот код полностью готов к интеграции:
Функция ПечатьДокумента() Экспорт
ТабличныйДокумент = Новый ТабличныйДокумент;
ТабличныйДокумент.ИмяПараметровПечати = "ПАРАМЕТРЫ_ПЕЧАТИ_РеализацияТоваровУслуг";
// Получаем макет нашей внешней обработки
МакетОбработки = ПолучитьМакет("Макет");
// Получаем области макета
ОбластьШапка = МакетОбработки.ПолучитьОбласть("Шапка");
ОбластьСтрока = МакетОбработки.ПолучитьОбласть("Строка");
ОбластьПодвал = МакетОбработки.ПолучитьОбласть("Подвал");
// Заполняем шапку печатной формы
ОбластьШапка.Параметры.Заполнить(СсылкаНаОбъект);
ТабличныйДокумент.Вывести(ОбластьШапка);
// Инициализируем переменные для подсчета итогов
ИтоговыйВес = 0;
ИтоговоеКоличествоМест = 0;
// Начинаем обход строк табличной части "Товары"
Для Каждого ТекущаяСтрока Из СсылкаНаОбъект.Товары Цикл
// Очищаем параметры области строки перед заполнением
ОбластьСтроки.Параметры.Очистить();
// Переносим базовые реквизиты строки (Код, Номенклатура, Количество, Цена, Сумма и т.д.)
ЗаполнитьЗначенияСвойств(ОбластьСтроки.Параметры, ТекущаяСтрока);
// --- БЛОК РАСЧЕТА ВЕСА ---
ВесСтроки = 0;
Если ЗначениеЗаполнено(ТекущаяСтрока.ЕдиницаИзмерения) Тогда
// Вес единицы измерения умножаем на количество в строке
ВесСтроки = ТекущаяСтрока.Количество * ТекущаяСтрока.ЕдиницаИзмерения.Вес;
КонецЕсли;
ОбластьСтроки.Параметры.Вес = ВесСтроки;
ИтоговыйВес = ИтоговыйВес + ВесСтроки;
// --- БЛОК РАСЧЕТА КОЛИЧЕСТВА МЕСТ ---
КоличествоМестСтроки = 0;
Если ЗначениеЗаполнено(ТекущаяСтрока.ЕдиницаМест) Тогда
КоэфОсновной = ?(ЗначениеЗаполнено(ТекущаяСтрока.ЕдиницаИзмерения), ТекущаяСтрока.ЕдиницаИзмерения.Коэффициент, 1);
КоэфМеста = ТекущаяСтрока.ЕдиницаМест.Коэффициент;
Если КоэфМеста <> 0 Тогда
КоличествоМестСтроки = (ТекущаяСтрока.Количество * КоэфОсновной) / КоэфМеста;
КонецЕсли;
КонецЕсли;
ОбластьСтроки.Параметры.КоличествоМест = КоличествоМестСтроки;
ИтоговоеКоличествоМест = ИтоговоеКоличествоМест + КоличествоМестСтроки;
// Выводим заполненную строку в документ
ТабличныйДокумент.Вывести(ОбластьСтроки);
КонецЦикла;
// Заполняем параметры подвала накопленными итогами
ОбластьПодвал.Параметры.ВсегоВес = ИтоговыйВес;
ОбластьПодвал.Параметры.ВсегоМест = ИтоговоеКоличествоМест;
// Выводим подвал в документ
ТабличныйДокумент.Вывести(ОбластьПодвал);
Возврат ТабличныйДокумент;
КонецФункции
При работе с нетиповыми или доработанными конфигурациями «Управление торговлей» необходимо учитывать ряд важных нюансов:
Вес (или ВесЧислом) непосредственно в справочник Номенклатура. В этом случае код расчета веса изменится и будет выглядеть так:
ВесСтроки = ТекущаяСтрока.Количество * ТекущаяСтрока.Номенклатура.ВесЧислом;
Применяя предложенные методики ручного расчета показателей в цикле обхода данных, мы гарантируем стабильную и быструю работу внешней печатной формы без риска возникновения ошибок отсутствия метаданных.