Уважаемые форумчане вот код в модуле УФ:

```1c
    &НаКлиенте
    Процедура ТоварыТоварПриИзменении(Элемент)
    Стр = ПолучитьТекущуюСтрокуТовары();
    Стр.ЭтоУслуга = ЭтоУслуга(Стр.Товар);
    Стр.Цена = ПолучитьЦенуТовара(Объект.Дата, Стр.Товар, Объект.ВидЦен);
    Стр.Количество = ?(Стр.ЭтоУслуга ИЛИ Стр.Количество = 0, 1, Стр.Количество);
    Стр.ЕдИзм = РаботаСОбъектами.ПолучитьРеквизитИзБазыДанных(Стр.Товар,"ЕдИзм");
    Стр.Сумма = Стр.Количество * Стр.Цена;
    ЗаполнитьДополнительныеДанныеСтроки(Стр);

    Если Остатки Тогда
    ДанныеОбъекта = Новый Структура("Товар,Период",Стр.Товар,Объект.Дата);
    ПолучитьОстатки(ДанныеОбъекта);
    КонецЕсли;

    КонецПроцедуры

    &НаСервере
    Процедура ПолучитьОстатки(ДанныеОбъекта)

    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    | ТоварныеЗапасыОстатки.Товар,
    | ТоварныеЗапасыОстатки.Склад,
    | ТоварныеЗапасыОстатки.КоличествоОстаток,
    | ТоварныеЗапасыОстатки.Товар.ЕдИзм КАК ЕдИзм
    |ИЗ
    | РегистрНакопления.ТоварныеЗапасы.Остатки(&Период, ) КАК ТоварныеЗапасыОстатки
    |ГДЕ
    | ТоварныеЗапасыОстатки.Товар = &Товар";

    Запрос.УстановитьПараметр("Период", ДанныеОбъекта.Период);
    Запрос.УстановитьПараметр("Товар", ДанныеОбъекта.Товар);

    РезультатЗапроса = Запрос.Выполнить();

    Выборка = РезультатЗапроса.Выбрать();

    Пока Выборка.Следующий() Цикл
    ОстатокТовара = Выборка.КоличествоОстаток;
    КонецЦикла;
    ЭлементТаблицы = РеквизитФормыВЗначение("Объект");
    ЭлементТаблицы.РасчитатьОстаток(ОстатокТовара);
    ЗначениеВРеквизитФормы(ЭлементТаблицы,"Объект");

    КонецПроцедуры

    это код в модуле объекта:

    Процедура РасчитатьОстаток(ПолученныйОстаток) Экспорт
    Для Каждого СтрОстатка из Товары Цикл
    СтрОстатка.Остаток = ПолученныйОстаток;
    КонецЦикла;
    КонецПроцедуры
```

все отрабатывает без проблем, но мне кажется что код "тяжеловат" посмотрите пожалуйста правильно ли я все сделал? можно ли его оптимизировать?
с Уважением Дамир
---
1. Нужно заполнять все зависимые реквизиты через 1 серверный вызов.
Посмотрите примеры в типовых конфигурациях. Правда там ещё и текущая строка кешируется.
2. Неоптимальный запрос получения остатков.
3. Заполнить поле таблицы товаров можно и без РеквизитФормыВЗначение().
---
Чтобы получить строку табличной части как прикладной тип в модуле формы нужно воспользоваться РеквизитФормыВЗначение(); Тут оно не нужно.
НайтиПоИдентификатору() возвращает элемент коллекции данных формы, это и есть ТекущиеДанные. В данном примере нет смысла.
Тут нужно передать на сервер текущие данные строки (через любую сериализируемую коллекцию, обычно структуру), далее заполнить её, вернуть на клиент и заполнить текущие данные строки.

```1c
    &НаКлиенте
    Процедура ТоварыТоварПриИзменении(Элемент)
    СтруктураСтроки = Новый Структура("Номенклатура, Цена, Количество");
    ЗаполнитьЗначениеСвойств(СтруктураСтроки, Элементы.Товары.ТекущиеДанные);
    ЗаполнитьРеквизитыНоменклатурыНаСервере(СтруктураСтроки); // тут из номенклатуры получим все что нужно.
    ЗаполнитьЗначениеСвойств(Элементы.Товары.ТекущиеДанные, СтруктураСтроки);
    КонецПроцедуры
```

Примеры есть тут: https://its.1c.ru/db/pubv8devui#content:284:hdoc
---
а если &НаСервере заменить на &НаСервереБезКонтекста будет еще лучше.
И цену можно будет в основном запросе получить. Так вместо 2 запросов, будет только 1 запрос.
---
Почти каждая строка процедуры на клиенте вызывает серверную процедуру. Так делать не стоит. Если нужен серверный вызов, так сделайте одну серверную процедуру, выполните в ней все что нужно за один раз.
---
какая-то ересь, вот здесь

```1c
    Процедура РасчитатьОстаток(ПолученныйОстаток) Экспорт
    Для Каждого СтрОстатка из Товары Цикл
    СтрОстатка.Остаток = ПолученныйОстаток;
    КонецЦикла;
    КонецПроцедуры
```

вы передаете в процедуру единственное значение (поскольку процедура вызывается после цикла) и перезаполняете им всю таблицу товары.

И зачем это в модуле, это прекрасно работает как Объект.Товары
---
Товары это табличная часть документа , в модуле формы у меня не получилось присвоить значение ПолученныйОстаток реквизиту Объект.Товары.Остаток, как мне это грамотно сделать?

вот так что ли?
в модуле формы:

```1c
    Для Каждого СтрОстатка из Объект.Товары Цикл
    СтрОстатка.Остаток = ОстатокТовара;
    КонецЦикла;
```
---
это я понял, так и не ясно, зачем вы при изменении строки товара в форме перезаполняете остатками всю табличную часть...
Вам надо в процедуре Процедура ТоварыТоварПриИзменении(Элемент) НаКлиенте найти нужную строку
 ТекущиеДанные = Элементы.Товары.ТекущиеДанные;
 идентификатор = ТекущиеДанные.ПолучитьИдентификатор();
затем в модуле формы в процедуру НаСервере передать идентификатор и получить реальную строку таблицы Товары
 товар = Объект.Товары.НайтиПоИдентификатору(идентификатор);
а дальше делайте с ней все что нужно в модуле формы
---
Вам надо в процедуре Процедура ТоварыТоварПриИзменении(Элемент) НаКлиенте найти нужную строку
ТекущиеДанные = Элементы.Товары.ТекущиеДанные;
идентификатор = ТекущиеДанные.ПолучитьИдентификатор();
затем в модуле формы в процедуру НаСервере передать идентификатор и получить реальную строку таблицы Товары
товар = Объект.Товары.НайтиПоИдентификатору(идентификатор);
Зачем искать строку по идентификатору, если ТекущиеДанные и есть эта строка? =\
---
С большой долей вероятности в текущих данных есть все реквизиты строки таблицы :)
---
текущие данные не строка, в них есть данные строки (и еще некоторые), это да. Если надо делать какие-то вычисления на сервере, не доступные на клиенте, то надо оперировать строкой табличной части, а не строкой элемента, ТекущиеДанные на сервере не доступны
---
для передачи на сервер используют конвертацию в структуру/массив/список
---
зачем городить структуру, если можно передать идентификатор и получить строку табличной части? в чем плюс?
---
Чтобы получить строку табличной части как прикладной тип в модуле формы нужно воспользоваться РеквизитФормыВЗначение(); Тут оно не нужно.
НайтиПоИдентификатору() возвращает элемент коллекции данных формы, это и есть ТекущиеДанные. В данном примере нет смысла.
Тут нужно передать на сервер текущие данные строки (через любую сериализируемую коллекцию, обычно структуру), далее заполнить её, вернуть на клиент и заполнить текущие данные строки.

```1c
    &НаКлиенте
    Процедура ТоварыТоварПриИзменении(Элемент)
    СтруктураСтроки = Новый Структура("Номенклатура, Цена, Количество");
    ЗаполнитьЗначениеСвойств(СтруктураСтроки, Элементы.Товары.ТекущиеДанные);
    ЗаполнитьРеквизитыНоменклатурыНаСервере(СтруктураСтроки); // тут из номенклатуры получим все что нужно.
    ЗаполнитьЗначениеСвойств(Элементы.Товары.ТекущиеДанные, СтруктураСтроки);
    КонецПроцедуры
```

Примеры есть тут: https://its.1c.ru/db/pubv8devui#content:284:hdoc
---
Фигней вы страдаете.
Данные уже есть на сервере, в строке таблицы, которую по идентификатору можно найти на сервере и на сервере же заполнить. То есть достаточно в серверную процедуру передать идентификатор строки. Ничего более.

Вы же предлагаете зачем - то в левую структуру копировать значения, тащить ее на сервер, заполнять эту структуру возвращать на клиент. Копировать обратно.
Ваш вариант имеет смысл только в одном случае - когда серверная процедура без контекста.
Если серверная процедура контекстная, объясните ЗАЧЕМ это нужно делать? Что бы что?
---
Все правильно, контекст тут и не нужен.
Считаешь, что лучше всю форму передать ради заполнения нескольких полей 1 строки таблицы?!:) Хы
---
Все правильно, контекст тут и не нужен.
Вот! Это главное уточнение. Без этого уточнения ваша рекомендация - странная дичь.
С этим уточнением ваша рекомендация - оптимизация работы формы =)

(16)Вы этим что-то конкретное хотели сказать?
---
Не понял вопроса.
Я скинул ссылку на пример: https://its.1c.ru/db/pubv8devui#content:286:1
Там есть обоснование.
Рекомендация была по конкретному примеру. Дичи не обнаружил.
---
Не понял вопроса.
Цитатой СП вы что хотели сказать?

Дичи не обнаружил.
Видишь суслика? А он есть. (с)
---
если честно, лень городить пример, но работает так как я написал.
НайтиПоИдентификатору() возвращает строку табличной части объекта, а не формы.
---
Запустил конф не поленился:
---
1. Нужно заполнять все зависимые реквизиты через 1 серверный вызов.
Посмотрите примеры в типовых конфигурациях. Правда там ещё и текущая строка кешируется.
2. Неоптимальный запрос получения остатков.
3. Заполнить поле таблицы товаров можно и без РеквизитФормыВЗначение().
---
Переделал вот так

```1c
    &НаКлиенте
    Процедура ТоварыТоварПриИзменении(Элемент)
    Стр = ПолучитьТекущуюСтрокуТовары();
    СтруктураДанных = Новый Структура();
    СтруктураДанных.Вставить("Дата",Объект.Дата);
    СтруктураДанных.Вставить("Товар",Стр.Товар);
    СтруктураДанных.Вставить("ВидЦен",Объект.ВидЦен);
    СтруктураДанных.Вставить("Остаток",Остатки);
    ДанныеТовара = ПолучитьСтруктуруДанныхТовара(СтруктураДанных);
    Стр.Цена = ДанныеТовара.ЦенаТовара.Цена;
    Стр.Количество = ?(Стр.Количество = 0, 1, Стр.Количество);
    Стр.ЕдИзм = ДанныеТовара.ЕдИзм;
    Стр.Сумма = Стр.Количество * Стр.Цена;
    Стр.Остаток = ДанныеТовара.Остаток;
    ЗаполнитьДополнительныеДанныеСтроки(Стр);

    КонецПроцедуры

    &НаСервере
    Функция ПолучитьСтруктуруДанныхТовара(СтруктураДанных)
    ЦенаТовара = РегистрыСведений.ЦеныТоваров.ПолучитьПоследнее(СтруктураДанных.Дата, Новый Структура("Товар, ВидЦен", СтруктураДанных.Товар, СтруктураДанных.ВидЦен));
    ЕдИзмерения = СтруктураДанных.Товар["ЕдИзм"];
    Если СтруктураДанных.Остаток Тогда
    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    | ТоварныеЗапасыОстатки.Товар,
    | ТоварныеЗапасыОстатки.Склад,
    | ТоварныеЗапасыОстатки.КоличествоОстаток,
    | ТоварныеЗапасыОстатки.Товар.ЕдИзм КАК ЕдИзм
    |ИЗ
    | РегистрНакопления.ТоварныеЗапасы.Остатки(&Период, ) КАК ТоварныеЗапасыОстатки
    |ГДЕ
    | ТоварныеЗапасыОстатки.Товар = &Товар";

    Запрос.УстановитьПараметр("Период", СтруктураДанных.Дата);
    Запрос.УстановитьПараметр("Товар", СтруктураДанных.Товар);

    РезультатЗапроса = Запрос.Выполнить();

    Выборка = РезультатЗапроса.Выбрать();

    Пока Выборка.Следующий() Цикл
    ОстатокТовара = Выборка.КоличествоОстаток;
    КонецЦикла;
    КонецЕсли;
    ДанныеТаблицы = Новый Структура("ЦенаТовара,ЕдИзм,Остаток",ЦенаТовара,ЕдИзмерения,ОстатокТовара);
    Возврат ДанныеТаблицы;
    КонецФункции
```

вижу что все равно как то по "колхозному" но зато количество вызовов сервера уменьшилось с 4 до одного
---
а если &НаСервере заменить на &НаСервереБезКонтекста будет еще лучше.
И цену можно будет в основном запросе получить. Так вместо 2 запросов, будет только 1 запрос.