Как открыть форму нового элемента справочника с заполненной табличной частью без записи в базу

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

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

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

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

Это самый «чистый» и рекомендуемый платформой 1С способ. Он позволяет передать данные в объект еще до того, как начнет выполняться программный код в процедуре ПриСозданииНаСервере. Таким образом, когда форма начнет инициализироваться, она уже будет «видеть» заполненные данные, и динамическое построение элементов интерфейса отработает правильно.

Разберем по шагам, как передать структуру заполнения, включая табличную часть. Для заполнения табличной части в структуру ЗначенияЗаполнения необходимо передать массив, состоящий из структур, где ключи соответствуют именам реквизитов табличной части.


&НаКлиенте
Процедура ОткрытьФормуСЗаполнением(Команда)

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

КонецПроцедуры

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

Способ 2. Заполнение через ДанныеФормы на сервере

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

Рассмотрим алгоритм действий:

  1. На клиенте вызываем получение формы объекта.
  2. Передаем форму на сервер для заполнения.
  3. На сервере создаем экземпляр объекта (без записи!).
  4. Заполняем объект нужными данными.
  5. Преобразуем объект в структуру данных формы и копируем их в форму.
  6. На клиенте открываем форму.

&НаКлиенте
Процедура ОткрытьФормуЧерезДанные(Команда)
    
    // 1. Получаем форму нового объекта
    Форма = ПолучитьФорму("Справочник.Контрагенты.ФормаОбъекта");
    
    // 2. Вызываем серверную процедуру для заполнения данных формы
    ЗаполнитьФормуНаСервере(Форма);
    
    // 3. Открываем уже заполненную форму
    Форма.Открыть();
    
КонецПроцедуры

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

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

Способ 3. Создание собственной формы во внешней обработке

Если конфигурацию менять нельзя, а типовая форма ведет себя слишком «умно» (скрывает элементы, которые вы хотите заполнить), можно прибегнуть к приему с внешней обработкой. Мы создаем внешнюю обработку, копируем в неё форму нужного справочника и дорабатываем её логику под свои задачи.

Выясним причину, почему это работает: когда мы открываем форму, основной реквизит которой имеет тип СправочникОбъект.ИмяСправочника, платформа воспринимает её как полноценную форму этого объекта. Мы можем программно вызвать её из нашей основной обработки, заполнить данные любым удобным способом и предоставить пользователю стандартный интерфейс для записи или отмены.

  1. Создаем внешнюю обработку.
  2. Добавляем в неё форму, копируя её из дерева метаданных нужного справочника.
  3. В модуле этой формы или при её открытии реализуем нужную логику заполнения.
  4. Вызываем эту форму программно.

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

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

Проанализировав все доступные варианты, можно сделать следующие выводы:

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

← На главную