Calcular Días laborales en Visual Basic .Net con SQL
June 3, 2009 by Rafael Villafuerte
Hace ya algunos meses desarrollé un Sistema Electrónico de Trámite Documentario en Visual Basic .NET 2005 usando como gestor de BD el SQL Server 2008 para un municipio de mi ciudad.
Bueno he buscado por todos lados este código, pero no lo encontré, así que yo mismo tube que hacerlo y lo comparto en este mi BLOG a Ustedes y se que les va a ser de gran ayuda. La programación que hice es Semi-Estructurada ( Utiliza Clases en algunos casos ). Uds. ya vean como acomodan el código.
1.- Deben de incluir la Funcion Días Laborales en alguna parte de su código, si la van a usar constantemente lo recomentable sería incluirlo en una clase como yo lo hice, como ven esta funcion tiene dos parámetros o datos de entrada: La fecha inicial para indicar el rango de inicio y la fecha final para indicar el rango de fin, es decir calculará los días laborales contenidos entre las dos fechas excluyendo días feriados, festivos, sabados y domingos. El parámetro que se envía luego de @FechaInicial y @Fecha final , es decir @ Dias Laborales es un parámetro OUTPUT de salida en el procedimiento almacenado, es por ello que tiene el Valor de 0. Esta función retorna la cantidad entera de días laborables que existe entre el rango de fechas.
Function DiasLaborales(ByVal fechainicial As Date, ByVal fechafinal As Date) As Integer
Dim diaslab As Integer = 0
Dim ini As Date = Format(fechainicial, “dd/MM/yyyy”)
Dim fin As Date = Format(fechafinal, “dd/MM/yyyy”)
‘Dim com As New SqlCommand(”DECLARE @DiasLaborales int EXEC DifDias @FechaInicial,@FechaFinal,@DiasLaborales output PRINT @DiasLaborales”, conexion)
Dim com As New SqlCommand(”DifDias”, conexion)
com.CommandType = CommandType.StoredProcedure
com.Parameters.Add(”@FechaInicial”, SqlDbType.DateTime).Value = ini
com.Parameters.Add(”@FechaFinal”, SqlDbType.DateTime).Value = fin
com.Parameters.Add(”@DiasLaborales”, SqlDbType.Decimal).Value = 0
conexion.Open()
diaslab = com.ExecuteScalar
conexion.Close()
Return diaslab
End Function
2.- Deberán crear mediante el Analizador de Consultas del SQL Server el siguiente Procedimiento Almacenado llamado “DifDias”, recuerden que la función anterior hace la llamada a este procedimiento mediante un Comand Execute, enviando dos parámetros de : Fecha Inicio, Fecha Fin y el resultado será devuelto mediante el parámetro de Salida: DiasLaborales.
CREATE PROCEDURE DifDias
@FechaInicial DATETIME,
@FechaFinal DATETIME,
@DiasLaborales INT OUTPUT
AS
BEGIN
DECLARE @RangoDiasNormales INT
DECLARE @Cnt INT
DECLARE @cantidad INT
DECLARE @FechaComparacion DATETIME
DECLARE @fechafiesta VARCHAR(5)
DECLARE @ini VARCHAR(10)
DECLARE @fin VARCHAR(10)
SELECT @RangoDiasNormales = 0
SELECT @DiasLaborales = 0
SELECT @Cnt=0
SELECT @cantidad=0
IF ((datepart(dw,@FechaFinal) = 6) or (datepart(dw,@FechaFinal) = 7))
BEGIN
SELECT @RangoDiasNormales = DATEDIFF(DAY,@FechaInicial,@FechaFinal)
END
ELSE
BEGIN
SELECT @RangoDiasNormales = DATEDIFF(DAY,@FechaInicial,@FechaFinal) + 1
END
SELECT @ini = (SELECT CAST((CAST(datepart(dd,@FechaInicial)AS
VARCHAR(2))+’/'+ CAST(datepart(mm,@FechaInicial)AS
VARCHAR(2))+’/'+CAST(datepart(yy,@FechaInicial)AS VARCHAR(4))) as
varchar(10)))
SELECT @fin = (SELECT CAST((CAST(datepart(dd,@FechaFinal)AS
VARCHAR(2))+’/'+ CAST(datepart(mm,@FechaFinal)AS VARCHAR(2))+’/'+
CAST(datepart(yy,@FechaFinal)AS VARCHAR(4)))as varchar(10)))
IF @ini <>@fin
BEGIN
IF @RangoDiasNormales = 2
BEGIN
SELECT @DiasLaborales = 1
END
ELSE
BEGIN
WHILE @Cnt < @RangoDiasNormales
BEGIN
SELECT @FechaComparacion = @FechaInicial + @Cnt
IF ((datepart(dw,@FechaComparacion) <> 6) and (datepart(dw,@FechaComparacion) <> 7))
BEGIN
SELECT @fechafiesta = (SELECT CAST((CAST(datepart(dd,@FechaComparacion)AS
VARCHAR(2))+’/'+ CAST(datepart(mm,@FechaComparacion)AS VARCHAR(2)))as varchar(5)))
SELECT @cantidad=(SELECT COUNT(*) FROM TDIAS_NOLABORABLES WHERE FECHA=@fechafiesta)
IF @cantidad=1
BEGIN
SELECT @DiasLaborales = @DiasLaborales
END
ELSE
BEGIN
SELECT @DiasLaborales = @DiasLaborales + 1
END
END
SELECT @Cnt = @Cnt + 1
END
END
END
ELSE
BEGIN
SELECT @DiasLaborales = 0
END
SELECT DiasLaborales = @DiasLaborales
END
Sabado se representa con el número 6 y Domingo con el 7, como ya había indicado al inicio de este Post, considera unicamente días laborables, es decir de Lunes a Viernes excluyendo los dias feriados y festivos, es decir : Lunes a Sabados excluyendo feriados y festivos , deberán quitar todas las comparaciones que se hacen con el DATEPART en 6 ( Sábados). Si la fecha inicial o final cae un día Sábado o Domingo esta no será contabilizada, Ojo! … sólo hace el calculo de dias entre Lunes a Viernes.
3.- El procedimiento almacenado anterior, hace uso de la tabla “TDIAS_NOLABORABLES”, para definir los días no laborables, festivos y feriados, deberán incluir entre sus tablas , la siguiente tabla:
CREATE TABLE TDIAS_NOLABORABLES
(
ID_DNL INT NOT NULL PRIMARY KEY IDENTITY(1,1),
FECHA CHAR(5),
DESCRIPCION VARCHAR(50)
)Algunos registros de ejemplo:
INSERT INTO TDIAS_NOLABORABLES VALUES (’1/1′,’AÑO NUEVO’)
INSERT INTO TDIAS_NOLABORABLES VALUES (’9/4′,’JUEVES SANTO’)
INSERT INTO TDIAS_NOLABORABLES VALUES (’10/4′,’JUEVES SANTO’)
INSERT INTO TDIAS_NOLABORABLES VALUES (’1/5′,’DIA DEL TRABAJO’)
INSERT INTO TDIAS_NOLABORABLES VALUES (’29/6′,’DIA DE SAN PEDRO’)
INSERT INTO TDIAS_NOLABORABLES VALUES (’28/7′,’DIA DE LA INDEPENDENCIA’)
INSERT INTO TDIAS_NOLABORABLES VALUES (’8/10′,’COMBATE DE ANGAMOS’)
INSERT INTO TDIAS_NOLABORABLES VALUES (’8/12′,’CONCEPCION DE MARIA’)
INSERT INTO TDIAS_NOLABORABLES VALUES (’25/12′,’NAVIDAD’)
4.- Ahora viene lo mas emocionante, “el funcionamiento”, como yo declaré dentro de una clase mi función hago la llamada a esa clase para heredar todos los métodos, en este caso uno de mis metodos es la función DiasLaborales. Mi Clase de llama ” Funciones” , primero declaro que la variable “funcion” es mi clase “Funciones”.
Dim funcion As New Funciones
Luego, en algún procedimiento, función, u otro tipo de estructura puedo llamar a mi función “DiasLaborales” contenida en mi clase “Funciones”, de la siguiente manera:
c= funcion.DiasLaborales(i,f)
Donde:
- i: Es la fecha inicial, variable de tipo DateTime
- f:Es la fecha final, variable de tipo DateTime
- c:Es la cantidad de dias laborales entre i - f, variable de tipo Entero
Espero que les haya servido de gran ayuda, ya que yo cuando busqué algo así no lo encontré, y bueno espero que agradezcan con un comentario.
Atte: Rafael Villafuerte




te amo men graciass eres un genioo estaba buscando estooo gracias mil veces gracias men
esta bien chula la programación.
excelente gracias por el codigo
buena aportacion