Estoy armando una planilla, lo mas parametrizable posible, de control de
ausentismo y cálculo de horas. Pero me empantane en un algoritmo que
necesito desarrollar. Estos son los datos:
Variables:
et: Tiempo de entrada segun turno
st: Tiempo de salida segun turno
er: Tiempo de entrada real
sr: Tiempo de salida real
li: Limite inferior del intervalo de tiempo a analizar
ls: Limite superior del intervalo de tiempo a analizar
Restricciones:
et < st; er < sr; li < ls
[et, st, er, sr, li, ls] = [00:00 .. 23:59]
Incognitas:
Necesito averguar, dentro del intervalo a analizar [li, ls] los
siguientes datos:
preh: Cantidad de horas trabajadas antes del turno
enh: Cantidad de horas trabajadas dentro del turno
posth: Cantidad de horas trabajadas despues del turno
Si Minutos(x) >= 40 entonces x = x + 1
Si 40 > Minutos(x) >= 20 entonces x = x + 0.5
donde x = [preh, enh, posth]
Ejemplo:
et = 07:00 st = 15:00
er = 05:30 sr = 18:25
li = 06:00 ls = 11:00
preh = 1 (desde 06:00 hasta 07:00)
enh = 4 (desde 07:00 hasta 11:00)
posth = 0
para
li = 11:00 ls = 13:00
preh = 0
enh = 2 (desde 11:00 hasta 13:00)
posth = 0
y para
li = 13:00 ls = 21:00
preh = 0
enh = 2 (desde 13:00 hasta 15:00)
posth = 3.5 (desde 15:00 hasta 18:25)
Los li y ls que puse como ejemplo no son arbitrarios; de ellos (y el dia
de la semana, entre otras cosas) depende la posterior discriminacion en
horas normales, extras, nocturnas, etc.
Caso especial del turno noche: lo "soluciono" uniendo dos intervalos:
li = 21:00 ls = 23:59
li = 00:00 ls = 06:00
Espero haberlo especificado suficientemente. desde ya, muchas gracias.
Julio.
[creo que] hay algunos puntos 'oscuros' en las 'ecuaciones' que usas para describir 'el problema' [me explico]:
1) si los tiempos 'turno' [et y st] equivalen a una jornada laboral 'normal' de 8 horas [et = 07:00 y st = 15:00]
a) cual es el razonamiento para 'castigarle' media hora al que entro 'realmente' a las 5:30 ???
b) cual es la 'necesidad' de separar las horas 'normales' en tres distintos 'enh' ??? [segun tu ejemplo]...
enh = 4 (desde 07:00 hasta 11:00) {+} 2 (desde 11:00 hasta 13:00) {+} 2 (desde 13:00 hasta 15:00)
2) se esperan turnos variados ? [o solo existe el de 07:00 a 15:00 {+} el 'nocturno' con sus 'horas extras'] -???-
se esperan entradas 'desde el dia anterior' y/o salidas 'hasta el dia sigiente' -???-
3) seria conveniente si expones 'realidades' mas... 'visibles' como...
a) rangos de donde 'tomar' las variables et, er, [etc. etc. etc.]
b) las formulas que estas utilizando actualmente [y si les falla... donde, cuando y por que]
4) [personalmente] me 'perdi' tratando de descifrar la ecuacion de los minutos y el 40 :((
comentas los detalles que se hubieran quedado 'en el tintero' ?
saludos,
hector.
__ la consulta original __
> Estoy armando una planilla, lo mas parametrizable posible, de control de ausentismo y calculo de horas.
Aclaro un poco mas el panorama. El algoritmo lo hice lo mas generico
posible, para no tener que limitarme a un horario laboral establecido
fijo. Ergo, podria ser que et = 06:00 y st = 12:00 y el algoritmo
tendria que andar igual. Aclaro tambien que hay varios turnos, y que
varian en funcion de las necesidades de la empresa.
Por otra parte, la discriminacion estre horas normales, extras, etc...
lo hago afuera del cálculo del algoritmo. Eso es porque tengo que
considerar algunos casos medio "extraños". Como ejemplo te cito uno:
Los sabados, las horas trabajadas se discriminan asi:
[07:00 .. 11:00] se consideran normales
[11:00 .. 13:00] se consideran extras al 50%
[13:00 .. 21:00] se consideran extras al 100%
Logicamente, dependiendo del turno que tenga que realizar, se aplica
cada caso en particular. Es por eso que la discriminacion de normales,
extras y nocturnas las hago afuera.
Te expongo mi estrategia: particionar el dia laboral en "compartimientos
estancos", segun el siguiente detalle:
Horarios diurnos:
[06:00 .. 11:00]
[11:00 .. 13:00]
[13:00 .. 21:00]
Horarios nocturnos:
[21:00 .. 23:59]
[00:00 .. 06:00]
Para esto tengo que tener en cuenta como caen los horarios en funcion
del "compartimiento estanco". Y es por eso que calculo, en funcion de
estas 6 variables de horas, la cantidad de horas que trabajo antes de
turno (y que corresponden a la franja horaria del "compartimiento
estanco"), la cantidad de horas que trabajo en su turno (y que
corresponden a la franja horaria del "compartimiento estanco") y la
cantidad de horas que trabajo después de finalizado su turno (y que
corresponden a la franja horaria del "compartimiento estanco")
Lo unico que se me ocurre es contemplar cada caso en particular. Es
decir, tomando los horarios [et, st, er, sr, li, ls] ir jugando con las
distintas alternativas. Un calculo rapido me da 720 posibilidades. Hay
algunas posibilidades que no se aplican, gracias a las restricciones que
puse (es decir, et < st; er < sr y li < ls) pero creo que aun asi son
muchas.
En cuanto al tema de los "minutos", es simple. Si trabaja más de 40
minutos, se computa 1 hora más, y si trabaja entre 20 minutos y 40
minutos de más, se computa 0.5 horas más.
En el caso de ejemplo que expuse, no lo "penalizo" media hora...
simplemente, me olvide de considerar el "compartimiento estanco" desde
las 00:00 hasta las 06:00. Siguiendo el mismo ejemplo:
et = 07:00 st = 15:00
er = 05:30 sr = 18:25
li = 00:00 ls = 06:00
preh = 0.5 (desde 05:30 hasta 06:00)
enh = 0
posth = 0
Si se te ocurre alguna manera mas piola (e inteligente) de manejar el
problema, estoy a tu entera disposicion.
Ah! desde ya, muchisimas gracias.
Julio.
Héctor Miguel escribió:
entiendo que las necesidades de control-horario de una empresa sean tan 'variadas' [quizas] como empresas existen :))
entiendo que los turnos 'aplicables' incluyan tambien 'dias especiales "trabajados"' [fines de semana, festivos, vacaciones, etc.]
supongo que existen casos donde no seria totalmente 'apicable' [p.e.] una restriccion del tipo: et < st [21:00 <-> 08:45] -???-
supongo que el tiempo extra [al 50% - 100%] para los sabados pudiera no ser aplicable para los dias 'normales' [luego entonces]...
intuyo que se necesita saber de que dia 'estmos hablando' y/o de una 'entrada desde el dia anterior' / 'salida hasta el dia siguiente' -?-
cuando te solicitaba exponer...
-> "... 'realidades' mas... 'visibles' como..."
" a) rangos de donde 'tomar' las variables et, er, [etc. etc. etc.]"
" b) las formulas que estas utilizando actualmente [y si les falla... donde, cuando y por que]"
-> [te lo aseguro] NO 'era' con la finalidad de 'saber mas de lo necesario' :))
sino porque conozco que 'trabajar' con horarios [generalmente] tiene sus 'visicitudes' :D
asumiendo que las 'variables' [y sus variaciones] no son 'sencillas' de exponer en pocas lineas :)) te sugiero:
a) buscar un lugar [hospedaje web] donde 'colgar' un archivo con casos practicos REALES
b) solicitar a quien lo pueda/quiera recibir en correspondencia 'directa' [para mi, solo quita de la direccion el 'NO...SPAM...PLS']
c) ver/descargar ejemplos [p.e. en paginas como]: http://www.cpearson.com/excel/overtime.htm
d) revisar las siguientes conversaciones: -> http://tinyurl.com/2zzkcu
e) exponer/comentar 'realidades' mas... 'visibles' [hojas rangos datos formulas etc.]
si cualquier duda [o informacion adicional]... comentas ?
saludos,
hector.
__ la consulta original __
> ... El algoritmo lo hice lo mas generico posible, para no tener que limitarme a un horario laboral establecido fijo.
> Ergo, podria ser que et = 06:00 y st = 12:00 y el algoritmo tendria que andar igual.
> Aclaro tambien que hay varios turnos, y que varian en funcion de las necesidades de la empresa.
> Por otra parte, la discriminacion estre horas normales, extras, etc... lo hago afuera del calculo del algoritmo.
> Eso es porque tengo que considerar algunos casos medio "extra#os". Como ejemplo te cito uno:
> Los sabados, las horas trabajadas se discriminan asi:
> [07:00 .. 11:00] se consideran normales
> [11:00 .. 13:00] se consideran extras al 50%
> [13:00 .. 21:00] se consideran extras al 100%
> Logicamente, dependiendo del turno que tenga que realizar, se aplica cada caso en particular.
> Es por eso que la discriminacion de normales, extras y nocturnas las hago afuera.
> Te expongo mi estrategia: particionar el dia laboral en "compartimientos estancos", segun el siguiente detalle:
> Horarios diurnos:
> [06:00 .. 11:00]
> [11:00 .. 13:00]
> [13:00 .. 21:00]
> Horarios nocturnos:
> [21:00 .. 23:59]
> [00:00 .. 06:00]
> Para esto tengo que tener en cuenta como caen los horarios en funcion del "compartimiento estanco".
> Y es por eso que calculo, en funcion de estas 6 variables de horas, la cantidad de horas que trabajo antes de turno
> (y que corresponden a la franja horaria del "compartimiento estanco"), la cantidad de horas que trabajo en su turno
> (y que corresponden a la franja horaria del "compartimiento estanco") y la cantidad de horas que trabajo despues de finalizado su turno
> (y que corresponden a la franja horaria del "compartimiento estanco")
> Lo unico que se me ocurre es contemplar cada caso en particular. Es decir, tomando los horarios [et, st, er, sr, li, ls]
> ir jugando con las distintas alternativas. Un calculo rapido me da 720 posibilidades.
> Hay algunas posibilidades que no se aplican, gracias a las restricciones que puse (es decir, et < st; er < sr y li < ls)
> pero creo que aun asi son muchas...
No hay inconveniente... no hay nada decreto en esto. Simplemente, quise
acotar la complejidad del algoritmo para poder concentrarnos solamente
en eso, y dejar de lado las cuestiones que, desde el punto de vista de
la ejecución del algoritmo (horas extras, nocturnas, etc) son irrelevantes.
El tema que expones es cierto, pero como manejo los tiempos como
"FechaHora", no tengo problemas a la hora de comparar. Siguiendo el
ejemplo que planteas,
et = 21:00 < st = 08:45, porque
Dia(et) = Dia(st) - 1
Todas las variables (et, st, er, sr, li, ls) toman valores horarios, de
00:00 a 23:59, considerando el caso especial que planteabamos anteriormente.
Estoy armando funciones en VBA para el manejo de los tiempos. No los
puse aca porque las estoy modificando a medida que se me ocurren las
ideas. La última versión es la que adjunto.
En cuanto a los casos posibles, arme un "programita" que me tira todos
los casos posibles, que resultaron ser 90 (un numero grande, pero mas
manejable que 720, jejejeje).
Es en estos momentos en los que me dejo de quejar de las clases de
Combinatoria en la facultad! (mas jejejes)
Bue, el codigo VBA para generar los casos de uso es:
Private Sub CommandButton1_Click()
Dim f As Long, i As Long
Dim Pos(1 To 6) As Byte
Dim t As String
Dim j As Byte
Dim z As Boolean
' Cada i representa el ordenamiento de las horas involucradas.
' Donde 1 = et, 2 = st, 3 = er, 4 = sr, 5 = li, 6 = ls
f = 1
i = 123456 'es el minimo i que cumple con el ordenamiento
t = ""
While i <= 654321 'es el maximo i que cumple con el ordenamiento
t = Format(i, "000000") 'variable donde almaceno i como texto
z = False ' me indica si algundigitos esta ausente en i
' Almaceno las posiciones de los digitos 1, 2, 3, 4, 5, 6 en t
For j = 1 To 6
Pos(j) = InStr(t, Format(j, "0"))
If Pos(j) = 0 Then
z = True
End If
Next
If Not z Then
If (Pos(1) < Pos(2) And Pos(3) < Pos(4) And Pos(5) <
Pos(6)) Then
Sheets("Hoja2").Cells(f, 1).Value = f
Sheets("Hoja2").Cells(f, 2).Value = t
f = f + 1
End If
End If
i = i + 1
Wend
MsgBox ("Terminado!")
End Sub
Voy a mirar los links que me mandaste.
Si tengo exito te chiflo. Gracias!
Héctor Miguel escribió:
> ... Todas las variables (et, st, er, sr, li, ls) toman valores horarios, de 00:00 a 23:59
> considerando el caso especial que planteabamos anteriormente.
> Estoy armando funciones en VBA para el manejo de los tiempos.
> No los puse aca porque las estoy modificando a medida que se me ocurren las ideas.
> La ultima version es la que adjunto.
> En cuanto a los casos posibles, arme un "programita" que me tira todos los casos posibles
> que resultaron ser 90 (un numero grande, pero mas manejable que 720, jejejeje).
> Es en estos momentos en los que me dejo de quejar de las clases de Combinatoria en la facultad! (mas jejejes)
1) no acabo de entender 'como' reduces las permutaciones posibles para una matriz de 6 elementos
de 720 posibilidades [=permutaciones(6,6)] -> a solo 90 -???-
2) si solo necesitas las 'combinaciones' posibles para una matriz de 6 elementos en 'pares'... [entrada <-> salida]
12, 13, 14, 15, 16 <-> 34, 35, 36, 31, 32 <-> [etc. etc. etc.]
=combinat(6,2) -> devuelve solo 15 posibilidades
3) si deseas incluir la probabilidad de entrada versus salida en el mismo turno que la entrada [dia anterior / siguiente]
=combinat(6+1,2) -> devuelve solo 21 posibilidades
cualquiera de las posibles 'combinaciones' es menor que las 90 que determinas 'discrecionalmente' en el codigo ;)
[bue... creo que] me espero a que visites los links sugeridos y/o por cualquier informacion adicional :))
saludos,
hector.
__ el codigo expuesto __
> Voy a mirar los links que me mandaste. Si tengo exito te chiflo...
Supongo que si aplicara conocimientos de combinatoria te podria
contestar facilmente. Pero creo que va a ser mas facil si te muestro
el codigo VBA que me da los famosos 90 casos:
Private Sub cmdCombinaciones_Click()
Dim Pos(1 To 6) As Byte 'Almacena las posiciones relativas de
los digitos 1..6
Dim i As Byte
Dim r As Byte
Dim n As Long
Dim valido As Boolean
'Estrategia: buscar todos los numeros entre 123456 y 563412
'que cumplan con la siguiente condicion:
'
'Pos(1)<Pos(2) and Pos(3)<Pos(4) and Pos(5)<Pos(6)
'
' El menor valor que puede tomar las combinaciones
n = 123456
' La fila donde voy a meter el numero
r = 1
While n <= 563412
valido = True
For i = 1 To 6
Pos(i) = InStr(Format(n, "000000"), Format(i, "0"))
Next i
' Si hay algun Pos(i) = 0, quiere decir que
' hay algun i que no esta en el numero, entonces, no es valido
For i = 1 To 6
If Pos(i) = 0 Then
valido = False
End If
Next i
' Si el numero tiene todos los digitos entre 1 y 6,
' verifico que ademas se cumpla la condicion
valido = valido And (Pos(1) < Pos(2) And _
Pos(3) < Pos(4) And _
Pos(5) < Pos(6))
If valido Then
Sheets("Hoja1").Cells(r, 1) = r
Sheets("Hoja1").Cells(r, 2) = n
Sheets("Hoja1").Cells(r, 3) = Pos(1)
Sheets("Hoja1").Cells(r, 4) = Pos(2)
Sheets("Hoja1").Cells(r, 5) = Pos(3)
Sheets("Hoja1").Cells(r, 6) = Pos(4)
Sheets("Hoja1").Cells(r, 7) = Pos(5)
Sheets("Hoja1").Cells(r, 8) = Pos(6)
r = r + 1
End If
n = n + 1
Wend
End Sub
Reemplazando
1 = et
2 = st
3 = er
4 = sr
5 = li
6 = ls
queda claro que el código me muestra las unicas 90 combinaciones que
cumplen con las condiciones.
Creo que logre hacerlo. La planilla es medio pesadita, pero va en
relacion con el grado de "inteligentzia" del que dispone.
On 6 abr, 03:48, "Héctor Miguel" <NOhemiordiS...@PLShotmail.com>
wrote: