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