При работе с типовыми конфигурациями 1С, такими как Управление торговлей для Украины, редакция 3.1 (аналог УТ11), часто возникает необходимость доработать стандартные печатные формы. Одной из распространённых задач является добавление итоговой информации, такой как общее количество позиций номенклатуры, суммарное количество единиц (штук), общий вес товара и указание склада, с которого отпускается товар. Давайте рассмотрим подробнее, как реализовать эти доработки, используя код модуля и редактирование макета печатной формы.
Мы будем работать с функцией, отвечающей за заполнение печатной формы РасходнаяНакладная, которая находится в модуле менеджера обработки ПечатьОбщихФорм.
Для начала, разберем по шагам, как вывести информацию о складе, с которого осуществляется отпуск товара. Эту информацию удобно разместить в шапке документа, например, в области "Покупатель" или "Поставщик", или создать отдельную область для неё.
Откроем конфигуратор, найдем обработку ПечатьОбщихФорм. На вкладке "Макеты" откроем макет ПФ_MXL_РасходнаяНакладная. В выбранной вами области (например, "Покупатель") создадим новую ячейку (или используем существующую) и зададим ей параметр, например, [Склад]. Убедимся, что размеры ячейки достаточны для вывода наименования склада.
В функции ЗаполнитьТабличныйДокументРасходнаяНакладная нам необходимо найти участок кода, где заполняется область макета "Покупатель" или "Поставщик". В исходном коде это выглядит так:
// ... код до области Покупатель
ОбластьМакета = Макет.ПолучитьОбласть("Покупатель");
ПредставлениеПолучателя = ФормированиеПечатныхФорм.ОписаниеОрганизации(СведенияОПокупателе, "ПолноеНаименование",,КодЯзыкаПечать);
РеквизитыПокупателя = ФормированиеПечатныхФорм.ОписаниеОрганизации(СведенияОПокупателе, "ФактическийАдрес,Телефоны,",,КодЯзыкаПечать);
// Получаем склад из данных документа
Склад = ДанныеПечати.Ссылка.Склад;
СтруктураДанныхПокупатель = Новый Структура;
СтруктураДанныхПокупатель.Вставить("ПредставлениеПолучателя", ПредставлениеПолучателя);
СтруктураДанныхПокупатель.Вставить("Получатель", ДанныеПечати.Получатель);
СтруктураДанныхПокупатель.Вставить("РеквизитыПокупателя", РеквизитыПокупателя);
// Добавляем склад в структуру параметров для заполнения области
СтруктураДанныхПокупатель.Вставить("Склад", ДанныеПечати.Ссылка.Склад);
// Для отладки можно использовать Сообщить(ДанныеПечати.Ссылка.Склад);
ОбластьМакета.Параметры.Заполнить(СтруктураДанныхПокупатель);
ТабличныйДокумент.Вывести(ОбластьМакета);
// ... остальной код
Здесь ключевым моментом является строка СтруктураДанныхПокупатель.Вставить("Склад", ДанныеПечати.Ссылка.Склад);. Она добавляет значение склада, полученное из реквизита документа ДанныеПечати.Ссылка.Склад, в структуру параметров, которая затем используется для заполнения области макета.
Важно: Убедитесь, что имя параметра в структуре (в данном случае "Склад") точно соответствует имени параметра в ячейке макета ([Склад]).
Задача вывода общего количества штук требует суммирования значений из колонки "Количество" всех строк табличной части документа. Отметим, что "общее количество позиций" может означать либо количество уникальных наименований товаров, либо просто количество строк в табличной части, что является более частым запросом. В данном случае мы сосредоточимся на сумме по колонке "Количество".
В начале функции ЗаполнитьТабличныйДокументРасходнаяНакладная, до цикла обхода строк табличной части, инициализируем переменную для хранения общей суммы количества. Найдем место, где объявляются другие счетчики:
// ...
Сумма = 0;
СуммаНДС = 0;
ВсегоСкидок = 0;
НомерСтроки = 0;
ВсегоБезСкидок = 0;
// Инициализируем счетчики для общего количества и веса
ИтогКоличество = 0;
ИтогВес = 0;
// ...
Далее, нам необходимо найти цикл, который перебирает строки табличной части документа. В предоставленном коде это цикл Пока ВыборкаПоТоварам.Следующий Цикл. Внутри этого цикла будем увеличивать наш счетчик ИтогКоличество:
// ...
// Выводим строки таблицы Товары
// Перемещаем цикл обхода для расчёта итогов перед основным циклом вывода строк,
// чтобы итоги были готовы к моменту вывода подвала.
// Обходим выборку для расчёта итогов
ВыборкаПоТоварам.Сбросить(); // Сбрасываем выборку, если она уже была обойдена
Пока ВыборкаПоТоварам.Следующий() Цикл
ИтогКоличество = ИтогКоличество + ВыборкаПоТоварам.Количество;
// ... здесь будет также расчет веса
КонецЦикла;
ВыборкаПоТоварам.Сбросить(); // Сбрасываем выборку ещё раз, чтобы основной цикл вывода начался с первой строки
Сообщить("Итоговое количество: " + ИтогКоличество); // Для отладки
// ...
Обратите внимание: Важно выполнить этот расчет в отдельном цикле перед основным циклом вывода строк или гарантировать, что ВыборкаПоТоварам будет сброшена и обойдена дважды (один раз для расчетов, второй раз для вывода). В исходном коде видно, что ВыборкаПоТоварам.Следующий() вызывается уже для вывода строк, поэтому для расчёта итогов нам нужно либо обойти её до этого, либо сбросить и обойти повторно. Предложенное выше размещение счётчика до основного цикла вывода строк и сброс выборки перед каждым использованием — это безопасный подход.
После завершения цикла, когда ИтогКоличество будет рассчитано, нам нужно вывести это значение в подвал таблицы. Найдем код, отвечающий за вывод подвала:
// ...
// Выводим подвал
ОбластьНомера = Макет.ПолучитьОбласть("ПодвалТаблицы" + СуффиксОбластиСтроки + "|НомерСтроки");
ОбластьКодов = Макет.ПолучитьОбласть("ПодвалТаблицы" + СуффиксОбластиСтроки + "|КолонкаКодов");
ОбластьТовар = Макет.ПолучитьОбласть("ПодвалТаблицы" + СуффиксОбластиСтроки + "|Товар" + СуффиксОбластиКолонки);
ОбластьДанных = Макет.ПолучитьОбласть("ПодвалТаблицы" + СуффиксОбластиСтроки + "|Данные" + СуффиксОбластиКолонки);
ТабличныйДокумент.Вывести(ОбластьНомера);
Если ВыводитьКоды Тогда
ТабличныйДокумент.Присоединить(ОбластьКодов);
КонецЕсли;
ТабличныйДокумент.Присоединить(ОбластьТовар);
СтруктураДанныхПодвал = Новый Структура; // Создаем новую структуру для параметров подвала
Если ЕстьСкидки Тогда
СтруктураДанныхПодвал.Вставить("ВсегоСкидок", ?(ЗаголовокСкидки.ТолькоНаценка,-ВсегоСкидок, ВсегоСкидок));
СтруктураДанныхПодвал.Вставить("ВсегоБезСкидок", ВсегоБезСкидок);
КонецЕсли;
СтруктураДанныхПодвал.Вставить("Всего", ФормированиеПечатныхФорм.ФорматСумм(Сумма));
// Добавляем параметр для общего количества
СтруктураДанныхПодвал.Вставить("ИтогКоличество", ИтогКоличество);
ОбластьДанных.Параметры.Заполнить(СтруктураДанныхПодвал);
ТабличныйДокумент.Присоединить(ОбластьДанных);
// ...
На макете ПФ_MXL_РасходнаяНакладная в области "ПодвалТаблицы" (или в области ОбластьДанных, если вы объединяете ячейки), необходимо создать ячейку с параметром [ИтогКоличество]. Только после этого значение будет выведено на форму.
Расчет общего веса аналогичен расчету общего количества, но имеет одну особенность: вес хранится не в табличной части документа, а в карточке номенклатуры. Поэтому нам понадобится обращаться к реквизиту Номенклатура.Вес.
Переменная ИтогВес уже была инициализирована вместе с ИтогКоличество в начале функции.
В том же цикле обхода выборки товаров, где мы суммируем количество, добавим расчет веса:
// ...
// Обходим выборку для расчёта итогов
ВыборкаПоТоварам.Сбросить();
Пока ВыборкаПоТоварам.Следующий() Цикл
ИтогКоличество = ИтогКоличество + ВыборкаПоТоварам.Количество;
// Расчёт общего веса
// Важно: вес хранится в карточке номенклатуры. Необходимо учитывать, что поле "Вес" может быть не заполнено.
Если ВыборкаПоТоварам.Номенклатура.Вес <> Неопределено Тогда
ИтогВес = ИтогВес + (ВыборкаПоТоварам.Номенклатура.Вес * ВыборкаПоТоварам.Количество);
КонецЕсли;
КонецЦикла;
ВыборкаПоТоварам.Сбросить();
Сообщить("Итоговый вес: " + ИтогВес); // Для отладки
// ...
Здесь критически важно добавить проверку ВыборкаПоТоварам.Номенклатура.Вес <> Неопределено. Если для какой-либо номенклатуры вес не указан, попытка умножения Неопределено на число приведет к ошибке.
Аналогично общему количеству, добавим параметр для веса в структуру данных подвала:
// ...
// Выводим подвал
// ... код получения областей подвала ...
СтруктураДанныхПодвал = Новый Структура;
// ... (существующие параметры)
// Добавляем параметры для общего количества и веса
СтруктураДанныхПодвал.Вставить("ИтогКоличество", ИтогКоличество);
СтруктураДанныхПодвал.Вставить("ИтогВес", ИтогВес);
ОбластьДанных.Параметры.Заполнить(СтруктураДанныхПодвал);
ТабличныйДокумент.Присоединить(ОбластьДанных);
// ...
На макете ПФ_MXL_РасходнаяНакладная в области "ПодвалТаблицы" (или в ОбластьДанных) необходимо создать ячейку с параметром [ИтогВес].
В процессе реализации подобных доработок вы можете столкнуться со следующими проблемами:
Эта ошибка (как в сообщении 18: Переменная не определена (ОбластьПодвалТаблицы)) возникает, когда вы пытаетесь использовать переменную, которая не была объявлена или получена. В данном случае, если вы хотите использовать ОбластьПодвалТаблицы напрямую, вам необходимо получить её из макета:
ОбластьПодвалТаблицы = Макет.ПолучитьОбласть("ПодвалТаблицы");
Однако, в типовом коде печатной формы "Расходная накладная" подвал таблицы выводится частями (ОбластьНомера, ОбластьКодов, ОбластьТовар, ОбластьДанных), которые затем присоединяются друг к другу. Поэтому, скорее всего, вам нужно будет добавлять параметры в уже существующую ОбластьДанных, как было показано выше.
Эта ошибка (как в сообщении 21) означает, что параметр с таким именем (ИтогКоличество) не существует в макете в той области, куда вы пытаетесь его передать. Убедитесь, что вы открыли макет в конфигураторе, перешли в соответствующую область (например, "ПодвалТаблицы" или ту, что используется для ОбластьДанных), и создали там ячейку с параметром [ИтогКоличество] (с квадратными скобками).
Сообщить() видны:
Если Сообщить(ИтогКоличество) показывает правильное значение, но на печатной форме оно отсутствует, то проблема, скорее всего, в макете. Проверьте следующее:
СтруктураДанныхПодвал.Вставить("ИтогКоличество", ИтогКоличество);) и в макете ([ИтогКоличество]).Область.Параметры.Заполнить(СтруктураДанных); для нужной области, и затем эта область выводится с помощью ТабличныйДокумент.Вывести(Область); или ТабличныйДокумент.Присоединить(Область);.Для эффективной отладки всегда используйте функцию Сообщить(). Вставляйте её в разные места кода, чтобы проверить значения переменных на каждом этапе: после инициализации, внутри цикла (если нужно видеть промежуточные значения), после цикла (для итоговых значений) и перед заполнением области макета. Это поможет точно локализовать проблему.
Модификация печатных форм в 1С требует внимательной работы как с программным кодом, так и с визуальным макетом в конфигураторе. Рассмотренные шаги позволяют нам добавить в печатную форму "Расходная накладная" важные итоговые данные: информацию о складе, общее количество штук по всем позициям и общий вес товара. Всегда делайте резервные копии или используйте расширения для доработки типовых конфигураций, чтобы облегчить дальнейшие обновления.