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

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

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

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

Вызов формы выбора с поддержкой множественного выделения

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

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

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

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


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

Обработка выбранных значений на клиенте

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

Разберем клиентскую процедуру-обработчик:


&НаКлиенте
Процедура ПолучитьМассивЗначенийВыбора(ВыбранныеЗначения, ДополнительныеПараметры) Экспорт
    
    Если ВыбранныеЗначения <> Неопределено И ТипЗнч(ВыбранныеЗначения) = Тип("Массив") Тогда
        ЗаполнитьПоЗаказамПоставщикаНаСервере(ВыбранныеЗначения);
    КонецЕсли;
    
КонецПроцедуры

Заполнение табличной части на сервере

Главная задача при обработке на сервере — правильно обратиться к данным и внести изменения в реквизит формы Объект.

Анализируя частые ошибки разработчиков, стоит отметить попытку выполнить вызов метода ПолучитьОбъект() и последующую запись через Записать() прямо в модуле формы. Проанализируем, почему делать так нельзя:

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

2. Лишние операции с базой: Заполняя данные на сервере, достаточно изменить коллекцию Объект.ТабличнаяЧасть. Запись документа должен производить сам пользователь интерактивно по кнопке «Записать» или «Провести».

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


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

Разбор распространенных ошибок

При реализации данного функционала начинающие разработчики могут столкнуться со следующими проблемами:

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

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

← На главную