Как получить данные выделенных строк динамического списка в 1С?

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

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

Вариант 1. Сбор данных на клиенте через метод ДанныеСтроки (с последующей передачей на сервер)

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

Посмотрим на пример клиентского кода и серверного обработчика:


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

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

Проанализируем скрытые риски и ограничения этого подхода:

  1. Проблема с кэшем клиента и возврат Неопределено: Метод ДанныеСтроки() возвращает данные только для тех строк, которые уже загружены в клиентский кэш. Если пользователь выделил диапазон с помощью клавиш Shift или выделил весь список комбинацией Ctrl+A, для строк за пределами видимой области метод вернет Неопределено, что приведет к ошибке при обращении к свойствам.
  2. Зависимость от состава колонок: Метод возвращает только те поля, которые физически присутствуют на форме. Если реквизит скрыт или удален пользователем через настройки формы, он не будет получен. Для обязательного чтения поля в свойствах динамического списка необходимо взводить флаг Использовать всегда.
  3. Избыточный трафик между клиентом и сервером: Упаковка полной структуры данных на клиенте и передача громоздкого соответствия или массива по сети замедляет работу при медленном интернет-соединении.

Вариант 2. Оптимальный способ: передача массива идентификаторов и запрос на сервере

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

Разберем по шагам реализацию этого способа:


&НаКлиенте
Процедура КомплектоватьОптимально(Команда)
    
    МассивСсылок = Элементы.Заявки.ВыделенныеСтроки;
    
    Если МассивСсылок.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;
    
    КомплектоватьОптимальноНаСервере(МассивСсылок);
    
КонецПроцедуры

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

Особенности списков без основной таблицы

Рассмотрим ситуацию, когда динамический список построен на основе сложного запроса без указания основной таблицы (например, с объединениями или группировками):

  1. В таком случае коллекция ВыделенныеСтроки будет содержать не прямые ссылки Ссылка, а системные структуры или ключи строк.
  2. Для корректной работы обязательно проверьте в свойствах динамического списка заполнение свойства Ключ строки — укажите там уникальное поле (или набор полей), по которому однозначно определяется строка.
  3. На сервере распакуйте полученные ключи и передайте их параметром в запрос для точной выборки записей.

Использование серверного запроса по массиву ВыделенныеСтроки гарантирует надежное получение данных любого объема без ограничений видимой области и существенно сокращает объем программного кода.

← На главную