В приведенной ниже статье попробуем с этим разобраться.
Начнем с дисклеймера.
Данная публикация не охватывает абсолютно все случаи жизни и не является единственно правильной, или вообще правильной, для решения конкретно ваших задач. Здесь просто описан простой способ получения определенного результата в конкретных условиях. Возможно вам он тоже подойдет.
Для начинающего программиста создание отчетов на СКД зачастую является делом не тривиальным. И не только потому, что изучение СКД не входит в общий курс обучения программированию 1с, но и потому, что являясь достаточно разветвленной и самостоятельной подсистемой конфигуратора, имеет свои особенности. Многие рекомендуют изучать книгу Хрусталевой "Разработка сложных отчетов в 1с Предприятии. Система компоновки данных". Именно эта книга, и даже не вся, а только её начало, натолкнуло меня на путь решения задачи, которую до этого я безуспешно пытался решить в течении 2-х дней. Дело в понимании механизмов работы СКД.
Задача.
Итак, необходимо собрать отчет по использованным на проекты материалам за некий период времени. Сам материал задается подобием, а используемые для этого данные представляют из себя выборку из документов заказа материала со склада производством и требований-накладных, т.е. фактического его списания. Иерархия отчета такова: проект — документ заказа — требования-накладные. Т.е. в проекте может быть много заявок и по каждой заявке может быть несколько списаний одного и того же материала, т.к. забирали заказанные материалы не все сразу, а по частям.
Первоначально подход был такой:
1. Написать запрос в котором соединить заявки и списания по этим заявкам и получать данные для СКД
2. Создать иерархию результатов отчета
3. Механизмами СКД вычислить ресурсы (итоги) по количеству заказанного и фактически списанного для каждой ступени иерархии
4. …и вуаля
План выглядит годным, приступаем к реализации и на выходе получаем такую таблицу:
Обратите внимание, что общее количество заказанного и списанного по заявке не совпадает:
В общем случае так может быть, для этого отчет и делается, но не в этот раз. Также обратите внимание на то, что не совпадает запрошенное количество по конкретной заявке:
Путем нехитрых размышлений приходим к выводу, что 2400 — это ни что иное, как 600*4, т.е. запрошенное по заявке количество * количество списаний по этой завке.
Убеждаемся в этом находя заявку, где количество списаний одно:
Да, для одного списания всё рассчитывается верно. Ошибка найдена: т.к заявка является группировкой, то для неё также рассчитывается ресурс "Количество по заявке". Становится понятно, что дело в том, что после отработки запрос фактически возвращает таблицу вида:
Таблица 1. Исходный запрос
Проект | Материал | Заказ | Списание | Кол-во заказ | Кол-во списание |
141218АСС | Брус | ДокументЗаказа | ДокументСписания№1 | 600 | 108 |
141218АСС | Брус | ДокументЗаказа | ДокументСписания№2 | 600 | 18 |
141218АСС | Брус | ДокументЗаказа | ДокументСписания№3 | 600 | 72 |
141218АСС | Брус | ДокументЗаказа | ДокументСписания№4 | 600 | 402 |
Так как "ДокументЗаказа" — один и тот же, то при вычисление ресурса для группировки по этому документу СКД просуммировал значение поля "Кол-во заказ" 4 раза.
В этом месте начинаются поиски в интернете и придумывание способов вычислить сумму заказов в пределах одного проекта чтобы потом подставить её в вычисление ресурса с агрегатной функцией макс. или мин. или тому подобных вещей. В любом случае мы приходим к необходимости усложнения исходного запроса для того, чтобы поля детальных записей не дублировались, т.к. ресурсы вычисляются именно по детальным записям.
Решение.
Как обычно постое, реализуемое за 10 минут с перекурами, если точно (не примерно, а точно) знать что и как работает.
Как я писал в начале, система компоновки данных сложная и развита система внутри платформы. Это целый отдельный механизм. Одной из функциональных особенностей этой системы является механизм связей наборов данных:
Начав читать указанную выше книгу Хрусталевой, мы понимаем, что механизм связей наборов данных является чем-то вроде "внутреннего запроса СКД". Т.е. с помощью него можно соединить данные из нескольких источников по неким критериям в единую таблицу, при этом сами исходные данные будут рассматриваться отдельно друг от друга как самостоятельные.
Таким образом можно вместо одного сложного (а вполне возможно — и очень сложного) исходного запроса написать два простых, разделив тем самым приведенную выше таблицу на две. Таблицу с документами заказа:
Таблица 2. Документы заказа
Проект | Материал | Документ заказа | Кол-во заказ | |
141218АСС | Брус | ДокументЗаказа | 600 |
и таблицу с документами списаний :
Таблица 3. Документы списаний
Номенклатура | Документ списания | Кол-во списание | Документ-Основание |
Брус | ДокументСписания№1 | 108 | ДокументЗаказа |
Брус | ДокументСписания№2 | 18 | ДокументЗаказа |
Брус | ДокументСписания№3 | 72 | ДокументЗаказа |
Брус | ДокументСписания№4 | 402 | ДокументЗаказа |
где "Документ-Основание" — реквизит документа списания хранящий ссылку на документ заказа материала, по которому это списание проводится.
Для соединения этих запросов в одно целое необходимо выполнить ещё один запрос. Этот последний запрос выполняет за нас механизм "Связи наборов данных", виртуально сделав левое соединение и фактически получив Таблицу 1. Для этого необходимо указать запросы и связываемые поля. В нашем случае это поля "СсылкаНаЗаявку" и "ДокументОснование" в которых хранится ссылка на документ заказа, а также, — т.к. в документах заказа и списания материалов может быть несколько, — поле с материалом:
Ну и указать ресурсы:
В результате мы получаем необходимый нам иерархический документ, но ресурсы для него будут считаться раздельно, т.к. исходные таблицы с результатами запросов — различны:
Что и требовалось доказать.
А чем функции ВычислитьВыражение и ВычислитьВыражениСГруппировкойМассив на худой конец не устраивают ? Пример если честно простоват, если вы пытались обосновать два набора данных и соединение между ними, этот пример не самый лучший вариант.
Плохо, что не представлен исходный запрос. Можно было бы подумать над более оптимальным решением, чем связь 2х наборов в СКД
(1) ну или так тоже можно
(2) Обычное левое соединение документов списания и документов заказа по полям докзаказа.ссылка=доксписания.док-основание и докзаказа.номенклатура=доксписания.номенклатура
(1) ВычислитьВыражениСГруппировкойМассив пробовал, ожидаемого результата не получил. Наверное не так пробовал…
(5) Правильно использовать так — Сумма(ВычислитьВыражениеСГруппировкойМассив(«Максимум(ВашРесурс)», «ВашеПолеЗаявки»)), во втором же поле достаточно обойтись классической суммой. Попробуйте ) Достаточно мощная функция, позволяет много чего сделать, без извращений в запросе.
(6) Премного благодарен!
(0) Я бы назвал публикацию «Особенности расчета ресурсов при соединении наборов данных в СКД». По сути вы это и показываете — соединив два набора данных в СКД вы получаете правильно рассчитанные итоги.
В курсе Гилева по СКД, это кстати, было, но не многие(я в том числе не увидел :-)) с первого раза на это обращают внимание.
(4) ох уж эти левые соединения, которые плодят дубли, когда в правой таблице строк больше, чем в левой (
Полагаю, что если бы в запросе СКД дополнительно сгруппировали по полям:
— Тип заявки
— Проект
— Ссылка на заявку
— Ссылка на ТН
— Максимум(Количество по заявке)
— Сумма(Количество по ТН)
То результат был бы верный
Но это уже на понимание, как работают запросы, а не особенности СКД
(9)
А если меняется структура отчета — нужны другие поля, например — вы тоже запрос будете переписывать под каждую из них?
(10) в любом случае нужно менять отчёт
Лично считаю, что работу программы проще предсказать, когда ты ей явно указываешь каким образом нужно собирать данные (запрос) чем через минупуляции с СКД
(11)
Нет, как раз в случае решения на СКД — не придется менять отчет и у пользователя будет возможность менять структуру.
То, что программисту проще настроить один вариант отчета и заточить под него запрос — это односзначно. Но это прошлый век.
Раз уж в теме собрались знатоки СКД есть вопрос. Как можно сократить выражение:
Просто в дальнейшем придется считать процент отклонения, и там таких выражений будет 3 штуки. Получится вот такое «радостное» выражение.
И это я еще деление на 0 не учитываю. Видимо буду от него избавляться условным оформлением.
(12)
Я не предлагаю отказаться от группировок в СКД, я предлагаю предварительно подготовить данные самым очевидным способом — в запросе
Считаю этот метод более наглядным и простым в отладке, чем соединение наборов данных или применение функций СКД в ресурсах
(13)
Последняя запись неверна в принципе — если Сумма(СуммаОтгрузкаТекПериод) <= 0, то будет деление на 0
(15) Я написал, что буду избавляться условным оформлением. Для других, более коротких конструкций идет выражение через
Просто выражение получается очень длинным, если вместо А и Б подставлять подобные выражения.
В приведенном прмере элементарно построить правильный запрос путем объединить. И все получится. СКД вещь отличная, но думаю, если можно построить запрос правильно,то и пользователькие варианты не помеха.