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