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

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

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

Проблема идентификаторов: разница между строкой и ее индексом

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

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

Способ 1. Получение данных на стороне клиента

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


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

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

Способ 2. Обработка данных на стороне сервера

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

Проанализируем пример серверной функции, которая создает документ ЗаказМатериаловВПроизводство и заполняет его табличную часть данными из спецификаций:


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

Оптимизация работы: избегаем проблемы N+1 запроса

Рассмотрим ситуацию, когда пользователь выбрал 100 строк. Если в цикле обращаться к СсылкаНаСпецификацию.МатериалыИУслуги, платформа выполнит 100 отдельных запросов к базе данных. Чтобы ускорить работу, выясним, как получить данные одним запросом.

Рекомендуется собрать все ссылки в массив и передать их в запрос, который выберет все необходимые материалы разом. Это значительно повысит производительность системы.

Важные рекомендации по работе с объектами

  1. Использование ЗаполнитьЗначенияСвойств(): Вместо того чтобы вручную прописывать каждую колонку (Строка.Номенклатура = Стр.Номенклатура), используйте функцию ЗаполнитьЗначенияСвойств(Получатель, Источник). Она автоматически сопоставит поля с одинаковыми именами.
  2. Механизм Заполнить(): Вместо ручного заполнения реквизитов внутри обработки, рассмотрите возможность использования процедуры ОбработкаЗаполнения в модуле объекта создаваемого документа. Это позволит централизовать логику и использовать метод НовыйДок.Заполнить(ДанныеОснования).
  3. Контроль контекста: Никогда не пытайтесь передать "строку таблицы формы" с клиента на сервер. Передавайте либо простые типы (числа, строки), либо ссылки на объекты базы данных.
  4. УстановитьСсылкуНового(): Этот метод, упомянутый в обсуждении, нужен только если вам требуется знать будущую ссылку документа еще до его записи (например, для генерации штрихкода, зависящего от GUID). В обычных задачах переноса данных он избыточен.

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

← На главную