В разработке на платформе 1С:Предприятие 8.3 (управляемое приложение) часто возникает задача: на основании выбора пользователя в таблице значений (ТЗ) создать документ и заполнить его данными, которые хранятся не только в самой строке таблицы, но и в связанных объектах — например, в табличных частях справочников-спецификаций. Рассмотрим подробно, как правильно реализовать этот механизм, избежав типичных ошибок начинающих разработчиков.
Первая и самая частая сложность заключается в понимании того, что именно возвращает платформа при обращении к выделенным строкам. Проанализируем ситуацию: свойство Элементы.СписокМатериалы.ВыделенныеСтроки возвращает не массив объектов или строк, а массив идентификаторов (уникальных числовых значений), привязанных к строкам формы. В качестве альтернативного способа организации множественного выбора строк подойдёт способ реализации флажков в списке на управляемых формах.
Попытка обратиться напрямую к идентификатору как к объекту (например, ТекСтрока.Спецификация) приведет к ошибке "Значение не является значением объектного типа". Чтобы получить реальные данные, нам необходимо выполнить преобразование идентификатора в данные строки. Разберем, как это сделать правильно в зависимости от контекста выполнения.
Если нам нужно быстро получить ссылку на объект из выделенной строки для последующей передачи на сервер, мы используем метод элемента формы ДанныеСтроки(). Рассмотрим пример реализации клиентской процедуры:
&НаКлиенте
Процедура СоздатьДокументНаОсновании(Команда)
ВыделенныеСтроки = Элементы.СписокМатериалы.ВыделенныеСтроки;
Если ВыделенныеСтроки.Количество() = 0 Тогда
ПоказатьПредупреждение(, "Не выбрано ни одной строки!");
Возврат;
КонецЕсли;
// Создаем массив ссылок для передачи на сервер
МассивСпецификаций = Новый Массив;
Для Каждого ИдентификаторСтроки Из ВыделенныеСтроки Цикл
ДанныеСтроки = Элементы.СписокМатериалы.ДанныеСтроки(ИдентификаторСтроки);
Если ДанныеСтроки <> Неопределено Тогда
МассивСпецификаций.Добавить(ДанныеСтроки.Спецификация);
КонецЕсли;
КонецЦикла;
СоздатьЗаказНаСервере(МассивСпецификаций);
КонецПроцедуры
Основная работа с объектами базы данных (создание документов, чтение табличных частей) должна происходить в серверном контексте. Важно помнить: на сервере объект Элементы недоступен. Поэтому, если мы передали на сервер массив идентификаторов, нам нужно использовать метод коллекции данных формы НайтиПоИдентификатору().
Проанализируем пример серверной функции, которая создает документ ЗаказМатериаловВПроизводство и заполняет его табличную часть данными из спецификаций:
&НаСервере
Функция СоздатьЗаказНаСервере(МассивСпецификаций)
НовыйДок = Документы.ЗаказМатериаловВПроизводство.СоздатьДокумент();
НовыйДок.Дата = ТекущаяДата();
// Заполняем основные реквизиты
НовыйДок.Статус = Перечисления.СтатусыЗаказовМатериаловВПроизводство.КОбеспечению;
// Обходим массив переданных ссылок на спецификации
Для Каждого СсылкаНаСпецификацию Из МассивСпецификаций Цикл
// Получаем данные табличной части спецификации
// Важно: обращение через точку к ТЧ справочника на сервере допустимо,
// так как платформа автоматически прочитает объект из базы.
Для Каждого СтрСпецификации Из СсылкаНаСпецификацию.МатериалыИУслуги Цикл
НоваяСтрока = НовыйДок.Товары.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрСпецификации);
// Если имена колонок отличаются, заполняем вручную
НоваяСтрока.Количество = СтрСпецификации.КоличествоУпаковок;
КонецЦикла;
КонецЦикла;
НовыйДок.Записать();
Возврат НовыйДок.Ссылка;
КонецФункции
Рассмотрим ситуацию, когда пользователь выбрал 100 строк. Если в цикле обращаться к СсылкаНаСпецификацию.МатериалыИУслуги, платформа выполнит 100 отдельных запросов к базе данных. Чтобы ускорить работу, выясним, как получить данные одним запросом.
Рекомендуется собрать все ссылки в массив и передать их в запрос, который выберет все необходимые материалы разом. Это значительно повысит производительность системы.
Строка.Номенклатура = Стр.Номенклатура), используйте функцию ЗаполнитьЗначенияСвойств(Получатель, Источник). Она автоматически сопоставит поля с одинаковыми именами.ОбработкаЗаполнения в модуле объекта создаваемого документа. Это позволит централизовать логику и использовать метод НовыйДок.Заполнить(ДанныеОснования).Выяснив эти нюансы, мы можем сделать вывод: правильная работа с таблицами в управляемом приложении строится на четком разделении идентификаторов интерфейса и ссылок на данные. Проанализировав выделенные строки на клиенте и передав массив ссылок на сервер, мы получаем надежный и производительный код для формирования любых документов на основании пользовательского выбора. Для динамического отображения таких табличных данных в интерфейсе подойдёт решение для программного вывода произвольной таблицы значений на управляемую форму.