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

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

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

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

Рассмотрим ситуацию, когда у нас есть реквизит формы с типом ДанныеФормыКоллекция (который в интерфейсе отображается как таблица). Когда мы обращаемся к свойству Элементы.ИмяТаблицы.ВыделенныеСтроки, платформа возвращает нам массив. Логично предположить, что это массив строк, но здесь кроется главная ловушка управляемого интерфейса.

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

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

Способ 1. Использование метода НайтиПоИдентификатору (Оптимальный)

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

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


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

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

Способ 2. Обработка данных на клиенте без выгрузки

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


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

Обратите внимание: метод Выгрузить() доступен только на сервере. Если вам нужна именно ТаблицаЗначений, контекстный вызов сервера неизбежен.

Нюансы работы с методом РеквизитФормыВЗначение

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

Когда вы выполняете преобразование ДанныеФормыКоллекция в ТаблицаЗначений, создается новый объект в памяти. Идентификаторам из управляемой формы (которые мы получили из Элементы.Таблица.ВыделенныеСтроки) в этой новой таблице ничего не соответствует. Метод Выгрузить() у объекта ТаблицаЗначений также требует массив строк, но это должны быть строки именно этой таблицы значений.

Поэтому правильная стратегия — фильтровать данные, пока они еще находятся в объекте ДанныеФормыКоллекция, и только потом (если нужно) преобразовывать результат в другие типы данных.

Особенности для Динамических списков

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

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

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

Рекомендации по оптимизации

Проанализируем типичные ошибки в коде. Часто можно встретить конструкцию вида ТЗ = Новый ТаблицаЗначений; непосредственно перед присваиванием результата выгрузки. Это избыточно, так как метод Выгрузить() сам инициализирует и возвращает новый объект ТаблицаЗначений.

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

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

← На главную