При работе с конфигурацией «1С:Управление торговлей» версии 11 (а также КА 2 и ERP) разработчики часто сталкиваются с задачей кастомизации этикеток и ценников. Типовой конструктор макетов предоставляет обширный список полей, но что делать, если на этикетку необходимо вывести специфический параметр? Например, особым образом обработанное рабочее наименование номенклатуры (скажем, с обрезанными лишними символами, специализированными префиксами или объединенное с артикулом).
В этой статье мы подробно разберем, как устроена подсистема печати этикеток «под капотом», почему стандартный отладчик не всегда помогает быстро найти место формирования данных, и рассмотрим два практических способа решения этой задачи: классический программный метод через доработку СКД и архитектурно правильный Low-code метод, не требующий изменения запросов конфигурации.
Для начала проанализируем ситуацию и выясним, почему у многих разработчиков возникают сложности при попытке быстро дописать нужный параметр. Дело в том, что механизм печати ценников и этикеток в УТ 11 разделен на несколько независимых уровней:
Если мы просто добавим поле в форму редактора, при печати система не сможет сопоставить его и выведет пустоту. Если добавим только в СКД печати — пользователь не увидит поле в конструкторе. Нам необходима синхронность действий. Рассмотрим детально каждый из двух способов реализации.
---
Этот метод подходит в тех случаях, когда алгоритм формирования нового параметра достаточно сложен и его невозможно или нецелесообразно хранить в базе данных как отдельный реквизит. Все доработки мы будем выполнять в рамках расширения конфигурации, чтобы сохранить типовую программу на поддержке.
Рассмотрим весь процесс по шагам.
Шаг 1. Добавление объектов в расширение
Для работы нам понадобятся следующие объекты конфигурации, которые необходимо перенести в наше расширение:
ПечатьЭтикетокИЦенников со всеми ее макетами.ШаблоныЭтикетокИЦенников (а именно его форма ФормаРедактированияШаблонаЭтикетокИЦенников).Шаг 2. Модификация макетов компоновки данных
В обработке ПечатьЭтикетокИЦенников содержатся встроенные макеты СКД. Нам необходимо отредактировать два основных макета:
ПоляШаблонаТовары — данный макет отвечает за вывод списка доступных полей в конструкторе шаблонов.ПоляШаблонаПечатьТовары (в некоторых релизах может называться ПоляШаблонаБД) — данный макет отвечает за выборку реальных данных из базы при формировании печатной формы.Откроем оба макета в расширении и выполним в них одинаковые действия:
ОбработанноеНаименование. Имя поля в обоих макетах должно совпадать с точностью до регистра букв!ОбработанноеНаименование в список доступных полей компоновки.Шаг 3. Обработка значения поля в СКД
Поскольку автору темы требуется именно обработанная строка наименования, мы можем поступить двумя путями в зависимости от сложности алгоритма:
ОбработанноеНаименование, а в поле «Выражение» пишем вызов нашей экспортной функции:
МойОбщийМодульКлиентСервер.ОбработатьНаименование(Номенклатура.Наименование)
Убедитесь, что общий модуль, к которому вы обращаетесь, имеет включенные флаги Клиент (управляемое приложение), Сервер и Вызов сервера.
Шаг 4. Регистрация нового поля в коде конструктора
Теперь нам нужно сделать так, чтобы форма конструктора увидела наше поле и разрешила пользователю перетащить его в область макета. Для этого переходим к модулю формы ФормаРедактированияШаблонаЭтикетокИЦенников справочника ШаблоныЭтикетокИЦенников.
Найдем процедуру ЗаполнитьДоступныеПоля(). Мы переопределим ее в расширении, используя аннотацию &После:
&После("ЗаполнитьДоступныеПоля")
Процедура Расш1_ЗаполнитьДоступныеПоля()
// Находим строку "Товары" в дереве доступных полей, чтобы поместить наш параметр туда
СтрокаТовары = ДоступныеПоля.Строки.Найти("Товары", "ИмяПоля");
Если СтрокаТовары <> Неопределено Тогда
НовоеПоле = СтрокаТовары.Строки.Добавить();
НовоеПоле.ИмяПоля = "ОбработанноеНаименование";
НовоеПоле.Представление = "Обработанное наименование (наше)";
НовоеПоле.ТипЗаполнения = Перечисления.ТипыЗаполненияШаблоновЭтикетокИЦенников.Реквизит;
КонецЕсли;
КонецПроцедуры
После применения данного расширения пользователь в режиме «1С:Предприятие» откроет редактор шаблона этикетки, увидит в левой колонке новое поле «Обработанное наименование (наше)», сможет перетащить его на макет, и при печати оно автоматически заполнится результатом работы вашей функции.
---
Первый метод имеет один весомый недостаток: при обновлении конфигурации фирма «1С» может существенно изменить структуру запросов в макетах СКД обработки ПечатьЭтикетокИЦенников. В результате ваше расширение может конфликтовать с новым кодом, что потребует ручного слияния форм и макетов.
Существует более изящное и стабильное решение, полностью использующее штатный функционал подсистемы дополнительных реквизитов и сведений УТ 11. Все дополнительные реквизиты номенклатуры автоматически подтягиваются в конструктор этикеток без какого-либо вмешательства в макеты СКД!
Рассмотрим, как реализовать автозаполнение обработанного наименования через этот механизм.
Шаг 1. Создание дополнительного реквизита в пользовательском режиме
После этого действия в конструкторе макета этикеток в группе полей номенклатуры автоматически появится поле «Обработанное наименование». Его уже можно размещать на макете. Но как сделать так, чтобы пользователям не пришлось заполнять его вручную при записи товара?
Шаг 2. Автоматическое заполнение значения реквизита при записи
Чтобы автоматизировать этот процесс, мы напишем небольшое расширение, перехватывающее событие записи номенклатуры. Создадим в расширении подписку на событие ПередЗаписью для справочника Номенклатура.
Проанализируем пример кода обработчика события, который будет находить наш дополнительный реквизит и записывать туда обработанную строку:
Процедура Расш1_ПередЗаписьюНоменклатурыПередЗаписью(Источник, Отказ) Экспорт
// Проверим, что это не группа номенклатуры
Если Источник.ЭтоГруппа Тогда
Возврат;
КонецЕсли;
// Наш алгоритм обработки наименования
ИсходноеНаименование = Источник.Наименование;
ОбработаннаяСтрока = МойОбщийМодуль.ВыполнитьПреобразованиеНаименования(ИсходноеНаименование);
// Находим нужный дополнительный реквизит в свойствах номенклатуры
СсылкаНаСвойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Обработанное наименование");
Если ЗначениеЗаполнено(СсылкаНаСвойство) Тогда
// Пытаемся найти уже существующую строку в табличной части ДополнительныеРеквизиты
СтрокаСвойства = Источник.ДополнительныеРеквизиты.Найти(СсылкаНаСвойство, "Свойство");
Если СтрокаСвойства = Неопределено Тогда
// Если строки еще нет, добавим ее
НоваяСтрока = Источник.ДополнительныеРеквизиты.Добавить();
НоваяСтрока.Свойство = СсылкаНаСвойство;
НоваяСтрока.Значение = ОбработаннаяСтрока;
Иначе
// Если строка есть, обновим значение
СтрокаСвойства.Значение = ОбработаннаяСтрока;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Преимущества второго способа очевидны:
Таким образом, выбор метода зависит от ваших требований к производительности и хранению данных. Если вам важно хранить историю изменений или использовать поле в поиске — выбирайте второй способ. Если база данных перегружена и вам критически важно формировать значение исключительно в момент печати — используйте первый способ с расширением СКД.