|
| |
 |
 |
 |
 |
 |
 |
 |
 |
|
DiasLaborables |
 |
 |
|
Para calcular los días
laborables
que hay entre dos fechas basta con calcular los días que hay entre esas dos
fechas y restarles los festivos.
Tenemos dos tipos distintos de
festivos y, por tanto, tendremos
que hacer dos cálculos
distintos:
Por
un lado, tenemos las fiestas
nacionales, locales, etc. que
variarán de un sitio a otro y de
un año a otro, por lo que no
queda más remedio que guardarlas
en una tabla al efecto. Calcular
cuántas fiestas de éstas hay en
un periodo es tan sencillo como
hacer un dCount() sobre la tabla
de festivos usando como criterio
la fecha de inicio y del final.
Por
otro lado tenemos los sábados y
domingos, que es un dato fijo y
podemos obtener mediante
cálculos. Habitualmente, este
cálculo se hace recorriendo con
un bucle todos los días del
periodo y comprobando para cada
uno si es sábado o domingo; sin
embargo una forma más sencilla y
bastante más eficaz, que es la
que vamos a usar aquí, parte de
la idea de que el número de
sábados, o domingos, entre dos
fechas es igual que el número de
semanas que empiezan por sábado,
o domingo, entre esas dos
fechas. En la práctica resulta
que no es así, pues si la fecha
de inicio del periodo es sábado
o domingo hay un festivo más,
pero no es ningún problema:
añadimos esta corrección al
procedimiento y funciona
perfectamente.
En
la función DiasLaborables,
incluyo todo esto, pero también
añado la función
WorkingDays que hace
exactamente lo mismo, pero
separando el cálculo de sábados
y domingos que lo hace mediante
una llamada a otra función,
WeekendDays, de la cual incluyo
dos versiones distintas,
WeekendDays2 que utiliza el
método de calcular los fines de
semana con DateDiff() y
WeekendDays que hace el
cálculo a base de operaciones
básicas sin usar ningún bucle ni
ninguna función de fecha.
De
los tres métodos, el más
eficiente es usar
WorkingDays con la función
WeekendDays pues resulta más
rápido; sin embargo, la
diferencia de velocidad no es
mucha pues la llamada al dCount()
es idéntica en ambos casos y es
lo que más retarda la función;
además lo que se gana en
velocidad, apenas nada, se
pierde en claridad del
procedimiento, por lo que yo
aconsejo usar DiasLaborables().
|
|
'---------------------------------------------------------------------------------------
' Procedure : DiasLaborables
' DateTime : 25/09/2005
' Author : José Bengoechea Ibaceta (Chea)
' Purpose : Calcular el número de días laborables entre dos fechas. Si se
' : le pasan los argumentos opcionales NombreTablaFestivos y
' : NombreCampoFestivo, tiene también en cuenta los días festivos
' : que estén guardados en un campo con nombre NombreCampoFestivo
' : en la tabla con nombre NombreTablaFestivos.
' Estás autorizado a utilizar este código dentro de una aplicación
' siempre que esta nota de autor permanezca inalterada.
' En el caso de querer publicarlo en una página Web, por favor,
' contactar con el autor en
'
' UA@bengoechea.net
'---------------------------------------------------------------------------------------
'
Public Function DiasLaborables(FechaDesde As Date, FechaHasta As Date, Optional _
NombreTablaFestivos As String, Optional NombreCampoFestivo As String) As Long
Dim Laborables As Long
On Error GoTo DiasLaborables_Error
Laborables = 1 + (FechaHasta - FechaDesde)
If NombreTablaFestivos <> "" And NombreCampoFestivo <> "" Then
Laborables = Laborables - DCount("*", NombreTablaFestivos, "[" & _
NombreCampoFestivo & "] Between #" & Format(FechaDesde, "mm/dd/yyyy") & _
"# AND #" & Format(FechaHasta, "mm/dd/yyyy") & "#")
End If
Laborables = Laborables - DateDiff("ww", FechaDesde, FechaHasta, vbSaturday)
Laborables = Laborables - DateDiff("ww", FechaDesde, FechaHasta, vbSunday)
Laborables = Laborables + (Weekday(FechaDesde, vbSunday) = 1)
Laborables = Laborables + (Weekday(FechaDesde, vbSaturday) = 1)
DiasLaborables = Laborables
On Error GoTo 0
Exit Function
DiasLaborables_Error:
MsgBox "Error " & Err.Number & " (" & Err.Description & _
") in procedure DiasLaborables"
End Function
|
|
|
|
 |
 |
|
 |
 |
|
 |
 |
 |
 |
 |
 |
 |
 |
 |
 |
|
WeekendDays |
 |
 |
|
Para calcular los días hábiles
que hay entre dos fechas, debemos calcular primero cuántos sábados y domingos
hay para descontarlos. Habitualmente esto se hace recorriendo con un bucle todas
las fechas y comprobando en cada una qué día de la semana es, pero yo quería
hacerlo directamente sin bucles ni funciones de fechas, con un rendimiento más
eficiente aunque apenas se note. Para lo que sí que sirve este ejemplo es para
demostrar que las fechas se pueden manejar con las cuatro operaciones básicas.
|
|
'---------------------------------------------------------------------------------------
' Procedure : WeekendDays
' DateTime : 19/09/2005
' Author : José Bengoechea Ibaceta(Chea)
' Purpose : Calcular la suma de sábados y domingos entre dos fechas sin utilizar
' : ni bucles ni funciones de fecha.
' Estás autorizado a utilizar este código dentro de una aplicación
' siempre que esta nota de autor permanezca inalterada.
' En el caso de querer publicarlo en una página Web, por favor,
' contactar con el autor en
'
' UA@bengoechea.net
'---------------------------------------------------------------------------------------
Public Function WeekendDays(DateStart As Date, DateEnd As Date) As Long
Dim TotalDias As Long, SemanasCompletas As Long, RestoDias As Long, wdResto _
As Long, wkd As Long
TotalDias = 1 + DateEnd - DateStart
SemanasCompletas = TotalDias \ 7
RestoDias = TotalDias Mod 7
'Calculamos el día de la semana del primer día del resto
'wdResto = Weekday(DateEnd - (RestoDias - 1), vbMonday)
'Como no quiero usar funciones de fecha, en vez de la línea anterioruso la siguiente
wdResto = 1 + ((DateEnd - (RestoDias - 1) + 5) Mod 7)
wkd = SemanasCompletas * 2
'Si el resto de días + el día de la semana (empezando en lunes) es mayor que 6, nos
' cabe un sábado y, si además es mayor que 7, nos cabe un domingo.
If RestoDias > 0 Then
If (RestoDias + wdResto > 6) Then wkd = wkd + 1
If (RestoDias > 1) And (RestoDias + wdResto > 7) And _
(Weekday(DateStart) <> 1) Then wkd = wkd + 1
End If
WeekendDays = wkd
End Function
|
|
|
|
 |
 |
|
 |
 |
|
 |
 |
 |
 |
 |
 |
 |
 |
 |
 |
|
WeekendDays2 |
 |
 |
|
Una de las formas más directas de calcular sábados y
domingos entre dos fechas es comprobar con DateDif ("ww"...) cuántas semanas hay
que empiezan por sábado y cuántas que empiecen por domingo y sumarle uno más si
la primera fecha para el cálculo es sábado o domingo.
|
|
'---------------------------------------------------------------------------------------
' Procedure : WeekendDays2
' DateTime : 24/09/2005 15:23
' Author : Chea
' Purpose : Calcular la suma de sábados y domingos entre dos fechas sin utilizar
' : bucles
' Estás autorizado a utilizar este código dentro de una aplicación
' siempre que esta nota de autor permanezca inalterada.
' En el caso de querer publicarlo en una página Web, por favor,
' contactar con el autor en
'
' UA@bengoechea.net
'---------------------------------------------------------------------------------------
Public Function WeekendDays2(DateStart As Date, DateEnd As Date) As Long
Dim wkd As Long
wkd = DateDiff("ww", DateStart, DateEnd, vbSaturday) + DateDiff("ww", _
DateStart, DateEnd, vbSunday)
If Weekday(DateStart, vbSunday) = 1 Then wkd = wkd + 1
If Weekday(DateStart, vbSaturday) = 1 Then wkd = wkd + 1
WeekendDays2 = wkd
End Function
|
|
|
|
 |
 |
|
 |
 |
|
 |
 |
 |
 |
 |
 |
 |
 |
 |
 |
|
WorkingDays |
 |
 |
|
Basta calcular los días que hay entre dos fechas y
restarle los sábados y domingos, que obtenemos con la función WeekEndDays, y los
festivos que tenemos en una tabla y que obtenemos con dCount().
|
|
Option Compare Database
Option Explicit
''---------------------------------------------------------
' WorkingDays
'
' Código escrito originalmente por José Bengoechea Ibaceta
' (Chea) y Juan M Afán de Ribera.
' Estás autorizado a utilizarlo dentro de una aplicación
' siempre que esta nota de autor permanezca inalterada.
' En el caso de querer publicarlo en una página Web,
' por favor, contactar con los autores en
'
' accessvba@ya.com
'
' Este código se brinda por cortesía de
' José Bengoechea Ibaceta (Chea)
' Juan M. Afán de Ribera
'
Function WorkingDays( _
DateStart As Date, _
DateEnd As Date, _
Optional TableName As String, _
Optional FieldName As String) As Long
Dim SQL As String
Dim Holidays As Long
If DateStart < DateEnd Then
On Error Resume Next
Holidays = DCount("*", TableName, "[" & FieldName & "] Between #" _
& Format(DateStart, "mm/dd/yyyy") & " AND #" & Format(DateEnd, "mm/dd/yyyy") & "#")
Err.Clear
WorkingDays = (DateEnd - DateStart) - (Holidays + WeekendDays(DateStart, DateEnd))
End If
End Function
|
|
|
|
 |
 |
|
 |
 |
|
 |
 |
|