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

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

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

Проблема модальных окон и современный подход

Раньше в 1С широко использовался метод ОткрытьФормуМодально(). Он останавливал выполнение кода до тех пор, пока пользователь не закроет окно. В современных конфигурациях (особенно в веб-клиенте) такой подход запрещен. Платформа выдает ошибку, требуя использовать асинхронные вызовы. Мы разберем, как разделить процесс заполнения на два этапа: инициация выбора и обработка результата.

Шаг 1. Открытие формы выбора (Клиентский контекст)

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

Рассмотрим пример кода для команды заполнения:


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

Обратим внимание на параметр РежимОткрытияОкнаФормы.БлокироватьОкноВладельца. Он позволяет сделать работу пользователя более предсказуемой, не давая редактировать основной документ, пока выбор не завершен.

Шаг 2. Обработка результата выбора

Теперь создадим экспортную процедуру, имя которой мы указали в ОписаниеОповещения. Выясним причину, по которой это важно: именно здесь мы получим ссылку на выбранный документ в переменной Результат.


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

Важный нюанс: метод КопироватьДанныеФормы необходим, так как на сервере мы работаем с преобразованной структурой, и нам нужно «вернуть» изменения в интерфейс пользователя.

Шаг 3. Реализация логики заполнения на сервере

Переходим к самой ответственной части — получению данных из выбранного документа. Проанализируем ситуацию: нам нужно прочитать табличную часть другого документа и загрузить её в наш. Использование запроса — самый производительный метод.


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

Дополнительные возможности оптимизации

Рассмотрим подробнее несколько моментов, которые сделают ваше решение профессиональным:

  1. Фильтрация при выборе: Чтобы пользователю было проще искать документ, в процедуре ВыполнитьКоманду можно настроить отбор. Например, показывать документы только по конкретному контрагенту. Для этого в функцию ОткрытьФорму передается структура параметров с ключом Отбор.
  2. Множественный выбор: Если нужно выбрать сразу несколько документов-оснований, установите параметр МножественныйВыбор = Истина. В этом случае в обработку оповещения придет не одна ссылка, а массив.
  3. Работа во внешних обработках: Если вы делаете внешнюю обработку заполнения ТЧ для типовой конфигурации (на базе БСП), используйте стандартный экспортный метод ВыполнитьКоманду. В этом случае ВладелецФормы будет доступен через параметры, передаваемые подсистемой.

Разберем пример с передачей отбора:


ПараметрыВыбора = Новый Структура;
СтруктураОтбора = Новый Структура("Контрагент, Проведен", Объект.Контрагент, Истина);
ПараметрыВыбора.Вставить("Отбор", СтруктураОтбора);

ОткрытьФорму("Документ.ПриобретениеТоваровУслуг.ФормаВыбора", ПараметрыВыбора, , , , , ОписаниеОповещения);

Проверка модифицированности

Никогда не забывайте устанавливать ЭтаФорма.Модифицированность = Истина; после программного изменения данных. Если этого не сделать, пользователь может случайно закрыть документ, и платформа не предупредит его о том, что данные были изменены, но не сохранены. Это одна из самых частых ошибок начинающих разработчиков при работе с методами КопироватьДанныеФормы или ЗначениеВДанныеФормы.

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

← На главную