Как программно заполнить новый документ и открыть его форму в 1С 8.3

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

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

Анализ проблемы: почему форма открывается пустой?

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

Проанализируем использование метода ЗначениеВРеквизитФормы(документ, "Объект"). Этот метод предназначен исключительно для синхронизации данных внутри программного кода модуля формы. Его нельзя просто вызвать извне и ожидать, что внешняя форма «подхватит» данные. Выясним причину: форма — это самостоятельный программный объект, и передача данных в нее должна происходить по строго определенным правилам платформы.

Способ 1: Использование параметра «ЗначениеЗаполнения»

Это наиболее «чистый» и рекомендуемый платформой способ для создания новых объектов с предопределенными данными. Вместо того чтобы создавать объект заранее, мы передаем инструкции по заполнению непосредственно в момент открытия формы. Проанализируем, как это работает на практике.

Для начала подготовим структуру с данными на клиенте и передадим её в параметры открытия формы:


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

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

Теперь нам необходимо обеспечить обработку этих данных в самом документе. Перейдем в Модуль объекта документа и найдем (или создадим) обработчик события ОбработкаЗаполнения. Рассмотрим пример кода:


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

Этот метод идеален, если данных немного. Но что делать, если нужно передать сотни строк табличной части? Рассмотрим следующий вариант.

Способ 2: Передача данных через Временное хранилище

Если объект сложный и данных слишком много для передачи через параметры, мы используем механизм Временного хранилища. Логика такова: мы создаем и заполняем объект на сервере, «замораживаем» его в хранилище, передаем адрес этой «заморозки» в форму, а форма при создании извлекает данные и подставляет их в свой основной реквизит.

Разберем по шагам реализацию этого алгоритма. Сначала подготовим данные на сервере (например, в модуле команды или внешней обработки):


&НаСервере
Функция ПодготовитьДокументИПоместитьВХранилище()
    // Создаем и заполняем объект
    НовыйДокумент = Документы.ПриходныйКассовыйОрдер.СоздатьДокумент();
    НовыйДокумент.Дата = ТекущаяДата();
    
    // Пример заполнения табличной части
    НоваяСтрока = НовыйДокумент.Товары.Добавить();
    НоваяСтрока.Номенклатура = Справочники.Номенклатура.НайтиПоНаименованию("Услуга");
    НоваяСтрока.Количество = 1;

    // Помещаем объект целиком во временное хранилище
    // Уникальный идентификатор формы (если есть) поможет связать время жизни хранилища с формой
    АдресХранилища = ПоместитьВоВременноеХранилище(НовыйДокумент);
    Возврат АдресХранилища;
КонецФункции

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

Теперь самое важное — нужно «научить» форму документа принимать эти данные. В модуле формы документа добавим обработчик события ПриСозданииНаСервере:


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

Важный нюанс: метод ЗначениеВРеквизитФормы здесь сработает корректно, потому что он вызывается в контексте сервера самой формы, и вторым параметром мы указываем имя основного реквизита — "Объект".

Ошибки, которых стоит избегать

Рассмотрим популярные, но неверные подходы, которые часто встречаются в коде:

  1. Использование ПолучитьФорму().Открыть(): Этот метод считается устаревшим (legacy) для управляемых форм. Он провоцирует лишние серверные вызовы и усложняет управление параметрами. Всегда используйте ОткрытьФорму().
  2. Попытка открыть форму уже записанного объекта: Если вы сначала вызываете Объект.Записать(), а потом хотите открыть его форму, передавайте в ОткрытьФорму параметр "Ключ" со ссылкой на документ. Система сама загрузит данные из базы.
  3. Забытая очистка временного хранилища: Если не вызывать УдалитьИзВременногоХранилища, данные будут занимать память на сервере до окончания сеанса пользователя, что при массовой работе может привести к снижению производительности.

Резюме для практического применения

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

Помните, что в управляемом приложении форма — это лишь визуальное отражение данных, хранящихся в реквизитах формы. Чтобы изменения стали видны пользователю, они должны попасть именно в реквизит Объект формы в момент её инициализации на сервере.

← На главную