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