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

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

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

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

Выясняем причину ошибки: почему выбирается только одна строка?

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


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

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

Критическая ошибка заключается в неверной вложенности параметров. Параметры МножественныйВыбор и ЗакрыватьПриВыборе являются системными параметрами самой управляемой формы выбора. Они должны находиться на самом верхнем уровне структуры ПараметрыФормы. Помещая их внутрь структуры ПараметрыОтбора, разработчик указывает платформе искать в динамическом списке документов поля с именами "ЗакрыватьПриВыборе" и "МножественныйВыбор" и пытаться отфильтровать по ним данные, что приводит к неработоспособности механизма множественного подбора.

Решение 1. Правильная передача параметров формы выбора

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


&НаКлиенте
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначенияМассив) Экспорт
    // 1. Формируем структуру отбора данных (будут показаны только проведенные документы)
    ПараметрыОтбора = Новый Структура;
    ПараметрыОтбора.Вставить("Проведен", Истина);
    
    // 2. Создаем структуру параметров открываемой формы
    ПараметрыФормы = Новый Структура;
    
    // Передаем отбор
    ПараметрыФормы.Вставить("Отбор", ПараметрыОтбора);
    
    // ВКЛЮЧАЕМ МНОЖЕСТВЕННЫЙ ВЫБОР (на верхнем уровне структуры!)
    ПараметрыФормы.Вставить("МножественныйВыбор", Истина);
    
    // Указываем, должна ли форма закрыться сразу после первого выбора
    ПараметрыФормы.Вставить("ЗакрыватьПриВыборе", Ложь); 
    
    // 3. Открываем форму с описанием обработчика оповещения
    ОписаниеОповещения = Новый ОписаниеОповещения("ВыполнитьПослеВыбора", ЭтаФорма);
    
    ОткрытьФорму(
        "Документ.РеализацияТоваровУслуг.ФормаВыбора", 
        ПараметрыФормы, 
        ЭтаФорма,
        ,,, 
        ОписаниеОповещения, 
        РежимОткрытияОкнаФормы.БлокироватьОкноВладельца
    );                         
КонецПроцедуры

В данном примере параметр ЗакрыватьПриВыборе = Ложь позволяет пользователю последовательно выбирать разные группы документов, не закрывая окно подбора. Если вам требуется, чтобы пользователь выделил область строк (зажав Shift или Ctrl) и при нажатии кнопки "Выбрать" окно закрылось, передайте в параметр ЗакрыватьПриВыборе значение Истина.

Безопасная обработка результата выбора

При использовании множественного выбора платформа может возвращать результат в различных форматах в зависимости от поведения пользователя в интерфейсе:

  1. Если пользователь выделил несколько документов и нажал кнопку "Выбрать", возвращается значение с типом Массив.
  2. Если пользователь выбрал только один документ (например, двойным кликом), платформа в зависимости от настроек формы может вернуть одиночную ссылку типа ДокументСсылка.РеализацияТоваровУслуг вместо массива.
  3. Если пользователь закрыл форму без выбора, возвращается значение Неопределено.

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


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

Решение 2. Особенности настройки кастомных форм выбора

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

Рассмотрим пошагово, на что обратить внимание в форме выбора:

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

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


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // Проверяем, передан ли параметр из вызывающей формы
    Если Параметры.Свойство("МножественныйВыбор") Тогда
        Элементы.Список.МножественныйВыбор = Параметры.МножественныйВыбор;
    КонецЕсли;
КонецПроцедуры

Решение 3. Использование временного хранилища для сложных структур данных

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

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

Давайте разберем по шагам, как построить такое взаимодействие:

Шаг 1. Подготовка данных в форме выбора (подбора)

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


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

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

Шаг 2. Получение и обработка данных в вызывающей форме

Теперь в форме документа-приемника мы принимаем адрес временного хранилища, переходим на сервер, извлекаем готовую таблицу и быстро заполняем нашу табличную часть.


// Код в модуле вызывающей формы (документа-приемника)
&НаКлиенте
Процедура ВыполнитьПослеВыбора(ВыбранноеЗначение, ДополнительныеПараметры) Экспорт
    
    Если ВыбранноеЗначение = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Проверяем, вернулся ли нам адрес временного хранилища (это всегда строка)
    Если ЭтоАдресВременногоХранилища(ВыбранноеЗначение) Тогда
        ЗаполнитьТабличнуюЧастьИзХранилища(ВыбранноеЗначение);
    КонецЕсли;
    
КонецПроцедуры

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

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

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

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

← На главную