Как пропорционально распределить сумму из двух таблиц
Перейти к содержимому

Как пропорционально распределить сумму из двух таблиц

  • автор:

Как пропорционально распределить сумму из двух таблиц

Argument ‘Topic id’ is null or empty

Сейчас на форуме

© Николай Павлов, Planetaexcel, 2006-2023
info@planetaexcel.ru

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

ООО «Планета Эксел»
ИНН 7735603520
ОГРН 1147746834949
ИП Павлов Николай Владимирович
ИНН 633015842586
ОГРНИП 310633031600071

Как пропорционально распределить сумму из двух таблиц

(3)Формулой это типа:
Ч1 = 150
Ч2 = 100
Ч3 = 50
Сумма = Ч2 / (Ч1 + Ч3)
Ч1 = Ч1 + Ч1 * Сумма
Ч3 = Ч3 + Ч3 * Сумма

Все понятно, всем спасибо.

(8) Чтобы не путаться в понятиях:
Коэффициент = Ч2 / (Ч1 + Ч3)
Ч1 = Ч1 + Ч1 * Коэффициент
Ч3 = Ч3 + Ч3 * Коэффициент

(8) А зачем так:
Ч1 = Ч1 + Ч1 * Коэффициент ?

Функция РассчитатьДельту(СуммаВходящая,ВсегоСуммаВходящая,СуммаРаспределения)
ПроцентОтОбщей=СуммаВходящая /(ВсегоСуммаВходящая/100);
Дельта=Окр(СуммаРаспределения/100*ПроцентОтОбщей,2,РежимОкругления.Окр15как20);
Возврат Дельта;
КонецФункции

+ потом если последняя сумма надо не функцию вызывать а тупо прибавлять оставшийся хвост. а то копейки остаются

мдэ. а что, в Советское время тоже образование хромало?

(12) хвост в виде лишней копейки, если коэффициент вида 0,3333333333333, лучше не к последней сумме прибавлять, а к максимальной. Аккуратнее получается. 🙂

(0) «программист»-гуманитарий?
(0) это шутка ?
(14)Можно и так 🙂

есть 2 (два) осажденных города.
в одном 150 защитников. в другом 50 защитников.
им на подмогу идет обоз с мукой.
везут 100 кг.
Задача: сколько муки нужно завезти в каждый город через подземный ход чтобы всем защитникам досталось поровну?
Решение:
Складываем всех защитников города, делим всю муку на кол-во всех защитников, находим сколько муки приходится на 1 защитника по норме.
Умножаем норму на кол-во защитников в каждом городе.
разделяем всю муку на 2 части ПРОПОРЦИОНАЛЬНО полученной норме для каждого города.

(14) В социальном государстве лучше прибавлять к минимальной сумме.
а теперь в запросе и так, чтобы копейки не терялись :)))
лично у меня — УГ получилось 🙂

(20)
declare t table (id int, b decimal)
declare @sum as decimal

insert t values (1, 100), (2, 50)

select
cast(@sum / (SUM(b) OVER()) * b as decimal(15,2)) AS t
from
t

Усложним задачу:
Есть главный документ.
Сумма документа = 150
Нал = 50
БезНал = 100

Он делится на 2 документа.

Первый Документ
Сумма = 80
Нал = ?
БезНал = ?

Второй Документ
Сумма = 70
Нал = ?
БезНал = ?

Вот как тут рассчитать оплату из главного документа ?

(22) распредели сумму в 100 пропорционально между 3 одинаковимы значениями, чтобы копейки не потерялись

*одинаковыми
типа
100 + 100 + 100 + 100 => 133,34 + 133,33 + 133,33

(14) В исходной задаче две суммы. В случае, если у одной суммы будет 0,3333333333333 — значит у другой 0,6666666666666. В общем, при округлении все будет хорошо. Вот если было три суммы (и более). Возникла бы ситуёвина, когда одному 0,3333333333333, другому 0,3333333333333 и третьему столько же. В результате копеечки могут и не бить.

(27) решение таки должно быть универсальным

(0) размазывать нужно как в (6) но с одной оговоркой
отсортировать суммы по убыванию и последней сумме добавить остаток

Суть этого гемора такова:
Определенный товар продается на ИП, остальной на ООО (одна касса работает с двумя фискальниками), до того пока не подключили банк все было нормально, вчера подключили.

т.е.
Один Чек ККМ делится на два в зависимости от товара.

Для Каждого Строка Из ТЗ Цикл
Результат = НужныйРезультат * Строка.Основание / База + Отклонение;
Отклонение = (Результат — Окр(Результат, 2));
Строка.Результат = Окр(Результат, 2);
КонецЦикла;

Это 1с розница, программно деление чека выглядит так:

Если Константы.ДваФР.Получить() Тогда
Запрос = Новый Запрос(»
|ВЫБРАТЬ * ПОМЕСТИТЬ ТабТов ИЗ &ТабТов КАК ТТ;
|ВЫБРАТЬ *
|ИЗ
| ТабТов КАК Товары
|ГДЕ
| Товары.Номенклатура.ТоварОрганизации = &Организация»);
Запрос.УстановитьПараметр(«ТабТов», Товары.Выгрузить());
ВремКассаККМ = КассаККМ;
Оплаты = Оплата.Выгрузить();
Организации = Справочники.Организации.Выбрать();
Пока Организации.Следующий() Цикл
Если Организации.Ссылка = Магазин.ОсновнойСклад.Организация Тогда;
Организация = Справочники.Организации.ПустаяСсылка();
Иначе
Организация = Организации.Ссылка;
КонецЕсли;
Запрос.УстановитьПараметр(«Организация», Организация);
Результат = Запрос.Выполнить();
Если Не Результат.Пустой() Тогда
ЭтотОбъект.Товары.Загрузить(Результат.Выгрузить());
ФР = ПолучитьСерверТО().ПолучитьИдентификаторПоИдКассы(Организация);
Если ЗначениеЗаполнено(Организация) И Не ПустаяСтрока(ФР) Тогда
КассаККМ = ПолучитьСерверТО().ПолучитьКассуККМ(ФР);
Иначе
КассаККМ = ВремКассаККМ;
КонецЕсли;
ИтогСуммы = Товары.Итог(«Сумма»);
ИтогОплат = Оплаты.Итог(«Сумма»);
Если ИтогСуммы <> ИтогОплат Тогда
ЭтотОбъект.Оплата.Загрузить(Оплаты);
Для Каждого ФормаОплат Из Оплата Цикл

КонецЦикла;
КонецЕсли;
ЗавершитьЗакрытиеЧека2(Печать, РучнойРежим, ВыбратьДокументПечати, ФР);
КонецЕсли;
КонецЦикла;
Иначе
ЗавершитьЗакрытиеЧека2(Печать, РучнойРежим, ВыбратьДокументПечати);
КонецЕсли;

(32) запросом же

(34)Если использовать временные таблицы, то можно распределить результат, а остаток оставить на максимальной/минимальной строке

Получилось как то так:
.
Для Каждого ФормаОплат Из Оплата Цикл
Если ПервыйПроход Тогда
СуммаОплаты = ИтогСуммы * Окр(ФормаОплат.Сумма / ИтогОплат, 2);
СписокОплат.Добавить(ФормаОплат.Сумма — СуммаОплаты);
ФормаОплат.Сумма = СуммаОплаты;
Иначе
ФормаОплат.Сумма = СписокОплат.Получить(ФормаОплат.НомерСтроки — 1).Значение;
КонецЕсли;
КонецЦикла;
ПервыйПроход = 0;
.

(36) В УТ или УПП глянь документ доп. расходы. Там есть алгоритм распределения суммы по кол-ву или объему

Как пропорционально распределить сумму из двух таблиц

Всем привет !
Подскажите как распределить сумму из одной ячейки пропорционально между суммами в других ячейках ?

Всем привет !
Подскажите как распределить сумму из одной ячейки пропорционально между суммами в других ячейках ? jordann

К сообщению приложен файл: rasp_summ.xls (42.5 Kb)

Сообщение Всем привет !
Подскажите как распределить сумму из одной ячейки пропорционально между суммами в других ячейках ? Автор — jordann
Дата добавления — 25.04.2015 в 19:28

Подбор слагаемых для нужной суммы

adjust0.png

Не очень частый, но и не экзотический случай. На моих тренингах такой вопрос задавали не один и не два раза 🙂 Суть в том, что мы имеем конечный набор каких-то чисел, из которых надо выбрать те, что дадут в сумме заданное значение. В реальной жизни эта задача может выглядеть по-разному.

  • Например, мы выгрузили из интернет-банка все платежи, которые поступили на наш счет за последний месяц. Один из клиентов разбивает сумму своего платежа на несколько отдельных счетов и платит частями. Мы знаем общую сумму оплаты и количество счетов, но не знаем их сумм. Надо подобрать те суммы в истории платежей, которые дадут в общем заданное значение.
  • У нас есть несколько рулонов стали (линолеума, бумаги. ), из которых надо подобрать под заказ те, что дадут заданную длину.
  • Блэкджек или в народе «очко». Надо набрать карты суммарной стоимостью максимально близкой к 21 баллу, но не превысить этот порог.

В некоторых случаях может быть известна разрешенная погрешность допуска. Она может быть как нулевой (в случае подбора счетов), так и ненулевой (в случае подбора рулонов), или ограниченной снизу или сверху (в случае блэкджека).

Давайте рассмотрим несколько способов решения такой задачи в Excel.

Способ 1. Надстройка Поиск решения (Solver)

Эта надстройка входит в стандартный набор пакета Microsoft Office вместе с Excel и предназначена, в общем случае, для решения линейных и нелинейных задач оптимизации при наличии списка ограничений. Чтобы ее подключить, необходимо:

  • в Excel 2007 и новее зайти Файл — Параметры Excel — Надстройки — Перейти (File — Excel Options — Add-ins — Go)
  • в Excel 2003 и старше — открыть меню Сервис — Надстройки (Tools — Add-ins)

и установить соответствующий флажок. Тогда на вкладке или в меню Данные (Data) появится нужная нам команда.

Чтобы использовать надстройку Поиск решения для нашей задачи необходимо будет слегка модернизировать наш пример, добавив к списку подбираемых сумм несколько вспомогательных ячеек и формул:

adjust1.png

  • Диапазон A1:A20 содержит наши числа, из которых мы будем выбирать нужные, чтобы «вписаться» в заданную сумму.
  • Диапазон В1:B20 будет своего рода набором переключателей, т.е. будет содержать нули или единички, показывая, отбираем мы данное число в выборку или нет.
  • В ячейке E2 стоит обычная автосумма всех единичек по столбцу B, подсчитывающая кол-во выбранных чисел.
  • В ячейке E3 с помощью функции СУММПРОИЗВ (SUMPRODUCT) считается сумма попарных произведений ячеек из столбцов А и B (то есть A1*B1+A2*B2+A3*B3+. ). Фактически, здесь подсчитывается сумма чисел из столбца А, отобранных единичками из столбца В.
  • В розовую ячейку E4 пользователь вводит желаемую сумму для подбора.
  • В ячейке E5 вычисляется абсолютное по модулю значение погрешности подбора с целью ее будущей минимизации.
  • Все желтых ячейках Е8:E17 хотелось бы получить список отобранных чисел, т.е. тех чисел из столбца А, напротив которых в столбце В есть единички. Для этого необходимо выделить сразу все (!) желтые ячейки и в них ввести вот такую формулу массива:

=ЕСЛИОШИБКА(ИНДЕКС($A$1:$A$20;НАИМЕНЬШИЙ(ЕСЛИ(B1:B20=1;СТРОКА(B1:B20);»»);СТРОКА()-СТРОКА($E$8)+1));»»)

=IFERROR(INDEX($A$1:$A$20;SMALL(IF(B1:B20=1;ROW(B1:B20);»»);ROW()-ROW($E$8)+1));»»)

После ввода формулы ее необходимо ввести не как обычную формулу, а как формулу массива, т.е. нажать не Enter, а Ctrl+Shift+Enter. Похожая формула используется в примере о ВПР, выдающей сразу все найденные значения (а не только первое).

Теперь перейдем на вкладку (или в меню) Данные и запустим инструмент Поиск решения (Data — Solver):

adjust4.png

В открывшемся окне необходимо:

  • Задать как целевую функцию (Target Cell) — ячейку вычисления погрешности подбора E5. Чуть ниже выбрать опцию — Минимум, т.к. мы хотим подобрать числа под заданную сумму с минимальной (а лучше даже нулевой) погрешностью.
  • В качестве изменяемых ячеек переменных (Changing cells) задать диапазон столбца переключателей B1:B20.
  • С помощью кнопки Добавить (Add) создать дополнительное условие на то, что ячейки диапазона B1:B20 должны быть бинарными (т.е. содержать только 0 или 1):

adjust5.png


С помощью той же кнопки, при необходимости, создать ограничение на количество чисел в выборке. Например, если мы знаем, что сумма была разбита на 5 счетов, то:

adjust6.png

После ввода всех параметров и ограничений запускаем процесс подбора кнопкой Найти решение (Solve). Процесс подбора занимает от нескольких секунд до нескольких минут (в тяжелых случаях) и заканчивается появлением следующего окна:

adjust3.png

Теперь можно либо оставить найденное решение подбора (Сохранить найденное решение), либо откатиться к прежним значениям (Восстановить исходные значения).

Необходимо отметить, что для такого класса задач существует не одно, а целое множество решений, особенно, если не приравнивать жестко погрешность к нулю. Поэтому запуск Поиска решения с разными начальными данными (т.е. разными комбинациями 0 и 1 в столбце В) может приводить к разным наборам чисел в выборках в пределах заданных ограничений. Так что имеет смысл прогнать эту процедуру несколько раз, произвольно изменяя переключатели в столбце В.

Найденные комбинации можно сохранять виде сценариев (кнопка Сохранить сценарий), чтобы вернуться к нем позднее с помощью команды Данные — Анализ «что-если» — Диспетчер сценариев (Data — What-If Analysis — Scenario Manager):

adjust7.png

И весьма удобно будет вывести все найденные решения, сохраненные в виде сценариев, в одной сравнительной таблице с помощью кнопки Отчет (Summary):

adjust8.png

Способ 2. Макрос подбора

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

adjust9.png

Для использования макроса нажмите сочетание Alt+F11, в открывшемся окне редактора Visual Basic вставьте новый модуль через меню Insert — Module и скопируйте туда этот код:

Sub Combinator() Dim Data() As Variant, Selected() As Variant Dim goal As Double, sel_count As Integer, prec As Double Const LIMIT = 1000000 prec = Range("D5").Value sel_count = Range("D2").Value goal = Range("D4").Value Set OutRange = Range("D8") Set InputRange = Range("A1", Range("A1").End(xlDown)) input_count = InputRange.Cells.Count Data = InputRange.Value ReDim Selected(1 To sel_count) As Variant NewTry: For j = 1 To sel_count Start: RandomIndex = Int(Rnd * input_count + 1) RandomValue = Data(RandomIndex, 1) 'начиная со второго элемента дополнительно проверяем, чтобы такой уже не был выбран If j > 1 Then For k = 1 To j - 1 If Selected(k) = RandomValue Then GoTo Start Next k End If Selected(j) = RandomValue Next j If Abs(WorksheetFunction.Sum(Selected) - goal) LIMIT Then MsgBox "Достигнут лимит попыток. Решение не найдено." Exit Sub Else GoTo NewTry End If End If End Sub

Аналогично первому способу, запуская макрос несколько раз, можно получать разные наборы подходящих чисел.

P.S. Сейчас набегут энтузиасты с мехмата МГУ с криками «Тупой перебор — это неэстетично!» Да, я в курсе, что прямой перебор вариантов — это не самый оптимальный способ поиска. Да, существует много умных алгоритмов поиска решения таких задач, которые сокращают время поиска и находят нужную комбинацию заметно быстрее. Могу даже рассказать про парочку. Но мне на данном этапе существующей скорости «тупого перебора» вполне достаточно — обработка массива из 1000 ячеек идет меньше секунды. Готов подождать 🙂

Ссылки по теме

  • Оптимизация бизнес-модели с помощью надстройки Поиск решения (Solver)
  • Что такое макросы, куда и как вставлять код макросов на VBA

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *