База знаний Одина — Одинэсника › Форумы › ODIN — Форум по 1С Предприятию › Как написать функцию на 1С для пропорционального распределения суммы? › Ответ в теме: Как написать функцию на 1С для пропорционального распределения суммы?
24 апреля 2026 в 18:38
#36811
Вот пример функции на 1С (BSL), которая пропорционально распределит заданную сумму по строкам таблицы значений (База) по колонке «Сумма». Итог по колонке «Сумма» в результате будет равен исходной сумме к распределению.
1С (Код)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
Функция РаспределитьПропорционально(СуммаКРаспределению, ТаблицаБаза) Если ТаблицаБаза = Неопределено Или ТаблицаБаза.Количество() = 0 Тогда Возврат Новый ТаблицаЗначений; КонецЕсли; // Считаем сумму по колонке "Сумма" в базе ОбщаяСумма = 0; Для Каждого Строка Из ТаблицаБаза Цикл ОбщаяСумма = ОбщаяСумма + Строка.Сумма; КонецЦикла; Если ОбщаяСумма = 0 Тогда // Если сумма базы 0, то распределить нельзя, возвращаем копию с нулями Результат = ТаблицаБаза.Скопировать(); Для Каждого Строка Из Результат Цикл Строка.Сумма = 0; КонецЦикла; Возврат Результат; КонецЕсли; // Создаем новую таблицу для результата Результат = Новый ТаблицаЗначений; Результат.Колонки.Добавить("Показатель"); Результат.Колонки.Добавить("КодIC"); Результат.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2))); // Для корректного распределения с учетом округления СуммаРаспределена = 0; ИндексМаксимума = 0; МаксимальноеЗначение = -1; // Найдем индекс строки с максимальной суммой (для компенсации погрешности округления) Для Номер = 0 По ТаблицаБаза.Количество() - 1 Цикл Если ТаблицаБаза[Номер].Сумма > МаксимальноеЗначение Тогда МаксимальноеЗначение = ТаблицаБаза[Номер].Сумма; ИндексМаксимума = Номер; КонецЕсли; КонецЦикла; // Распределяем сумму пропорционально Для Номер = 0 По ТаблицаБаза.Количество() - 1 Цикл Строка = ТаблицаБаза[Номер]; РаспределеннаяСумма = Окр(СуммаКРаспределению * Строка.Сумма / ОбщаяСумма, 2, Истина); НоваяСтрока = Результат.Добавить(); НоваяСтрока.Показатель = Строка.Показатель; НоваяСтрока.КодIC = Строка.КодIC; НоваяСтрока.Сумма = РаспределеннаяСумма; СуммаРаспределена = СуммаРаспределена + РаспределеннаяСумма; КонецЦикла; // Корректируем погрешность округления на строку с максимальным значением Разница = СуммаКРаспределению - СуммаРаспределена; Если Разница <> 0 Тогда Результат[ИндексМаксимума].Сумма = Результат[ИндексМаксимума].Сумма + Разница; КонецЕсли; Возврат Результат; КонецФункции |
Как использовать:
1С (Код)
|
1 2 3 4 5 6 7 8 9 10 11 12 |
ТаблицаБаза = Новый ТаблицаЗначений; ТаблицаБаза.Колонки.Добавить("Показатель"); ТаблицаБаза.Колонки.Добавить("КодIC"); ТаблицаБаза.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2))); // Заполнить ТаблицаБаза данными СуммаКРаспределению = 10000; // например РаспределеннаяТаблица = РаспределитьПропорционально(СуммаКРаспределению, ТаблицаБаза); // В РаспределеннаяТаблица сумма по колонке "Сумма" будет равна 10000 |
Функция учитывает округление до 2 знаков и компенсирует погрешность на строку с максимальным значением, чтобы итоговая сумма была точной.