При работе с современными типовыми конфигурациями на платформе «1С:Предприятие 8.3» (такими как 1С:Комплексная автоматизация, 1С:ERP или 1С:Управление торговлей) часто возникает необходимость кастомизации печатных форм. Одна из самых распространенных задач — вывод дополнительного реквизита, созданного пользователем в режиме «1С:Предприятие», в стандартную печатную форму (например, в счет на оплату из заказа клиента).
В этой статье мы подробно разберем, почему возникают типичные ошибки при попытке написать такой код самостоятельно, проанализируем структуру модуля печати и рассмотрим три практических способа решения этой задачи: от классического запроса до элегантного обращения к стандартным функциям Библиотеки стандартных подсистем (БСП).
Часто начинающие разработчики и аналитики при попытке дописать код в модуле менеджера печати сталкиваются с ошибками компиляции вида Переменная не определена. Давайте разберем типичный ошибочный код и выясним причины его неработоспособности:
// Ошибочный код
СтруктураДанныхДатаИзгТовара.Вставить(УправлениеСвойствами.ЗначениеСвойства(ДокументСсылка.ТекущийДокумент, ПланВидовХарактеристикСсылка.ДополнительныеРеквизитыИСведения, ДатаИсполненияЗаказа));
Проанализируем, почему этот код вызывает ошибки компилятора:
ДокументСсылка и ПланВидовХарактеристикСсылка — это обозначения типов данных в системе 1С, а не конкретные переменные или объекты. В коде нельзя обращаться к ним напрямую для получения данных. Для работы с конкретным документом нам нужна ссылка на этот документ (например, СсылкаНаДокумент), а для обращения к менеджеру плана видов характеристик используется конструкция во множественном числе — ПланыВидовХарактеристик.ДатаИсполненияЗаказа написано без кавычек. Программа пытается найти переменную с таким именем в текущем контексте и, не находя ее, выдает ошибку. Имя свойства для разработчиков должно передаваться в виде строки в кавычках либо предварительно находиться в базе данных программным путем.Теперь, когда мы понимаем физику процесса, перейдем к правильным методам реализации нашей задачи.
Современные конфигурации 1С построены на базе БСП (Библиотеки стандартных подсистем). В ней присутствует мощный модуль УправлениеСвойствами, который позволяет получить значение любого дополнительного реквизита буквально одной строкой кода без написания громоздких запросов.
Для этого нам понадобится так называемое Имя для разработчиков. Его можно найти в режиме «1С:Предприятие»: откройте карточку вашего дополнительного реквизита и найдите на вкладке «Главное» (или в меню «Еще» -> «Для разработчиков») уникальный идентификатор. Обычно он выглядит как ИмяРеквизита_УникальныйХэш, например: ДатаИсполненияЗаказа_cb85b7049ecf49b78e5150a610da5b33.
Рассмотрим пример кода, который мы вставим в процедуру формирования печатной формы:
// 1. Получаем область из нашего макета печати
ОбластьМакета = Макет.ПолучитьОбласть("ДатаИзгТовара");
// 2. Определяем ссылку на текущий документ (в контексте цикла печати БСП это обычно Переменная Ссылка или ДанныеПечати.Ссылка)
СсылкаНаДокумент = ДанныеПечати.Ссылка; // Имя переменной зависит от конкретной процедуры печати
// 3. Задаем имя свойства "для разработчиков"
ИмяСвойства = "ДатаИсполненияЗаказа_cb85b7049ecf49b78e5150a610da5b33";
// 4. Вызываем стандартный метод БСП для получения значения реквизита
ЗначениеДопРеквизита = УправлениеСвойствами.ЗначениеСвойства(СсылкаНаДокумент, ИмяСвойства);
// 5. Если значение заполнено, выводим область на печать
Если ЗначениеЗаполнено(ЗначениеДопРеквизита) Тогда
СтруктураПараметров = Новый Структура;
СтруктураПараметров.Вставить("ДатаИзготовленияТовара", ЗначениеДопРеквизита);
ОбластьМакета.Параметры.Заполнить(СтруктураПараметров);
ТабличныйДокумент.Вывести(ОбластьМакета);
КонецЕсли;
Этот способ является наиболее стабильным, так как платформа сама оптимизирует кэширование и получение данных дополнительных реквизитов.
Если вам требуется интегрировать получение дополнительного реквизита в уже существующий сложный пакетный запрос печатной формы (для экономии обращений к базе данных), оптимально использовать классический запрос к табличной части дополнительных реквизитов документа.
Проанализируем структуру запроса и напишем правильный вариант с отбором по конкретному документу и имени свойства:
// Создаем объект Запрос
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЗаказКлиентаДополнительныеРеквизиты.Значение КАК ДатаИзготовленияТовара
|ИЗ
| Документ.ЗаказКлиента.ДополнительныеРеквизиты КАК ЗаказКлиентаДополнительныеРеквизиты
|ГДЕ
| ЗаказКлиентаДополнительныеРеквизиты.Ссылка = &Ссылка
| И (ЗаказКлиентаДополнительныеРеквизиты.Свойство.Имя = &ИмяСвойства
| ИЛИ ЗаказКлиенаДополнительныеРеквизиты.Свойство.Наименование = &НаименованиеСвойства)";
// Передаем параметры в запрос
Запрос.УстановитьПараметр("Ссылка", СсылкаНаДокумент);
// Поиск по внутреннему имени (более надежно)
Запрос.УстановитьПараметр("ИмяСвойства", "ДатаИсполненияЗаказа_cb85b7049ecf49b78e5150a610da5b33");
// Либо поиск по представлению для пользователя (синониму)
Запрос.УстановитьПараметр("НаименованиеСвойства", "Дата изготовления товара");
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
ОбластьМакета = Макет.ПолучитьОбласть("ДатаИзгТовара");
ОбластьМакета.Параметры.ДатаИзготовленияТовара = Выборка.ДатаИзготовленияТовара;
ТабличныйДокумент.Вывести(ОбластьМакета);
КонецЕсли;
Обратите внимание: При использовании запроса крайне важно устанавливать параметр &Ссылка, чтобы ограничить выборку только текущим обрабатываемым документом. В противном случае запрос вернет данные по всем документам базы данных, что приведет к фатальному снижению производительности.
Этот способ идеально подходит, если объект (документ) уже полностью прочитан в память и находится в транзакции или в процедуре формы. Мы можем осуществить поиск непосредственно в коллекции строк его табличной части ДополнительныеРеквизиты.
Рассмотрим пример реализации:
// Получаем область макета
ОбластьМакета = Макет.ПолучитьОбласть("ДатаИзгТовара");
// Находим элемент плана видов характеристик по его представлению (заголовку)
СвойствоДопРеквизита = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту("Заголовок", "Дата изготовления товара");
Если ЗначениеЗаполнено(СвойствоДопРеквизита) Тогда
// Выполняем поиск строки в табличной части текущего документа
ОтборСтрок = Новый Структура("Свойство", СвойствоДопРеквизита);
НайденныеСтроки = СсылкаНаДокумент.ДополнительныеРеквизиты.НайтиСтроки(ОтборСтрок);
Если НайденныеСтроки.Количество() > 0 Тогда
// Заполняем параметр полученным значением из первой найденной строки
ОбластьМакета.Параметры.ДатаИзготовленияТовара = НайденныеСтроки[0].Value;
ТабличныйДокумент.Вывести(ОбластьМакета);
КонецЕсли;
КонецЕсли;
Крайне не рекомендуется вносить изменения непосредственно в типовую конфигурацию «1С:Комплексная автоматизация», так как это существенно усложнит последующие обновления системы. Для безопасного внедрения кода воспользуемся механизмом Расширений конфигурации:
ПечатьСчетовНаОплату и ее макет (в котором вы предварительно добавили область ДатаИзгТовара с параметром ДатаИзготовленияТовара).ЗаполнитьТабличныйДокументСчетаНаОплату).&После или &Вместо для кастомизации вывода печатной формы. Например, с помощью метода &После вы можете дописать вывод вашей области в самом конце формирования табличного документа.Таким образом, ваша доработка останется полностью изолированной от типового кода, а обновление системы пройдет в штатном автоматическом режиме.