MOSTRAR RELACIÓN DE FECHAS ENTRE DOS FECHAS

Hola a todos!.

Hace unos días me hacían una consulta a través de LinkedIn que trataba sobre cómo se podía generar automáticamente todas las fechas comprendidas entre dos fechas (inicial y final).

Aunque esto es posible realizarlo mediante fórmulas, creo que lo más oportuno es hacerlo con VBA, ya no solo por la rapidez sino por todas las posibilidades que ofrece para luego poder pasar estos datos a un formulario con cuadros de lista o combos.

Para este ejercicio voy a plantear dos situaciones, una en la que queremos obtener todas las fechas y otra en la que queremos obtener solo los días hábiles y omitiendo también festivos.

Veamos la primera, obtener todas las fechas, para ello imaginad que tenemos las siguiente fechas en nuestra hoja Excel:

MOSTRAR RELACION DE FECHAS ENTRE DOS FECHAS

y queremos obtener todas las fechas que comprenden desde el 01/05/2018 hasta el 15/05/2018. Para poder hacerlo vamos a utilizar esta macro:

Sub obtener_fechas()
'Declaramos variables
Dim inicio As Date, fin As Date, nCont As Date
Dim sCadena As String, fsem As String
Dim matriz As Variant, j As Double
With Sheets("FECHAS")
'Indicamos las celdas con la fecha inicio y fin
inicio = .Cells(1, 2)
fin = .Cells(2, 2)
'Mediante un loop añadimos un día a la fecha inicial
'y guardamos fechas en la variable sCadena
Do While inicio < fin - 1
nCont = DateAdd("w", 1, inicio)
inicio = nCont
sCadena = sCadena & " " & inicio
Loop
'pasamos la información de la matriz a la hoja
matriz = Split(sCadena, " ")
For j = 1 To UBound(matriz)
.Cells(j, 3) = Format(matriz(j), "mm/dd/yyyy")
Next j
End With
End Sub

Como podéis observar, mediante un loop vamos añadiendo días a la fecha inicial de forma que vamos componiendo cada fecha hasta llegar a la fecha final. Esos datos los guardamos en una variable string como una cadena de texto que luego pasaremos a una matriz y finalmente a la hoja, este es el resultado:

MOSTRAR RELACION DE FECHAS ENTRE DOS FECHAS1

Ahora vamos con la segunda situación, es decir, queremos obtener sólamente los días hábiles y excluir festivos, para ello utilizaremos la misma macro pero con unas modificaciones:

Sub obtener_fechas_dias_lab()
'Declaramos variables
Dim inicio As Date, fin As Date, nCont As Date, dfest As Date
Dim sCadena As String, fsem As String, j As Double
Dim matriz As Variant
With Sheets("FECHAS")
'Indicamos las celdas con la fecha inicio y fin
inicio = .Cells(1, 2)
fin = .Cells(2, 2)
'Mediante un loop añadimos un día a la fecha inicial
'y guardamos fechas en la variable sCadena
Do While inicio < fin - 1
nCont = DateAdd("w", 1, inicio)
inicio = nCont
fsem = Format(inicio, "ddd")
dfest = CDate(.Cells(3, 2))
'Si el día es un sábado o domingo o un festivo no guardamos fecha
If fsem <> "sá." And fsem <> "do." And inicio <> dfest Then
sCadena = sCadena & " " & inicio
End If
Loop
'pasamos la información de la matriz a la hoja
matriz = Split(sCadena, " ")
For j = 1 To UBound(matriz)
.Cells(j, 4) = Format(matriz(j), "mm/dd/yyyy")
Next j
End With
End Sub

Para poder excluir los sábados y los domingos es necesario que podamos detectar los días en las fechas que vamos generando en el loop, esto lo hacemos con:

Format(inicio, "ddd")

Donde los sábados se representan como: “sá.” y los domingos como “do.“, es obvio que si estamos trabajando con otros idiomas debemos modificar e introducir los datos correspondientes . Con un condicional excluimos los sábados y los domingos y también la fecha del día festivo, finalmente la información es la siguiente:

MOSTRAR RELACION DE FECHAS ENTRE DOS FECHAS2

Y con esto ya hemos finalizado el ejercicio, ya podemos obtener los días entre dos fechas y listalos, (con o sin días laborales).

Espero que os resulte de utilidad!.

Descarga el archivo de ejemplo pulsando en: MOSTRAR RELACIÓN DE FECHAS ENTRE DOS FECHAS

¿Te ha resultado de interés?, puedes apoyar a Excel Signum con una pequeña donación.

Donate Button with Credit Cards

¡¡Muchas gracias!!

Anuncios

APLICAR FORMATO DE FECHA A UNA CADENA DE TEXTO USANDO ADO EN VBA

Hola a todos 🙂

Espero que os vaya muy bien!. En el post de hoy vamos a trabajar con ADO para dar formato de fecha a una cadena de texto.

El tema de las fechas aunque puede parecer sencillo, siempre es susceptible de complicarse. Y en muchas ocasiones el problema se debe al formato con el que llegan los datos que nos envían. En el post de hoy vamos a trabajar uno de esos formatos.

Vamos a ilustrarlo con un ejemplo, imaginad que abrís una petición en la red a favor del control de horarios y ruidos de los locales de ocio nocturno (¡todo un reto!). Y la aplicación que ha recogido los datos os envía un archivo con la siguiente información:

DAR FORMATO DE FECHA A UNA CADENA DE TEXTO USANDO ADO EN VBA

Efectivamente, los campos NOMBRE, PETICIÓN y FIRMA no tienen nada de particular, pero el campo FECHA DE FIRMA debería contar con un formato de fecha y si embargo nos llega como un texto. Esto es un problema, dado que a priori no vamos a poder trabajar fácilmente con este tipo de fechas y es más, necesitamos exportar algunas de las columnas del fichero a otra aplicación para generar otro tipo de informaciones.

Hemos elegido ADO para transferir la información de la hoja BASE a la hoja INFORMACIÓN y será en ese proceso en el que vamos a utilizar SQL para formatear las fechas y también controlar aquellas celdas que se encuentren vacías.

Para hacer el trabajo, os dejo esta macro que es capaz formatear solo las celdas que contienen la fecha:

Sub CONEXION_SQL_FECHAS()
'Declaramos variables
Dim Dataread As ADODB.Recordset, obSQL As String
Dim cnn As ADODB.Connection
Dim Fin As Integer, i As Long, MiLibro As String, Tit As String
'Desactivamos actualización de pantalla
Application.ScreenUpdating = False
'Eliminamos datos de hoja INFORMACION anteriores
Sheets("INFORMACION").Select
With Sheets("INFORMACION")
'Eliminamos datos de la consulTa SQL anterior
Fin = Application.CountA(.Range("A:A"))
If Fin > 0 Then .Range("A2:D" & Fin).ClearContents
'Realizamos consulta SQL, y componemos un string para crear los datos y darle formato de fecha
obSQL = "SELECT [BASE$].[NOMBRE], [BASE$].[PETICION], [BASE$].[FIRMA], " & _
"IIF(NOT ISNULL([BASE$].[FECHA DE FIRMA]),CDATE(MID([BASE$].[FECHA DE FIRMA],1,2) & '/' & MID([BASE$].[FECHA DE FIRMA],3,2) & '/' & MID([BASE$].[FECHA DE FIRMA],5,4)),NULL) AS [FECHA DE FIRMA] " & _
"FROM [BASE$] "
MiLibro = ActiveWorkbook.Name
Set cnn = New ADODB.Connection
With cnn
.Provider = "Microsoft.Jet.OLEDB.4.0"
.ConnectionString = "DATA SOURCE=" & Application.ActiveWorkbook.Path + "\" & MiLibro
.Properties("Extended Properties") = "Excel 8.0"
.Open
End With
'Grabamos la consulta
Set Dataread = New ADODB.Recordset
With Dataread
.Source = obSQL
.ActiveConnection = cnn
.CursorLocation = adUseClient
.CursorType = adOpenForwardOnly
.LockType = adLockReadOnly
.Open
End With
'Pegamos datos y añadimos encabezados
Do Until Dataread.EOF
Dataread.MoveFirst
.Cells(2, 1).CopyFromRecordset Dataread
For i = 0 To Dataread.Fields.Count - 1
Tit = Dataread.Fields(i).Name
.Cells(1, i + 1) = Tit
Next
Loop
'Por seguridad formateamos la columna FECHA DE FIRMA a fecha
.Columns("D:D").NumberFormat = "m/d/yyyy"
'liberamos y desconectamos variables
Dataread.Close: Set Dataread = Nothing
cnn.Close: Set cnn = Nothing
End With
Application.ScreenUpdating = True
End Sub

Como podéis observar,  usamos ADO para importar la información de una hoja a la otra, y en el proceso aprovechamos para realizar los cambios y controles necesarios. En concreto, en esta sentencia SQL:

"IIF(NOT ISNULL([BASE$].[FECHA DE FIRMA]),CDATE(MID([BASE$].[FECHA DE FIRMA],1,2) & '/' & MID([BASE$].[FECHA DE FIRMA],3,2) & '/' & MID([BASE$].[FECHA DE FIRMA],5,4)),NULL) AS [FECHA DE FIRMA]

Donde controlamos que solo sean formateadas las celdas que contienen datos usando un IIF que valida si son nulas. Si no lo son, componemos una nueva cadena de texto creando la fecha y aplicamos la función CDate que nos devolverá una expresión tipo fecha, ¡Justo lo que queremos!.

Una vez ejecutada la macro, el resultado es el siguiente:

DAR FORMATO DE FECHA A UNA CADENA DE TEXTO USANDO ADO EN VBA1

Este es un ejemplo muy concreto donde los datos a formatear deben ser texto, de hecho, cuando no nos envían la información con formato de fecha, casi siempre viene así.

Antes de finalizar, os recuerdo la necesidad de marcar en las referencias la librería de ADO Activex Data Objects 2.8 Library, es importante que lo hagáis, de lo contrario, la macro no va a funcionar:

exportar-una-tabla-o-consulta-de-access-a-excel-con-ado2

Y eso es todo, espero que os resulte de utilidad a la hora de trabajar con fechas en Excel 🙂

Descarga el archivo de ejemplo pulsando en: APLICAR FORMATO DE FECHA A UNA CADENA DE TEXTO USANDO ADO EN VBA

 
¿Te ha resultado de interés?, puedes apoyar a Excel Signum con una pequeña donación.

Donate Button with Credit Cards

¡¡Muchas gracias!!

CALCULAR DÍAS, MESES Y AÑOS ENTRE DOS FECHAS Y DIFERENTES PERIODOS

Hola a todos!!

Hace unos días recibí una consulta sobre el cálculo de días, meses y años entre dos fechas, pero aplicado a varios periodos, es decir, el obtener los días, los meses y los años entre dos fechas es sencillo cuando aplicamos la función SIFECHA(), podéis profundizar un poco más en este post: CALCULAR AÑOS ENTRE DOS FECHAS EN EXCEL.

Es aplicar la función sifecha() para obtener los días, los meses y los años entre las dos fechas, y donde los elementos se relacionan entre sí, es decir, no son datos absolutos, sino que los meses van acumulando los días y los años van acumulando los meses, este sería un ejemplo:

calcular-dias-meses-y-anos-entre-dos-fechas-y-diferentes-periodos

Las fórmulas usadas para obtener este resultado con:

Años: =SIFECHA(A2;B2; "Y")
Meses: =SIFECHA(A2;B2; "YM")
Días:=SIFECHA(A2;B2; "MD")
Antigüedad General: =SIFECHA(A2;B2; "y")& " años  " & SIFECHA(A2;B2; "ym")& " meses  " &SIFECHA(A2;B2; "md")& " dias "

Hasta ahora esto es sencillo, pero ¿cómo hacemos para calcular el sumatorio de los años, los meses y los días? teniendo muy en cuenta que no podemos sumar simplemente, dado que los días no pueden ser más que los días que tiene un mes.

Lo que estamos buscando sería esto (siguiendo nuestro ejemplo):

calcular-dias-meses-y-anos-entre-dos-fechas-y-diferentes-periodos2

Como podéis observar, el resultado no es la simple suma de conceptos por columna, sino que existe una relación entre días, meses y años, de forma que los días sobrantes se van trasladando a los meses y los meses sobrantes se van trasladando a los años (en este la suma de los periodos no llegan a un año).

Para conseguir este resultado vamos a introducir la siguiente fórmula:

Para los días:
=SI(SUMA($E$2:E5)>30,5;SUMA($E$2:E5)-(ENTERO(SUMA($E$2:E5)/30,5)) *(30,5);SUMA($E$2:E5))

Para los meses:
=SI(SUMA($D$2:D5)+((SUMA($E$2:E5)-E6)/30,5)>11;((SUMA($D$2:D5)+((SUMA($E$2:E5)-E6)/30,5))-(ENTERO((SUMA($D$2:D5)+((SUMA($E$2:E5)-E6)/30,5))/12))*12);SUMA($D$2:D5)+((SUMA($E$2:E5)-E6)/30,5))

Para los años:
=SUMA($C$2:C5) +ENTERO((SUMA($D$2:D5) +((SUMA($E$2:E5)-E6)/12)-D6)/12)

Esta fórmula es bastante conocida en manuales, foros, etc… y me ha parecido interesante dejarla en la web. He realizado algún ajuste que creía interesante para reducir el contenido de la fórmula.

Descarga el archivo pulsando en: CALCULAR DÍAS, MESES Y AÑOS ENTRE DOS FECHAS Y DIFERENTES PERIODOS