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

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

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

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

Анализируем типичную ошибку: почему ТекущиеДанные подводят?

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

  1. Асинхронность интерфейса: Установка свойства ТекущаяСтрока инициирует процесс перепозиционирования в визуальном элементе. Платформа не гарантирует, что объект ТекущиеДанные обновится мгновенно в ту же микросекунду, когда выполняется следующая строка кода в цикле.
  2. Избыточные вызовы: Каждое изменение текущей строки заставляет форму пытаться перерисоваться и, в некоторых случаях, запрашивать дополнительные данные с сервера. Это создает колоссальную нагрузку на клиентское приложение.
  3. Ограничение кэша: Динамический список — это не таблица в памяти, а механизм «ленивой» подгрузки данных. Он хранит на клиенте только те записи, которые видны на экране или находятся рядом. При попытке прыгнуть программно на строку, которая еще не подгружена, данные могут просто не успеть прийти.

Посмотрим на пример кода, который работать не будет (или будет работать некорректно):


// ОШИБОЧНЫЙ ПРИМЕР
Для каждого Строка из Элементы.Список.ВыделенныеСтроки Цикл
    Элементы.Список.ТекущаяСтрока = Строка; // Попытка заставить список сменить строку
    Данные = Элементы.Список.ТекущиеДанные; // Получаем данные, но они всё еще от старой строки!
    Если Данные.Автор = ТекущийПользователь Тогда
        // ... логика ...
    КонецЕсли;
КонецЦикла;

Решение №1: Использование метода ДанныеСтроки на клиенте

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

Разберем правильный алгоритм работы на стороне клиента:


&НаКлиенте
Функция ПроверитьАвторствоЗаписей()
    ЯвляетсяАвтором = Истина;
    ВыдСтроки = Элементы.КомментарииПоХронологии.ВыделенныеСтроки;
    ТекПользователь = ПользователиКлиентСервер.ТекущийПользователь();

    Для каждого ИдентификаторСтроки из ВыдСтроки Цикл
        // Получаем данные конкретной строки по её ID
        НужныеДанные = Элементы.КомментарииПоХронологии.ДанныеСтроки(ИдентификаторСтроки);
        
        // Важно проверить, что данные получены (не Неопределено)
        Если НужныеДанные <> Неопределено Тогда
            Если НужныеДанные.Автор <> ТекПользователь Тогда
                ЯвляетсяАвтором = Ложь;
                Прервать; // Если нашли хотя бы одну чужую запись, проверка не пройдена
            КонецЕсли;
        Иначе
            // Данные могут быть не подгружены в кэш клиента
            // В этом случае лучше использовать серверный метод
        КонецЕсли;
    КонецЦикла;

    Возврат ЯвляетсяАвтором;
КонецФункции

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

Решение №2: Надежный метод через серверный запрос (рекомендуется)

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

Алгоритм действий будет следующим:

  1. Собрать массив идентификаторов выделенных строк на клиенте.
  2. Передать этот массив в серверную функцию.
  3. На сервере выполнить запрос к источнику данных (регистру или таблице), используя условие ГДЕ Ссылка В (&МассивИдентификаторов).

Рассмотрим пример реализации:


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

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

Почему не стоит переводить список в Таблицу Значений?

Иногда в обсуждениях можно встретить совет: «Выгрузите динамический список в таблицу значений и обходите её». Посмотрим на этот совет критически. У объекта ДинамическийСписок на клиенте нет метода Выгрузить(). Чтобы получить содержимое списка на сервере, вам придется программно исполнять схему компоновки данных, что является крайне ресурсоемкой операцией.

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

Подведем итоги

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

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

← На главную