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