На самом деле нет необходимости три раза «дергать» сервер. Ведь мы точно знаем, что каждый раз при добавлении нового товара нам понадобятся все три его реквизита. А значит, все их можно получить за один серверный вызов. Это будет более эффективным решением.
В данном случае универсальность выбранного нами решения нужно принести в жертву эффективности работы конкретной формы в конкретной ситуации. В данной ситуации прежде всего нас должна заботить не универсальность, а прикладная логика работы формы. Универсальность сама по себе хороша, но не в данном случае. То есть нет одного решения на все времена. В каждой форме нужно думать заново.
Для реализации этого решения в обработчике события ПриИзменении() поля Товар табличной части документа ПриходнаяНакладная нужно вызвать функцию, возвращающую в виде структуры сразу все нужные нам реквизиты выбранного элемента. Поэтому в модуле формы документа поместим функцию ПолучитьРеквизитыТовара(), выполняющуюся на сервере без контекста формы (листинг 4.5).
Листинг 4.5. Функция «ПолучитьРеквизитыТовара()»
&НаСервереБезКонтекста
Функция ПолучитьРеквизитыТовара(Ссылка)
РеквизитыТовара = Новый Структура;
РеквизитыТовара.Вставить("Артикул", Ссылка.Артикул);
РеквизитыТовара.Вставить("ЕдиницаИзмерения", Ссылка.ЕдиницаИзмерения);
РеквизитыТовара.Вставить("Цена", Ссылка.Цена);
Возврат РеквизитыТовара;
КонецФункции
В этой функции мы создаем структуру и заполняем ее поля Артикул, ЕдиницаИзмерения и Цена значениями соответствующих реквизитов справочника Товары, полученных по ссылке на элемент справочника.
Единственное значение данных формы, которое нам понадобится в этой функции, – это ссылка на элемент справочника, его мы передаем в параметре Ссылка. Поэтому мы выполняем внеконтекстный серверный вызов (директива компиляции &НаСервереБезКонтекста), который будет работать значительно быстрее, чем вызов сервера с контекстом формы (директива компиляции &НаСервере). Подробнее этот вопрос будет рассмотрен в .
Как видите, функция будет совершенно не универсальная, зато форма будет работать быстро за счет минимизации серверных вызовов. То есть вместо трех вызовов сервера, как раньше, будет происходить всего один серверный вызов.
Теперь изменим обработчик события ПриИзменении() поля Товар табличной части документа ПриходнаяНакладная следующим образом (листинг 4.6).
Листинг 4.6. Процедура «ТоварыТоварПриИзменении()»
&НаКлиенте
Процедура ТоварыТоварПриИзменении(Элемент)
ДанныеТекущейСтроки = Элементы.Товары.ТекущиеДанные;
ВыбранныйТовар = ДанныеТекущейСтроки.Товар;
РеквизитыТовара = ПолучитьРеквизитыТовара(ВыбранныйТовар);
ДанныеТекущейСтроки.Артикул = РеквизитыТовара.Артикул;
ДанныеТекущейСтроки.ЕдИзм = РеквизитыТовара.ЕдиницаИзмерения;
ДанныеТекущейСтроки.Цена = РеквизитыТовара.Цена;
КонецПроцедуры
В этом обработчике мы передаем ссылку на выбранный товар в функцию ПолучитьРеквизитыТовара(), которая возвращает в виде структуры реквизиты товара, и присваиваем значение полей возвращенной структуры колонкам табличной части Артикул, ЕдИзм и Цена.
ПРИМЕЧАНИЕ
Этот пример можно посмотреть в демонстрационной конфигурации «01 (вар. 2) Объединение нескольких вызовов сервера в один».
Запустим «1С:Предприятие», откроем приходную накладную и сделаем выбор из справочника товаров в колонке Товар табличной части документа. После этого колонки табличной части Артикул, ЕдИзм и Цена будут автоматически заполнены соответствующими значениями из справочника Товары (рис. 4.19).

Рис. 4.19. Заполнение колонок табличной части в приходной накладной
Как мы видим, функциональность прикладного решения будет такой же, как и в первом случае, но производительность будет втрое выше, так как при выборе товара в одной строке табличной части документа будет произведено только одно обращение к серверу (рис. 4.20).

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