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

Я не могу сформировать таблицу значений перед формированием отчета т.к. список номенклатуры образуется в процессе формирования отчета и должен быть передан в набор данных параметром.

Вопрос - как сделать так, чтобы текст запроса набора данных хранился в одном месте а не в трёх. Можно ли для этого использовать набор данных - объект, подкладывать туда не таблицу значений а набор данных или схему компоновки данных и передавать туда параметры?
---
Вам уже ответили (8), где рекомендовали изменить текст запроса программно. Подробнее:
Наверное, будет удобнее сначала подготовить каждый отчет.
Рекомендую:
 -Последний пакет запроса из СКД кажого отчета сохранить во временную таблицу, например ВТ_Рез
 -Затем в тексте запроса написать

```1c
    Выбрать ВТ_Рез.*, 0 как Доходность из ВТ_Рез
```

 Оно само там всё заполнит и в доступных полях появится нужное поле.
 - Далее оформляете настройки как Вам нужно с Итогами, условным оформлением и т.д.
-Напишите функцию, возвращающую дополнительный текст запроса, которую будете вызывать из каждого отчета. Например:

```1c
    Выбрать ВТ_Рез.*, ВТ_Доходность.Доходность КАК доходность
    ИЗ ВТ_Рез как ВТ_рез
    левое соединение (ПодзапросВычисляющийДоходность) как ВТ_Доходность
    по ВТ_рез.Номенклатура=ВТ_Доходность.Номенклатура
```

- Затем переопределяете текст запроса в нужном наборе данных отчетов при вызове формирования отчета:

```1c
    Набор=СхемаКомпоновкиДанных.НаборыДанных.НаборДанных1;
    ТекстЗапроса=Набор.Запрос;
    ТекстЗапроса=ТекстЗапроса+" ; "+ВашаФункцияВозвращающаяТекстЗапроса();
    СхемаКомпоновкиДанных.НаборыДанных.НаборДанных1.Запрос=ТекстЗапроса;
```

  В итоге у вас в отчете будет два результирующих пакета, с доходностью=0 и правильно высчитанной.
  СКД возьмет последний. Если будет долго формироваться, то старый пакет можно будет вырезать программно.
---
Alien_job, что понимаете под "среднюю доходность"? если рентабельность то есть отчет Валовая прибыль
---
PhoenixAOD, Слова "средняя доходность" для примера. Можно для примера говорить "валовая прибыль", но я не знаю как наличие отчета по валовой прибыли поможет вывести валовую прибыль в отчет по остаткам номенклатуры.
---
Alien_job,
Я не могу сформировать таблицу значений перед формированием отчета т.к. список номенклатуры образуется в процессе формирования отчета и должен быть передан в набор данных параметром.

так может быть при формировании таблицы значений для набора данных - объекта просто выполнять запрос для формирования списка номенклатуры с наложенными отборами настроек? ну и дальше дополнить таблицу значений результата запроса нужными полями, или непосредственно в запросе дополнить.
---
ЧерныйКот, например в процессе запроса к регистру остатков мы получаем номенклатуру на остатках. Потом формируем для неё таблицу значений. Эту таблицу значений мы передаем в скд как набор данных объект и скд делает запрос к регистру остатков? Двойная работа
---
Alien_job, допиши запрос программно. Или подмени СКД уже с измененным запросом. Или оставь старый СКД и замени его новым с правильным запросом.
А то нашел чем себя занять))
---
Xershi, не совсем понял
---
Вам уже ответили (8), где рекомендовали изменить текст запроса программно. Подробнее:
Наверное, будет удобнее сначала подготовить каждый отчет.
Рекомендую:
 -Последний пакет запроса из СКД кажого отчета сохранить во временную таблицу, например ВТ_Рез
 -Затем в тексте запроса написать

```1c
    Выбрать ВТ_Рез.*, 0 как Доходность из ВТ_Рез
```

 Оно само там всё заполнит и в доступных полях появится нужное поле.
 - Далее оформляете настройки как Вам нужно с Итогами, условным оформлением и т.д.
-Напишите функцию, возвращающую дополнительный текст запроса, которую будете вызывать из каждого отчета. Например:

```1c
    Выбрать ВТ_Рез.*, ВТ_Доходность.Доходность КАК доходность
    ИЗ ВТ_Рез как ВТ_рез
    левое соединение (ПодзапросВычисляющийДоходность) как ВТ_Доходность
    по ВТ_рез.Номенклатура=ВТ_Доходность.Номенклатура
```

- Затем переопределяете текст запроса в нужном наборе данных отчетов при вызове формирования отчета:

```1c
    Набор=СхемаКомпоновкиДанных.НаборыДанных.НаборДанных1;
    ТекстЗапроса=Набор.Запрос;
    ТекстЗапроса=ТекстЗапроса+" ; "+ВашаФункцияВозвращающаяТекстЗапроса();
    СхемаКомпоновкиДанных.НаборыДанных.НаборДанных1.Запрос=ТекстЗапроса;
```

  В итоге у вас в отчете будет два результирующих пакета, с доходностью=0 и правильно высчитанной.
  СКД возьмет последний. Если будет долго формироваться, то старый пакет можно будет вырезать программно.
---
Onwardv, И всё равно это выглядит как костыль
---
up
---
То есть надо в каждый отдельный отчет из перечисленных тобой добавить столбец с рентабельностью? При этом ты не хочешь портить сам текст запроса в существующем отчете? Как-то нелогично получается. Самый правильный вариант отсеивать в постановке. В любом случае тебе придется дорабатывать отчеты, почему бы не сделать это по нормальному?
---
mazechild, по моему нормально - это с минимумом копипасты. Я не то чтобы портить текст запроса не хочу - я хочу чтобы правила расчета этого столбика по номенклатуре лежали в одном месте а не в 3-х отчетах
---
Alien_job, В чём будет польза такой реализации?
---
mazechild, Требования к этому столбику еще 10 раз изменятся. Польза - нужно будет в 3 раза меньше потом переделывать.
---
Alien_job, напишите тогда функцию, а в СКД в вычисляемых полях ее используйте.
(12) Alien_job, спрашивайте, что не поняли?
---
Xershi, Функция будет вызываться в цикле для каждой строки результата. А в функции будет запрос. Запросы в цикле - нельзя.
Не понял куда дописать запрос программно.
"Или подмени СКД уже с измененным запросом. Или оставь старый СКД и замени его новым с правильным запросом." - если я правильно понял не решают проблему копипасты а наоборот
---
Alien_job,
Все просто. В СКД можно использовать функции глобальных и неглобальных общих модулей в вычисляемых полях при условии что функция объявлена как экспортная.
Есть только маленькая тонкость при программном формировании отчета СКД.
Обычно, при инициализации процессора компоновки данных делают так:

```1c
    ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки);
```

При таком формировании отчета вызова функций не произойдет. Что бы эту возможность включить нужно сделать так

```1c
    ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки,,,Истина);
```
---
mazechild, тонкость интересная. Спасибо, не знал о таком. Но функцию использовать не получится - запрос в цикле.
---
:) Да, это так, настоящий "Костыль". Но не переживайте, даже плотники всякие щепочки и чурочки постоянно подкладывают. И ничего.
---
Как вариант решения - это использование процедуры с кэшированием.
Создаем функцию в модуле с кэшем на вызов, где запросом получаем рентабельность по номенклатуре и записываем все это в соответствие, которое возвращаем.
Делаем еще одну функцию в общем модуле с параметром "номенклатура". Из этой функции вызываем кэшируемую функцию и получаем значение соответствия по номенклатуре.
В СКД создаем дополнительное поле и откуда вызываем вторую процедуру.
Запроса в цикле формально нет, но при таком подходе куда проще создать дополнительный набор данных и делать соединение на закладке "связи наборов данных" и где так же получать показателей рентабельности по исчерпывающему набору номенклатуры.
---
evil_wizard, вроде если номенклатура в отчете не повторяется то кеш ничего не даст - при вызове для каждой строки номенклатура будет новая и функция будет выполняться заново. Или при первом вызове мы получаем рантабельность для вообще всей номенклатуры из справочника? Это не реально

Сам сделал так : в отчетах добавил набор дынных с "заглушкой" - типа "выбрать 1 как рентабельность из номенклатура где номенклатура в &СписокПараметров". Настроил связи наборов и вывел поле в отчет. При формировании отчета подменяю текст запроса для этого набора данных как в (17) СхемаКомпоновкиДанных.НаборыДанных.НаборДанных1.Запрос=ТекстЗапроса;
---
Alien_job, я предлагаю кешировать не функцию получения рентабельности, а функцию получения соответствия номенклатуры и ее рентабельности. Таким образом соответствие получится один раз и дальше будет браться из кеша.