'Calendario continuado en Excel by htorres - Mikel ERP
'November 25, 2019
'Maracaibo , Venezuela
Option Explicit
Private finBucle As Integer 'para detener el bucle cuando termine de dibujar los dias
'Nota: variables iniciadas con 'p' significan parametros (pBaseYear, pLastWeek, etc.)
Sub SetCalContHernan()
Const rStartDate As String = "C5"
Const Color1 As Long = 13434879
Const Color2 As Long = 16382457
Const Color3 As Long = 14869218
Const rDiasSem As Integer = 7 'se conoce pero para controlar los parametros la dejo aqui
'Const pBaseYear As Integer = 2018 'el año base, puede cambiarlo a tu gusto, solo le di un uso pero ahora puedes descartarla
Dim i As Integer, fillColor As Long
Dim d As Integer
Dim l As Integer 'para mi esto representa la cantidad de filas en las que deseas tener tu calendario
Dim oStartDate As Range
Dim rSemanas As Integer 'Columnas de semana
Dim pStartWeek As Integer
Dim pCalendarWidth As Integer
Dim wColumnas As Integer
Dim pLastDay As Integer
Dim pColumna As Integer
Dim inicioCalendario As Integer 'la posicion inicial del calendario
Dim letraColumna As String 'solo para efeectos de prueba
Dim evaluatedYear As Integer
Dim myFlag As Integer
Dim daysWritten As Integer
Application.ScreenUpdating = False 'esto debe ir al principio, despues de la declaracion de las variables
rSemanas = Range("rQtySemanas") 'puedes dirigir esto hacia una celda
pStartWeek = 2 'puedes asignar esto a una celda. Asigno 2 para que inicie en Lunes
If IsDate(Range(rStartDate)) Then
Set oStartDate = Range(rStartDate) 'tengo que revisar el formato de esta fecha
evaluatedYear = makeCalendar(rSemanas, Year(oStartDate), bisiesto(Year(oStartDate)))
Else
MsgBox "Invalid Start Date"
Exit Sub
End If
Range("semanas").Select
With Selection
.ClearContents
.Interior.Pattern = xlNone
End With
'pColumna la necesito para saber cuantas filas me va a tomar el calendario
pColumna = Val(Replace(ThisWorkbook.Names.Item("firstDayInCalendar"), "=", ""))
'Esta sentencia deberia ser para colocar los encabezados de las columnas
'---CREANDO LOS ENCABEZADOS---
Range(oStartDate.Address).Offset(1, 1).Activate 'tomar una posicion para construir el calendario
'ActiveCell.Offset(1, 1).Activate
pCalendarWidth = (rDiasSem * rSemanas) - 1
For i = 0 To pCalendarWidth
'si deseas que tu calendario inicie con el dia de semana correspondiente
'puedes extender la idea que viene en la siguiente linea de codigo
'ActiveCell.Offset(0, i) = StrConv(Left(Format(Weekday(oStartDate + i, 2), "ddd"), 1), 1)
ActiveCell.Offset(0, i) = StrConv(Left(Format(Weekday(oStartDate - Weekday(oStartDate, 2) + i + 2, 2), "ddd"), 1), 1)
Next i
'---ESCRIBIR UN CALENDARIO CON SEIS SEMANAS ANTES DE CADA SALTO---
'calcular las lineas ncesarias para completar
'el calendario hasta el 31-dic de cada año
'considerando las semanas requeridas
l = 0 'esta modificacion que propones, finalmente me da la posibilidad de nombrar esto a lineas (variable "l")
While pLastDay < finBucle
'---ESCRIBIR LOS DIAS---
l = l + 1
Select Case l
Case 1 'si estamos en la primera semana del rango
inicioCalendario = Range(oStartDate.Address).Column
Range(oStartDate.Address).Offset(2, pColumna - inicioCalendario).Activate 'cambie esto para colocar lo que me pediste (iniciar en la columna siguiente a donde finalizo el año anterior)
wColumnas = pCalendarWidth - (pColumna - 1) + inicioCalendario
For d = 0 To wColumnas
If Day(oStartDate + d) = 1 Then
'MsgBox "estoy en dia 1"
ActiveCell.Offset(0, d) = oStartDate + d
ActiveCell.Offset(0, d).NumberFormat = "m/d"
ActiveCell.Offset(0, d).Interior.Color = Color1
ActiveCell.Offset(0, d).Font.Bold = True
ActiveCell.Offset(0, d).Font.Name = "Arial"
ActiveCell.Offset(0, d).Font.Size = 8
ActiveCell.Offset(0, d).HorizontalAlignment = xlCenter
ActiveCell.Offset(0, d).VerticalAlignment = xlCenter
Else
ActiveCell.Offset(0, d) = oStartDate + d
ActiveCell.Offset(0, d).NumberFormat = "d"
ActiveCell.Offset(0, d).Interior.Color = Color2
ActiveCell.Offset(0, d).Font.Bold = False
ActiveCell.Offset(0, d).Font.Name = "Arial"
ActiveCell.Offset(0, d).Font.Size = 8
ActiveCell.Offset(0, d).HorizontalAlignment = xlCenter
ActiveCell.Offset(0, d).VerticalAlignment = xlCenter
End If
'por si un dia se te ocurre pintar los feriados
If ((Weekday(oStartDate + d, 2) = 6 Or Weekday(oStartDate + d, 2) = 7) And Day(oStartDate + d) <> 1) Then
'MsgBox "estoy en fin de semana"
ActiveCell.Offset(0, d).Interior.Color = Color3
ActiveCell.Offset(0, d).Font.Color = vbRed
ActiveCell.Offset(0, d).Font.Bold = True
End If
' si quieres pintar los meses
' If Month(oStartDate + d) Mod 2 Then
' ActiveCell.Offset(0, d).Interior.Color = Color1
' Else
' ActiveCell.Offset(0, d).Interior.Color = Color2
' End If
Next d
Case Else
Range(oStartDate.Address).Offset(2 + l - 1, 1).Activate 'no te confundas, la operacion es: 2 + L minuscula - 1
For d = 0 To pCalendarWidth
If Day(oStartDate + pLastDay) = 1 Then
ActiveCell.Offset(0, d) = oStartDate + pLastDay
ActiveCell.Offset(0, d).NumberFormat = "m/d"
ActiveCell.Offset(0, d).Interior.Color = Color1
ActiveCell.Offset(0, d).Font.Bold = True
ActiveCell.Offset(0, d).Font.Name = "Arial"
ActiveCell.Offset(0, d).Font.Size = 8
ActiveCell.Offset(0, d).HorizontalAlignment = xlCenter
ActiveCell.Offset(0, d).VerticalAlignment = xlCenter
Else
ActiveCell.Offset(0, d) = oStartDate + pLastDay
ActiveCell.Offset(0, d).NumberFormat = "d"
ActiveCell.Offset(0, d).Interior.Color = Color2
ActiveCell.Offset(0, d).Font.Bold = False
ActiveCell.Offset(0, d).Font.Name = "Arial"
ActiveCell.Offset(0, d).Font.Size = 8
ActiveCell.Offset(0, d).HorizontalAlignment = xlCenter
ActiveCell.Offset(0, d).VerticalAlignment = xlCenter
End If
'por si un dia se te ocurre pintar los feriados
If ((Weekday(oStartDate + pLastDay, 2) = 6 Or Weekday(oStartDate + pLastDay, 2) = 7) And Day(oStartDate + pLastDay) <> 1) Then
'MsgBox "estoy en fin de semana"
ActiveCell.Offset(0, d).Interior.Color = Color3
ActiveCell.Offset(0, d).Font.Color = vbRed
ActiveCell.Offset(0, d).Font.Bold = True
End If
' si quieres pintar los meses
' If Month(oStartDate + pLastDay) Mod 2 Then
' ActiveCell.Offset(0, d).Interior.Color = Color1
' Else
' ActiveCell.Offset(0, d).Interior.Color = Color2
' End If
pLastDay = pLastDay + 1
Next d
End Select
Select Case l
Case 1
pLastDay = d
daysWritten = wColumnas + 1
'Debug.Print daysWritten
Case Else
pLastDay = pLastDay
daysWritten = daysWritten + (pCalendarWidth + 1)
'Debug.Print daysWritten
If myFlag = 1 Then GoTo finalizar
If pCalendarWidth >= (finBucle - daysWritten) Then
'bajo la bandera
myFlag = 1
'reescribo pCalendarWidth
pCalendarWidth = finBucle - daysWritten - 1
'tomar la ultima posicion del año, para poder pasarla como inicial en el siguiente calendario
ActiveWorkbook.Names.Add "firstDayInCalendar", , , , , , , , , ActiveCell.Offset(0, pCalendarWidth + 1).Column
'letraColumna = Split(Cells(1, columna).Address, "$")(1) 'solo para validar
End If
End Select
Wend
finalizar:
Range("C15").Activate
Application.ScreenUpdating = True 'debemos devolver el estado a True
MsgBox "Calendario creado!!!", vbInformation, "Mikel ERP by htorres"
End Sub
Public Function bisiesto(anio As Integer)
Dim mesFeb As Date
Dim mesEvaluado As Integer
mesFeb = DateValue(Format("03/01/" & anio, "mm/dd/yyyy"))
mesEvaluado = Day(Application.EoMonth(mesFeb, -1))
If mesEvaluado = 28 Then
bisiesto = 365
finBucle = bisiesto
Else
bisiesto = 366
finBucle = bisiesto
End If
End Function
Public Function makeCalendar(semanas As Integer, anio As Integer, tipoAnio As Integer) As Integer
'para crear mas funcionalidad
Select Case semanas
Case 4
MsgBox "Creando calendario de 4 semanas", vbInformation, "Mikel ERP by htorres"
Case 6
MsgBox "Creando calendario de 6 semanas", vbInformation, "Mikel ERP by htorres"
Case Else '8 semanas
MsgBox "Creando calendario de 8 semanas" & Chr(10) & _
"para el año " & anio, vbInformation, "Mikel ERP by htorres"
End Select
End Function