При работе с Системой Компоновки Данных (СКД) в 1С мы часто сталкиваемся с необходимостью построения сложных отчетов, включающих вычисляемые поля. Одна из распространенных проблем возникает, когда эти вычисляемые поля представляют собой результат деления, и стандартный механизм расчета итогов в СКД начинает работать некорректно. Рассмотрим эту ситуацию на примере расчета сдельной заработной платы, где нам нужно разделить количество произведенной продукции на число сотрудников в смене, а затем получить общий итог за период.
Представьте, что мы формируем отчет по произведенной продукции, где для каждого дня и сотрудника вычисляется объем продукции, приходящийся на одного человека. Формула для детальной строки может выглядеть как Товары.Количество / Смена. Однако, когда мы пытаемся получить общий итог за период, СКД по умолчанию может посчитать не сумму значений по дням, а общий объем продукции за период, деленный на общее число смен (или какое-то другое агрегированное значение параметра "Смена"). Это приводит к искажению итоговых данных, поскольку Сумма(Товары.Количество / Смена) не равно Сумма(Товары.Количество) / Сумма(Смена).
Давайте подробно разберем, почему возникает такая ситуация и как мы можем ее корректно решить, чтобы наши отчеты всегда показывали точные и ожидаемые итоги.
Когда мы определяем вычисляемое поле в СКД, например, КоличествоНаСотрудника = Товары.Количество / Смена, и затем указываем его в ресурсах, СКД по умолчанию применяет агрегатные функции (такие как Сумма, Среднее и т.д.) к исходным полям, а затем выполняет операции над агрегированными значениями. Это означает, что при расчете общего итога по нашему полю КоличествоНаСотрудника, СКД может попытаться сделать следующее:
Товары.Количество за весь период.Смена (количество человек) за весь период.Сумма(Товары.Количество) / Сумма(Смена).Такой подход даст верный результат только в очень специфических случаях (например, если Смена всегда равна 1 или не меняется). Но в нашей задаче, где количество людей в смене может быть разным в разные дни, мы ожидаем, что СКД сначала рассчитает Товары.Количество / Смена для каждого дня (или каждой детальной записи), а затем просуммирует эти уже рассчитанные дневные (или детальные) значения. Именно для решения таких сценариев нам на помощь приходит мощная функция СКД — ВычислитьВыражениеСГруппировкойМассив.
ВычислитьВыражениеСГруппировкойМассив для корректного расчета итоговФункция ВычислитьВыражениеСГруппировкойМассив специально разработана для выполнения расчетов на более детальном уровне группировки, а затем агрегации этих промежуточных результатов. Это именно то, что нам нужно для получения правильных итогов по нашему полю.
Давайте рассмотрим подробнее синтаксис и применение этой функции.
Синтаксис функции:
ВычислитьВыражениеСГруппировкойМассив(<Выражение>, <ВыражениеПолейГруппировки>, <ОтборЗаписей>, <ОтборГруппировок>)
Для нашей задачи нас будут интересовать первые два параметра:
<Выражение>: Это строка, содержащая выражение, которое должно быть вычислено для каждого элемента промежуточной группировки. Важно отметить, что это выражение выполняется в контексте более глубокой группировки, поэтому внутри него можно использовать агрегатные функции, которые будут работать для этой промежуточной группировки. В нашем случае, мы хотим получить количество продукции на одного сотрудника за каждый день, поэтому наше выражение будет "Сумма(Товары.Количество/Смена)". Обратите внимание на наличие Сумма() внутри выражения – она агрегирует значения Товары.Количество/Смена по самой глубокой доступной группировке (в нашем случае, по дням).<ВыражениеПолейГруппировки>: Это поле или список полей, по которым будет формироваться промежуточная группировка. Для каждого уникального значения этих полей будет вычислено <Выражение>, и результаты будут собраны в массив. В нашем примере, где мы хотим суммировать ежедневные показатели, таким полем будет "Дата".Функция ВычислитьВыражениеСГруппировкойМассив возвращает массив значений. Чтобы получить единый итоговый результат (например, общую сумму), нам необходимо обернуть эту функцию в соответствующую агрегатную функцию, в нашем случае — Сумма().
Рассмотрим, как мы можем применить эту функцию для исправления расчета итогов в нашем отчете по сдельной зарплате:
Наш ресурс, для которого необходимо корректно посчитать итог, это количество произведенной продукции на одного сотрудника за день. Давайте назовем его, например, ПродукцияНаСотрудника.
Мы хотим, чтобы для каждого дня СКД сначала вычислила Товары.Количество / Смена, а затем для каждого сотрудника просуммировала эти дневные результаты. С учетом специфики работы ВычислитьВыражениеСГруппировкойМассив, финальное выражение для нашего ресурса будет выглядеть так:
Сумма(ВычислитьВыражениеСГруппировкойМассив("Сумма(Товары.Количество/Смена)", "Дата"))
"Сумма(Товары.Количество/Смена)": Это внутреннее выражение. Оно говорит СКД: "Для каждой записи, сгруппированной по полю 'Дата' (следующий параметр), вычисли сумму значений 'Количество/Смена'". Если у нас в один день может быть несколько записей с одинаковым количеством людей в смене, это выражение сначала вычислит результат деления для каждой из них, а затем просуммирует их для данного дня."Дата": Это поле, по которому происходит промежуточная группировка. СКД сначала сгруппирует все данные по полю Дата, для каждой уникальной даты выполнит внутреннее выражение "Сумма(Товары.Количество/Смена)", и соберет полученные ежедневные итоги в массив.Сумма(...): Внешняя функция Сумма. Она получает массив ежедневных итогов (который вернула ВычислитьВыражениеСГруппировкойМассив) и суммирует все элементы этого массива. Таким образом, мы получаем корректный общий итог за весь период, который является суммой корректно рассчитанных ежедневных значений.Для применения данного выражения необходимо выполнить следующие шаги в настройках СКД:
ПродукцияНаСотрудника.
Сумма(ВычислитьВыражениеСГруппировкойМассив("Сумма(Товары.Количество/Смена)", "Дата"))
После применения этих настроек, СКД будет сначала корректно вычислять долю продукции на человека для каждого дня, а затем суммировать эти дневные значения, предоставляя вам точный общий итог за весь отчетный период.
В ходе обсуждения на форуме пользователи столкнулись с проблемой, когда стандартный расчет давал 383,33, в то время как ожидаемый результат по сумме ежедневных данных составлял 335. После применения предложенного выражения ВычислитьВыражениеСГруппировкойМассив("Сумма(Товары.Количество/Смена)", "Дата"), пользователь получил массив ежедневных значений, таких как "24; 31; 27; 31; 19; 26; 87; 48,333333333333333333333333333; 17; 73". После суммирования этих значений, итоговая сумма совпала с ожидаемой, что подтверждает правильность данного подхода. Некоторая путаница изначально возникла из-за особенностей отображения чисел в Excel, но в итоге было установлено, что расчет в 1С был верным.
ВычислитьВыражениеСГруппировкойМассив. Например, "Дата" и "Сумма(Товары.Количество/Смена)".<Выражения> (например, Сумма(), Среднее()) и какая функция агрегирует массив (внешняя Сумма()). Это определяет логику ваших расчетов.Таким образом, функция ВычислитьВыражениеСГруппировкойМассив является мощным инструментом в арсенале разработчика 1С, позволяющим решать сложные задачи по расчету ресурсов и агрегации данных в СКД, особенно когда стандартные механизмы не дают желаемого результата из-за специфики вычисляемых полей. Мы надеемся, что это подробное объяснение поможет вам создавать более точные и информативные отчеты.