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