Как программно открыть форму документа на основании и передать дополнительные данные для заполнения

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет IT и автоматизация бизнеса
← На главную

При разработке в среде 1С:Предприятие 8.3 часто возникает задача не просто создать документ на основании другого, но и передать в новую форму специфические данные, которых нет в источнике. Стандартный механизм «ввода на основании» отлично работает, когда нужно просто перенести данные из одного объекта в другой, но когда требуется программное вмешательство до момента записи объекта пользователем, возникают определенные трудности.

В этой статье мы подробно разберем, как правильно передавать параметры при открытии формы, почему стандартный параметр ЗначенияЗаполнения может игнорироваться платформой и какие существуют надежные способы решения этой задачи.

Проблема: Конфликт параметров «Основание» и «ЗначенияЗаполнения»

Рассмотрим типичную ситуацию. Нам нужно открыть форму нового документа ЗаказКлиента на основании ПриходТовара, но при этом передать в новый документ значение некоего дополнительного реквизита, который не заполняется автоматически. Казалось бы, решение очевидно — передать структуру в ОткрытьФорму. Однако здесь кроется главная ловушка платформы.

Проанализируем пример кода, который часто приводит к неудаче:


ЭлементыОтбора = Новый Структура("МойРеквизит", ЗначениеМоегоРеквизита);
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Основание", Объект.Ссылка);
ПараметрыФормы.Вставить("ЗначенияЗаполнения", ЭлементыОтбора);

ОткрытьФорму("Документ.ЗаказКлиента.ФормаОбъекта", ПараметрыФормы);

Выясним причину, почему это не работает. В платформе 1С существует жесткий приоритет обработки параметров. Если в структуру параметров одновременно переданы ключи Основание и ЗначенияЗаполнения, система отдает полный приоритет Основанию. При этом содержимое ЗначенияЗаполнения просто игнорируется механизмом автоматического заполнения. В результате в процедуру ОбработкаЗаполнения модуля объекта в качестве данных заполнения попадает только ссылка на документ-основание.

Решение №1: Передача структуры в качестве основания

Это наиболее элегантный и «чистый» способ. Вместо того чтобы передавать ссылку в параметр Основание, мы передадим туда структуру, содержащую и ссылку, и наши дополнительные данные.

Рассмотрим, как это реализовать на стороне вызывающей формы:


// Формируем структуру, которая станет нашим "основанием"
ДанныеДляЗаполнения = Новый Структура;
ДанныеДляЗаполнения.Вставить("ДокументОснование", Объект.Ссылка);
ДанныеДляЗаполнения.Вставить("ДополнительныйПараметр", "Значение");

ПараметрыФормы = Новый Структура("Основание", ДанныеДляЗаполнения);
ОткрытьФорму("Документ.ЗаказКлиента.ФормаОбъекта", ПараметрыФормы);

Теперь проанализируем, что нужно изменить в модуле создаваемого документа (в процедуре ОбработкаЗаполнения). Нам необходимо научить систему понимать, что данные могут прийти не только в виде ссылки, но и в виде структуры.


Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
    
    Если ТипЗнч(ДанныеЗаполнения) = Тип("Структура") Тогда
        
        // Проверяем наличие нашего спец-параметра
        Если ДанныеЗаполнения.Свойство("ДополнительныйПараметр") Тогда
            ЭтотОбъект.МойРеквизит = ДанныеЗаполнения.ДополнительныйПараметр;
        КонецЕсли;
        
        // Вызываем типовое заполнение, передав туда ссылку на реальное основание
        Если ДанныеЗаполнения.Свойство("ДокументОснование") Тогда
            // Здесь может быть вызов типовой процедуры или переустановка 
            // переменной ДанныеЗаполнения для дальнейшей обработки
            ОснованиеДляТипового = ДанныеЗаполнения.ДокументОснование;
            // Продолжаем логику заполнения на основании ОснованиеДляТипового...
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

Решение №2: Использование свойства «Заполнять из данных заполнения»

Если вам нужно заполнить реквизиты объекта без сложной логики в ОбработкаЗаполнения, можно воспользоваться платформенным свойством реквизита.

  1. В конфигураторе откройте свойства нужного реквизита документа.
  2. Установите галочку «Заполнять из данных заполнения».
  3. При вызове формы используйте параметр ЗначенияЗаполнения, но не указывайте параметр Основание.

Посмотрим на пример кода:


ЭлементыЗаполнения = Новый Структура("Склад, Организация", СсылкаНаСклад, СсылкаНаОрганизацию);
ПараметрыФормы = Новый Структура("ЗначенияЗаполнения", ЭлементыЗаполнения);
ОткрытьФорму("Документ.РеализацияТоваровУслуг.ФормаОбъекта", ПараметрыФормы);

Важный момент: если вам все же нужно и основание, и эти значения, придется вернуться к Решению №1, так как наличие Основания в параметрах открытия формы «забивает» автоматику ЗначенийЗаполнения.

Решение №3: Обработка в «ПриСозданииНаСервере» формы

Если по каким-то причинам вы не хотите менять модуль объекта (например, чтобы не задевать логику создания объектов программно без формы), можно дозаполнить объект непосредственно в модуле формы. Параметры, переданные в ОткрытьФорму, всегда доступны в коллекции Параметры на сервере.

Разберем алгоритм действий в форме документа:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Проверяем, что это создание нового объекта, а не открытие существующего
    Если Параметры.Ключ.Пустая() Тогда
        
        // Проверяем наличие наших параметров
        Если Параметры.Свойство("ЗначенияЗаполнения") 
            И ТипЗнч(Параметры.ЗначенияЗаполнения) = Тип("Структура") Тогда
            
            Если Параметры.ЗначенияЗаполнения.Свойство("СпецДанные") Тогда
                Объект.МойРеквизит = Параметры.ЗначенияЗаполнения.СпецДанные;
            КонецЕсли;
            
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

Этот метод хорош тем, что он позволяет работать с данными формы даже в том случае, если ОбработкаЗаполнения в модуле объекта их проигнорировала.

Особенности работы с расширениями

Если вы работаете в расширении конфигурации, проанализируем ситуацию с аннотациями. Для модификации логики заполнения лучше всего использовать &Вместо или &Перед для процедуры ОбработкаЗаполнения.

Используя &Перед, вы можете подменить ДанныеЗаполнения (если это структура) или извлечь из структуры нужные вам данные, записать их в ДополнительныеСвойства объекта, а затем позволить типовому коду отработать по ссылке-основанию.

Резюме и рекомендации

Подведем итоги нашего исследования:

Следуя этим правилам, вы сможете гибко управлять процессом создания документов и обеспечите корректную передачу данных в любых сценариях разработки на платформе 1С.

← На главную