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

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

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

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

Ограничения платформы и причины типовых ошибок

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

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

Вариант 1. Заполнение через ПолучитьФорму и КопироватьДанныеФормы (рекомендуемый способ)

Рассмотрим проверенный способ, который позволяет полностью сформировать и рассчитать новый документ на сервере, не меняя код целевой конфигурации и не требуя включения флагов заполнения у реквизитов.

Разберем по шагам логику работы данного алгоритма:

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

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


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

Теперь рассмотрим серверную процедуру заполнения. Здесь можно заполнять реквизиты напрямую через свойства структуры ДанныеФормы, либо преобразовать их в прикладной объект ДокументОбъект для использования типовых методов расчета:


&НаСервере
Процедура ЗаполнитьДанныеДокументаНаСервере(ДанныеФормы)
    
    // Способ 1: Прямое заполнение структуры данных формы
    ДанныеФормы.Дата = ТекущаяДатаСеанса();
    ДанныеФормы.Организация = ПредопределенноеЗначение("Справочник.Организации.ОсновнаяОрганизация");
    ДанныеФормы.Контрагент = Объект.Контрагент;
    
    // Заполнение строк табличной части
    СтрокаТЧ = ДанныеФормы.Товары.Добавить();
    СтрокаТЧ.Номенклатура = Объект.Номенклатура;
    СтрокаТЧ.Количество = 10;
    СтрокаТЧ.Цена = 100;
    СтрокаТЧ.Сумма = 1000;
    
    // Способ 2: Преобразование в ДокументОбъект для вызова процедур пересчета
    // ДокОбъект = ДанныеФормыВЗначение(ДанныеФормы, Тип("ДокументОбъект.ЗаказПоставщику"));
    // ДокОбъект.Заполнить(СтруктураДанных);
    // ЗначениеВДанныеФормы(ДокОбъект, ДанныеФормы);
    
КонецПроцедуры

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

Вариант 2. Использование метода ОткрытьФорму и структуры ЗначенияЗаполнения

Проанализируем альтернативный подход через вызов стандартного метода ОткрытьФорму. Данный способ подходит, если у реквизитов документа включено свойство Заполнять из данных заполнения, либо в модуле объекта определен обработчик события ОбработкаЗаполнения.

Так как ТаблицаЗначений не может быть передана на клиент, таблицу товаров преобразуем на сервере в сериализуемый тип — Массив структур. Каждая структура в массиве представляет собой отдельную строку табличной части.

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


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

Теперь рассмотрим вызов формы на клиенте с передачей параметров заполнения:


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

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

Сравнение подходов

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

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