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

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

При переходе с обычных форм на управляемые разработчики часто сталкиваются со сложностями инициализации новых объектов. В обычном приложении было привычно создать объект в коде, заполнить любые его поля, вызвать методы пересчета и открыть форму объекта. В управляемом интерфейсе логика разделена между клиентом и сервером: передать сам объект ДокументОбъект с сервера на клиент нельзя, а создавать пустые документы с последующей записью в базу данных не рекомендуется, чтобы не засорять информационную базу незавершенными черновиками.

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

Анализ типичных ошибок при открытии формы нового документа

Посмотрим на ошибочный подход, который часто пытаются реализовать по аналогии со старыми версиями платформы:


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

&НаСервере
Процедура ЗаполнитьДокументНаСервере(ДанныеФормы)
    Док = Документы.ЗаказКлиента.СоздатьДокумент();
    Док.Организация = Объект.Организация;
    Док.Контрагент = Объект.Контрагент;
    ЗначениеВДанныеФормы(Док, ДанныеФормы);
КонецПроцедуры

Выясним, почему этот код неэффективен и приводит к проблемам:

  1. Лишние серверные вызовы и преобразования: Происходит множественная пересылка данных между клиентом и сервером с постоянными конвертациями через ДанныеФормыВЗначение и ЗначениеВДанныеФормы.
  2. Не вызывается процедура ОбработкаЗаполнения: Вызов СоздатьДокумент() просто инициализирует пустой объект в памяти, не запуская стандартные механизмы заполнения реквизитов и правил по умолчанию.
  3. Отсутствует расчет связанных полей: При прямом заполнении реквизитов не срабатывают интерактивные события формы (например, ПриИзменении), из-за чего зависимые реквизиты (система налогообложения, договоры, соглашения, валюта) остаются со значениями по умолчанию.

Способ 1. Использование стандартного параметра «ЗначениеЗаполнения» (рекомендуемый)

Платформа 1С предоставляет встроенный механизм расширения управляемой формы документа. Для передачи первичных данных достаточно передать структуру в специальный параметр ЗначениеЗаполнения. При этом открытие формы выполняется в одну клиентскую команду.

Рассмотрим пример на клиенте:


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

При таком подходе платформа выполняет следующие действия:

  1. На сервере создается новый экземпляр документа.
  2. Автоматически вызывается обработчик ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка) в модуле объекта целевого документа, куда в параметр ДанныеЗаполнения передается наша структура.
  3. Если СтандартнаяОбработка = Истина, платформа автоматически сопоставляет ключи структуры с реквизитами документа и заполняет их.
  4. Объект трансформируется в данные формы и открывается пользователю за один вызов без предварительной записи в БД.

Способ 2. Передача параметра «Основание» и обработка в модуле объекта

Если для нового документа требуется передать ссылку на документ-основание или сложную структуру данных с особой логикой распределения по табличным частям, используем параметр Основание.

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


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

В модуле объекта создаваемого документа проанализируем тип переданного основания в обработчике события:


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

Способ 3. Передача произвольных параметров в форму и обработка «ПриСозданииНаСервере»

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

Код вызова формы:


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

В модуле открываемой формы в процедуре ПриСозданииНаСервере обязательно проверяем, что документ является новым, и используем метод Свойство структуры параметров:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Обрабатываем только для новых документов
    Если Объект.Ссылка.Пустая() Тогда
        
        Если Параметры.Свойство("Организация") Тогда
            Объект.Организация = Параметры.Организация;
        КонецЕсли;
        
        Если Параметры.Свойство("Контрагент") Тогда
            Объект.Контрагент = Параметры.Контрагент;
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

Почему не пересчитываются зависимые реквизиты (налогообложение, договоры, счета)?

Частая проблема: организация или контрагент заполнились, но реквизиты вроде Налогообложение, Договор или Банковский счет остались незаполненными или установились по умолчанию.

Проанализируем причину: обработчики событий элементов формы (например, ОрганизацияПриИзменении на клиенте) срабатывают только при интерактивном вводе пользователем. Программное присвоение значений в ОбработкаЗаполнения или в ПриСозданииНаСервере не вызывает обработчики изменений элементов формы.

Чтобы зависимые реквизиты заполнились корректно, в типовых конфигурациях вызываются соответствующие серверные процедуры пересчета объекта:


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

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

Для понимания того, где размещать код инициализации, рассмотрим строгий порядок событий платформы:

  1. Инициализация экземпляра объекта на сервере.
  2. Событие ОбработкаЗаполнения в модуле объекта (получает значение параметров ЗначениеЗаполнения или Основание).
  3. Конвертация объекта в прикладные данные формы (структуру Объект).
  4. Событие ПриСозданииНаСервере в модуле формы документа.
  5. Передача сформированных данных формы на сторону клиента.
  6. Событие ПриОткрытии на клиенте.
  7. Отображение готовой формы пользователю.

Важное замечание по отладке: Процедура ОбработкаЗаполнения всегда исполняется на сервере. Если база работает в клиент-серверном режиме (SQL), убедитесь, что сервер 1С:Предприятия запущен с ключом отладки (-debug), иначе точка останова в модуле объекта не сработает.

← На главную