Мне необходимо решить задачу, в которой известно сколько сотрудник зарабатывает за полный месяц и период его работы - разбить данные с учетом года и фактически отработанного времени. Зп начисляется пропорционально отработанному времени (без учета выходных и праздников). т.е. 100% - Январь 10300, и 15 дней в феврале 54% 5518. Если нет даты увольнения (пустая ячейка, значит сотрудник продолжает работу.
Mershik, формула не учитывает месяц начала работы и никак не привязана к году работы.. В примере у Сотрудника 3 в Январе отработано 65% месяца, а по расчету выходит полный месяц. И если сотрудник начал работать в феврале, то это тоже не будет взято в расчет.. Форум читаю уже несколько лет, но впервые не могу найти ответ и сама затрудняюсь выстроить логику данного расчета )
Alisa2017 написал: сама затрудняюсь выстроить логику данного расчета
Здравствуйте! Распечатайте производственный календарь на 2016 год (у Вас в примере он) и зайдите в бухгалтерию. Спросите, как посчитать зарплату сотруднику, который отработал 1 день 01.04.2016, если его месячный оклад 10200. Бухгалтер посмотрит, сколько рабочих дней в производственном календаре на апрель 2016 (21 рабочий день), разделит оклад на количество рабочих дней и умножит на фактически отработанное время - на 1 день. Получится 485 руб. 71 коп. И если ему заплатят 340 руб., то первая же проверка сделает жизнь тому расчетчику очень весёлой. Мой вариант решения во вложении. Проверяйте.
Скрытый текст
Код
Option Explicit
Option Base 1
Function fnNachisleniya(lСтавка As Long, dДатаПриёма As Date, dДатаУвольнения As Date, dГод As Long)
'aequit 29.02.2020 v.2
Dim dДатаTemp As Date, dДатаНачалоМесяца As Date, dДатаКонецМесяца As Date
Dim lОтработаноДнейВМесяце As Long, lРабочихДнейВМесяце As Long
Dim СтоимостьРабочегоДня As Double, i As Long, j As Long, a()
If dДатаУвольнения = Empty Then dДатаУвольнения = Format(Date, "DD.MM.YYYY")
For i = 1 To 12
If Year(dДатаУвольнения) < dГод Or Year(dДатаПриёма) > dГод Then Exit For
lРабочихДнейВМесяце = 0
lОтработаноДнейВМесяце = 0
dДатаНачалоМесяца = DateSerial(dГод, i, 1)
dДатаTemp = DateAdd("m", 1, dДатаНачалоМесяца)
dДатаКонецМесяца = DateSerial(Year(dДатаTemp), Month(dДатаTemp), 0)
If dДатаПриёма <= dДатаНачалоМесяца And dДатаУвольнения >= dДатаКонецМесяца Then
ReDim Preserve a(i)
a(i) = lСтавка
ElseIf dДатаУвольнения < dДатаКонецМесяца And Year(dДатаУвольнения) = dГод Then
For j = 1 To Day(dДатаКонецМесяца)
If fnЭтоРабочийДень(DateSerial(dГод, i, j)) Then
lРабочихДнейВМесяце = lРабочихДнейВМесяце + 1
End If
Next j
СтоимостьРабочегоДня = lСтавка / lРабочихДнейВМесяце
For j = 1 To Day(dДатаУвольнения)
If fnЭтоРабочийДень(DateSerial(dГод, i, j)) Then
lОтработаноДнейВМесяце = lОтработаноДнейВМесяце + 1
End If
Next j
ReDim Preserve a(i)
a(i) = WorksheetFunction.Round(lОтработаноДнейВМесяце * СтоимостьРабочегоДня, 2)
Exit For
ElseIf dДатаПриёма > dДатаНачалоМесяца And Month(dДатаПриёма) = i Then
For j = 1 To Day(dДатаКонецМесяца)
If fnЭтоРабочийДень(DateSerial(dГод, i, j)) Then
lРабочихДнейВМесяце = lРабочихДнейВМесяце + 1
End If
Next j
СтоимостьРабочегоДня = lСтавка / lРабочихДнейВМесяце
For j = Day(dДатаПриёма) To Day(dДатаКонецМесяца)
If fnЭтоРабочийДень(DateSerial(dГод, i, j)) Then
lОтработаноДнейВМесяце = lОтработаноДнейВМесяце + 1
End If
Next j
ReDim Preserve a(i)
a(i) = WorksheetFunction.Round(lОтработаноДнейВМесяце * СтоимостьРабочегоДня, 2)
End If
Next i
For i = 1 To 12
Next i
ReDim Preserve a(12)
fnNachisleniya = a
End Function
Alisa2017 написал: Заранее огромное спасибо за помощь
Скорее всего, ТС обрадовалась и убежала с устроившим её ответом... Если считать зарплату пропорционально отработанному времени, то сотрудник, начавший работу 11.01.2016 получит полную ставку, так как он отработал полную норму часов по производственному календарю и нельзя на этом основании ему сокращать зарплату и рассчитывать её по календарным дням. Впрочем, возможно, это просто учебная задача для студентов и преподаватели подразумевают чистую математику без учета бухгалтерских правил.
Alisa2017, это слишком громко сказано, я как раз ещё продолжаю учиться, в том числе и у buchlotnik и у многих других (если Вы читаете форум несколько лет, то все эти имена знаете).
Именно так. Но ваше решение более жизненное и может ещё не раз пригодиться на практике, а не в теории. И я не сбежала )) Простите, что ответила не сразу))
Alisa2017 написал: может ещё не раз пригодиться на практике,
Смысл состоит в том, что каждый день в неполном месяце проверяется вспомогательной функцией на предмет того, рабочий он или нерабочий. Затем высчитывается стоимость рабочего дня исходя из количества рабочих дней в конкретном месяце. Для корректной работы функции следите за актуальностью праздничных дней и рабочих суббот - их добавлять в таблицы на другом листе. Остальные праздничные дни и рабочие субботы (и воскресенья) уже добавлены в базу внутри кода (с 01.01.2006 по 31.12.2020). Удачи!
P.s. нашел ошибку в алгоритме - если выбрать другой год, например, 2017, ошибочно выдает первый месяц с зарплатой у уволенного сотрудника. Сейчас поправлю... P.s. 2. Исправил. Теперь корректно отрабатывает изменения года. Файл и код заменил в посте выше.
позвольте снова вернуться к данной теме. все что нужно внести корректировку в уже имеющуюся формулу. В предложенных вариантах расчет ЗП идет по усредненной стоимости за месяц включая и выходные дни. мне необходимо что бы формула расчета считала чисторабочие дни. ни как не догадаюсь как мне это сделать также сделал отдельным списком "выходные_дни" Загрузить файлы