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

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

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

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

Критическая ошибка из обсуждений на форумах

Рассмотрим код, к которому часто приходят разработчики в процессе обсуждения:


Для каждого СтрокаТЧ Из Элементы.ТабличноеПолеНаФорме.ВыделенныеСтроки Цикл
    Сообщить("Строка номер " + СтрокаТЧ.НомерСтроки);
КонецЦикла;

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

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

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

Решение 1. Получение данных выделенных строк на клиенте (&НаКлиенте)

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

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


&НаКлиенте
Процедура ОбработатьВыделенныеСтрокиНаКлиенте()
    
    // Получаем элемент формы, отображающий таблицу
    ТаблицаФормы = Элементы.ТабличнаяЧастьТовары;
    
    // Получаем массив идентификаторов выделенных строк
    МассивИдентификаторов = ТаблицаФормы.ВыделенныеСтроки;
    
    // Проверяем, выбрано ли хоть что-нибудь
    Если МассивИдентификаторов.Количество() = 0 Тогда
        ПоказатьПредупреждение(, "Пожалуйста, выделите хотя бы одну строку в таблице!");
        Возврат;
    КонецЕсли;
    
    // Обходим массив идентификаторов и извлекаем данные для каждого из них
    Для Каждого Идентификатор Из МассивИдентификаторов Цикл
        
        ДанныеСтроки = ТаблицаФормы.ДанныеСтроки(Идентификатор);
        
        // Теперь нам доступны любые реквизиты и колонки этой строки
        ИмяТовара = ДанныеСтроки.Номенклатура;
        КоличествоТовара = ДанныеСтроки.Количество;
        
        ОбщегоНазначенияКлиентСервер.СообщитьПользователю(
            НСтр("ru = 'Выбрана номенклатура: " + ИмяТовара + " в количестве " + КоличествоТовара + "'")
        );
        
    КонецЦикла;
    
КонецПроцедуры

Обратите внимание: метод ДанныеСтроки() доступен исключительно на клиенте. Попытка вызвать его в серверном контексте вызовет ошибку компиляции.

Решение 2. Получение данных выделенных строк на сервере (&НаСервере)

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

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

Для поиска строки по её идентификатору на сервере применяется метод НайтиПоИдентификатору(). Рассмотрим пример реализации такой связки:


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

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

Решение 3. Как выгрузить выделенные строки в Таблицу Значений (ТЗ) на сервере

Распространенная задача — не просто перебрать строки, а получить из них полноценный объект ТаблицаЗначений на сервере, чтобы затем передать его в качестве параметра в запрос или использовать для пакетной обработки данных.

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

Объект.Товары.Выгрузить(Элементы.ТабличнаяЧастьТовары.ВыделенныеСтроки).

Этот код вызовет ошибку несоответствия типов, так как метод Выгрузить() ожидает на вход массив реальных **объектов строк** коллекции (типа ДанныеФормыЭлементКоллекции), а не массив числовых идентификаторов.

Разберем правильный алгоритм выгрузки выделенных строк в отдельную ТаблицуЗначений:


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

Важная настройка формы: Режим выделения

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

Выполним следующую настройку:

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

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

Резюме: разница между Обычными и Управляемыми формами

Почему возникает путаница среди разработчиков? Дело в том, что в старых версиях платформы (1С 8.1 и на обычных формах в 1С 8.2) свойство ВыделенныеСтроки табличного поля возвращало массив реальных строк табличной части. Старый код, аналогичный приведенному в начале статьи, там успешно работал.

В современных управляемых формах (1С 8.2 / 8.3 / 8.4) ради оптимизации трафика между клиентом и сервером платформа оперирует исключительно легкими идентификаторами. Запомните это важное различие и всегда используйте методы-декодеры: ДанныеСтроки() для клиентских процедур и НайтиПоИдентификатору() для серверных вычислений.

← На главную