Con el siguiente código se calcula 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.


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

La función WeekendDays calcula la suma de sábados y domingos entre dos fechas sin utilizar ni bucles ni funciones de fecha.


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 &gt; 0 Then
If (RestoDias + wdResto &gt; 6) Then wkd = wkd + 1
If (RestoDias &gt; 1) And (RestoDias + wdResto &gt; 7) And _
(Weekday(DateStart) &lt;&gt; 1) Then wkd = wkd + 1
End If
WeekendDays = wkd
End Function

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.


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

Y para terminar 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().


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 &lt; DateEnd Then
On Error Resume Next
Holidays = DCount("*", TableName, "[" &amp; FieldName &amp; "] Between #" &amp; Format(DateStart, "mm/dd/yyyy") &amp; " AND #" &amp; Format(DateEnd, "mm/dd/yyyy") &amp; "#")
Err.Clear
WorkingDays = (DateEnd - DateStart) - (Holidays + WeekendDays(DateStart, DateEnd))
End If
End Function

Fuente: Utilidades Access

8 Responses to “Cálculo del número de días laborales o festivos”

  1. Paula Says:

    Hola
    me parecio excelente el articulo
    pero te cuento que a partir de estoy tratando de generar otra funcion
    se trata de como hacer (en access) que si le entrego el numero de semana y año, al funcion me devuelva el rango de fechas…por ejemplo, la semana 1 del 2008 va entre el 1/1/08 y el 6/1/08…
    me puedes ayudar??? por favor es que en el trabajo estoy metida hace varios dias sin poder solucionarlo…saludos.
    Paula.

  2. Lumbanico Says:

    Hola paula,

    Acabo de posterar en el blog una función con la que creo que se obtienen los resultados a los que hacías referencia en tu comentario.

    http://lumbanico.wordpress.com/2008/02/27/intervalo-de-fechas-de-una-semana-del-ano/

    Un saludo.

  3. Fatiga Says:

    Hola. Yo lo que estoy tratando de encontrar es la forma de que access me devuelva una fecha (en día hábil) después de sumarle a otra fecha (también hábil) un número de días (que también deberán ser hábiles).
    Cuando digo hábiles me refiero a laborables.
    La idea es poder calcular vencimientos. Que el programa me permita añadir a una fecha determinada, por ejemplo, 7 días hábiles.

    Gracias por la ayuda que puedas prestarme

  4. lumbanico Says:

    Creo que la siguiente función te puede ayudar. Pasándole una fecha y el número de días hábiles que deseas sumarle te devuelve la fecha hábil. Para este cálculo también utilizar una tabla (tblFes) en la que se guardan los días festivos (distintos de domingos y sábados) que los tiene en cuenta para hacer el cálculo.

    Function IPublica(d As Date, p As Integer) As Date
    On Error GoTo Err_IPublica

    Dim a As Integer
    Dim f As Date

    While a < p

    IPublica_1:

    If Weekday(d, vbMonday) = 6 Then d = d + 1: GoTo IPublica_1
    If Weekday(d, vbMonday) = 7 Then d = d + 1: GoTo IPublica_1
    If IsNull(DLookup(”IdFes”, “tblFes”, “FesFecha=#” & Format(d, “mm/dd/yyyy”) & “#”)) = False Then d = d + 1: GoTo IPublica_1

    d = d + 1
    a = a + 1

    Wend

    IPublica_2:

    If Weekday(d, vbMonday) = 6 Then d = d + 1: GoTo IPublica_2
    If Weekday(d, vbMonday) = 7 Then d = d + 1: GoTo IPublica_2
    If IsNull(DLookup(”IdFes”, “tblFes”, “FesFecha=#” & Format(d, “mm/dd/yyyy”) & “#”)) = False Then d = d + 1: GoTo IPublica_2

    IPublica = d

    Exit_IPublica:
    Exit Function

    Err_IPublica:
    MsgBox Err.Description
    Resume Exit_IPublica

    End Function

  5. Fatiga Says:

    Si, gracias. Parece lo que busco. Pero ahora me doy cuenta de que hace mucho que no uso el access (aclaro que siempre fui bastante intuitivo, es decir no se de programación ni de sql) y ahora no me acuerdo como se hace para incorporar una función como esta. Me refiero a que no se donde debo copiarla para que funcione.
    Estoy tratando de encontrar en tu blog si está explicado esto.
    Gracias de nuevo.

  6. lumbanico Says:

    El código de la función debes añadirlo a un módulo de la base de datos de access, y llamarla desde algún evento de un formulario de la siguiente forma: IPublica(21/06/2008,10). Así se añadirán 10 días al 21/06/2008.

  7. Fatiga Says:

    Que bueno, me llegó tu respuesta justo cuando estaba explorando los módulos. Poco a poco voy recordando. Muchas gracias por la atención.
    Paso al análisis.
    1) Cuando cargo la función, me saltan dos errores de compilación, ambos en el renglón de If IsNull. Aparentemente le faltaría (criteria) en “FesFecha=#”.
    2) Puedo hacer que me pregunte el número de días en el evento? Vos me ponés 10, pero para mi, ese número será siempre distinto.

    Muchas gracias, de nuevo.

  8. lumbanico Says:

    He añadido un nuevo post con ejemplo que espero que solucione tus dudas.

    Un saludo.

    http://lumbanico.wordpress.com/2008/06/24/diashabiles/


Leave a Reply