Добрый день. Есть вот такой запрос. Смысл в том, что я пытаюсь поменять цену товара в ТЧ "состав" справочника "номеклатура". Сам запрос отрабатывает норм, но в цикле я никак не могу установить новую цену для состав.цена, т.к. выдаёт ошибку: Поле объекта не обнаружено (Цена) НоменклатураОбъект.Состав.Цена = ВыборкаДетальныеЗаписи.ЦенаРегистра; Подскажите, что я не так делаю, а то вчера целый день убил на это. Заранее благодарен.

```1c
    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    | НоменклатураСостав.Наименование КАК Наименование,
    | НоменклатураСостав.Количество,
    | НоменклатураСостав.Цена,
    | НоменклатураСостав.Стоимость,
    | СтоимостьМатериалаСрезПоследних.Цена КАК ЦенаРегистра,
    | Номенклатура.Ссылка КАК Ссылка
    |ИЗ
    | Справочник.Номенклатура.Состав КАК НоменклатураСостав
    | ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СтоимостьМатериала.СрезПоследних(&ПериодВыборки, Цена > 0) КАК СтоимостьМатериалаСрезПоследних
    | ПО НоменклатураСостав.Наименование = СтоимостьМатериалаСрезПоследних.Наименование
    | ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
    | ПО НоменклатураСостав.Ссылка = Номенклатура.Ссылка
    |
    |СГРУППИРОВАТЬ ПО
    | НоменклатураСостав.Наименование,
    | НоменклатураСостав.Количество,
    | НоменклатураСостав.Цена,
    | НоменклатураСостав.Стоимость,
    | СтоимостьМатериалаСрезПоследних.Цена,
    | Номенклатура.Ссылка
    |
    |УПОРЯДОЧИТЬ ПО
    | Наименование
    |АВТОУПОРЯДОЧИВАНИЕ";

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

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

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

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

Сначала необходимо найти строку табличной части в которую нужно установить новое значение цены. Строку можно найти по значению реквизита "Наименование". Для простоты считаем, что наименования в ТЧ уникальны. Тогда код буде такой:

```1c
    Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
    //Получаем элемент справочника Номенклатура
    НоменклатураОбъект = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
    //Находим строку ТЧ Состав
    НайденаяСтрока = НоменклатураОбъект.Состав.Найти(ВыборкаДетальныеЗаписи.Наименование, "Наименование");
    //Если нашли строку, то меняем в ней цену
    Если НайденаяСтрока <> Неопределено Тогда
    НайденаяСтрока.Цена = ВыборкаДетальныеЗаписи.ЦенаРегистра;
    КонецЕсли;
    //Записываем
    НоменклатураОбъект.Записать();
    КонецЦикла;
```

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

Сначала необходимо найти строку табличной части в которую нужно установить новое значение цены. Строку можно найти по значению реквизита "Наименование". Для простоты считаем, что наименования в ТЧ уникальны. Тогда код буде такой:

```1c
    Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
    //Получаем элемент справочника Номенклатура
    НоменклатураОбъект = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
    //Находим строку ТЧ Состав
    НайденаяСтрока = НоменклатураОбъект.Состав.Найти(ВыборкаДетальныеЗаписи.Наименование, "Наименование");
    //Если нашли строку, то меняем в ней цену
    Если НайденаяСтрока <> Неопределено Тогда
    НайденаяСтрока.Цена = ВыборкаДетальныеЗаписи.ЦенаРегистра;
    КонецЕсли;
    //Записываем
    НоменклатураОбъект.Записать();
    КонецЦикла;
```

Код конечно не оптимальный. Номенклатура записывается после каждого изменения цены в строке ТЧ Состав. В запросе необходимо использовать итоги по Номенклатуре и строке табличной части. Тогда можно будет получив номенклатуру, перебрать все строки ТЧ Состав, установить в них цену, а затем один раз записать сделанные изменения.
---
Спасибо за информацию.
---
У меня нет торговли под рукой, но то что делаешь это уже неправильно.

```1c
    НоменклатураОбъект.Состав.Цена = ВыборкаДетальныеЗаписи.ЦенаРегистра;
```

Можно изменить реквизиты объекта, но не реквизиты "вложенного объекта".

И по моему в торговле цена не хранится в справочнике, она хранится в регистре, поэтому надо изменять записи регистра, а не объекты справочника(то что пользователь видит на форме на самом деле может храниться в разных местах). На мой взгляд тебе нужно пройти или найти хоть какие-то минимальные курсы по программированию, а иначе у тебя будет много "таких вопросов".
---
Я учусь, это не торговля, а небольшая конфа для обучения. Самое интересное то, что
НоменклатураОбъект.Состав.Цена = ВыборкаДетальныеЗаписи.ЦенаРегистра; - Это мне вчера советовали, когда я задавал аналогичный вопрос.
---
Предыдущее сообщение обновил. Не все советы одинаково полезны, могут и тролить. Тогда нужно смотреть конфу чего там и как храниться, давай конфу скажу где искать. Но все же прислушайся к моему совету и поищи курсы, на сайте 1с можно пройти за 1300 руб, но они тебе сильно помогут и избавят от таких вопросов.
---
ты чего шутишь? Зачем конфа? Он обращается к коллекции табличной части без перебора строк!

(1) После того как ты получил объект, тебе нужно найти нужно строку в табличной части "состав", для этого Для этого посмотри в сторону НайтиСтроки, по результату получил именно строку табличной части, а не коллекцию строк! И тогда поле цена будет обнаружено)
---
А ты уверен что цена хранится в табличной части? Если конфа не типовая что там и где можно только гадать и можно давать тучу советов, но работать не будет.
---
если принять на веру, что запрос выполняется без ошибок, то в табличной части есть цена. См. запрос.
---
Дело в том, что справочник "номенклатура" состоит из 2 ТЧ - состав и манипуляции. В тч "состав" висят материалы (товары), их количество, цена материалов из регистра сведений на дату и соответственно стоимость материалов для данной номенклатуры. В ТЧ манипуляции висят манипуляции, их кол-во и цена на манипуляции из регистра сведений. Сумма всех материалов и всех манипуляций = цена номенклатуры. Смысл в том, чтобы сделать обработку, которая пройдёт по всем номенклатурам и везде пересчитает стоимость матералов(товаров), используя актуальную цену из регистра сведений.
---
явно не оптимальная модель. Идет дублирование цены на материалы в регистре и в справочнике. Попытка синхронизировать цены это костыль.
Скорее всего цена номенклатуры (та, что хранится в самом справочнике) используется в документах и на нее завязана бизнеслогика.
Обработкой синхронизации текущей цены пересчитали цену номенклатуры. Потом перепровели старые документы. Что в итоге получится?
Даже без перепроведения, просто распечатать старый документ... будет уже с новой ценой.
Согласен с (5). Переделывайте на хранение в периодических регистрах. Даже уже существующий регистр подойдет. Там где храните цены материалов.
---
Да, потому что запрос отрабатывает, если бы запрос не давал результат то и ошибки не было поле не обнаружено.
---
```1c
    А ты уверен что цена хранится в табличной части?
```

Я смотрю ты тут самый уверенный. Я не прочитал запрос, onetone не видит что цены хранятся в табличной части....
Тогда расскажи нам , для чего еще автор берет цены из регистра и записывает их в табличную часть если не для хранения? У меня тоже создалось впечатление, что цены хранятся в табличной части. По этому я и написал, что в справочнике их хранить не айс! Для этого существуют регистры.
---
Я как раз ни в чем не уверен, потому не даю советы как это лучше реализовать. Мой единственный совет пройти курсы, посмотреть обучающие видео, разобраться с теорией.
---
В регистре сведений хранятся цены на материалы(товары), а цена самой номенклатуры хранится в справочнике.
---
Смотри, ты получил объект (НоменклатураОбъект = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();)

Теперь тебе нужно цену(которую ты получил в запросе записать в таблицу "состав", скорей всего в этой таблице есть "ТипЦен"(или что-то типа того), тогда тебе по этому типу цен надо найти строку, затем в полученной строке поменять цену, если строк нет то добавить новую
короче что-то типа того:

```1c
    Отбор = Новый Структура();
    Отбор.Вставить("ТипЦен", ТвойТипЦен);
    НайденноеЗначение = НоменклатураОбъект.состав.НайтиСтроки(Отбор);

    Если НайденноеЗначение.Количество() Тогда
    Для каждого стр из НайденноеЗначение Цикл //это если несколько строк, но если их там несколько то это косяк ;)
    Стр.Цена = ВыборкаДетальныеЗаписи.ЦенаРегистра;
    КонецЦикла;
    Иначе
    СтрокаСостава = НоменклатураОбъект.состав.Добавить();
    СтрокаСостава.Цена = ВыборкаДетальныеЗаписи.ЦенаРегистра;
    КонецЕсли;
```