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