El código VBA de ManejandoMondo

endomondo
Etiquetas:

Segunda entrada sobre ManejandoMondo y su código VBA: el fichero Excel que puedes tener gratis para el seguimiento de tu actividad deportiva.

La aplicación ManejandoMondo puedes conseguirla solicitándola a manejandodatos@gmail.com, y si te mola, incluso puedes colaborar con tu donación.

Aunque ya hace mucho tiempo, allá por 2013, escribí sobre el lenguaje VBA y su supervivencia, en 2021 aún sigue vigente. Yo no es un lenguaje que utilice demasiado, porque suelo desarrollar más con Javascript y Vue, o Python.

Por motivos laborales, también desarrollo en ASP Clásico en el lado del back-end, aunque cada vez menos.

VBA aún perdurará

Parecía que VBA estaba destinado a morir hace ya varios años, pero aún sigue bastante vigente. Yo no creo que sea un lastre de lenguaje, pero sí es cierto que mientras que Python o Javascript, o incluso C# de la propia Microsoft, entre otros, han evolucionado, VBA se ha quedado estancado, y tiene pinta de que no evolucionará más (de hecho, yo creo que lleva años sin evolución).

Es una pena porque este lenguaje podía ser mucho más potente de lo que es, si se reforzara con varias “cositas”. En mi opinión, yo hubiera mejorado el tema de diccionarios (de Python o algo similar a JSON en Javascript), también habría facilitado sintaxis abreviada (cómo los a = 1 if condicion else 2 de Python).

VBA de ManejandoMondo para llamar al formulario

Para llamar al formulario es necesario hacerlo desde una función de un módulo, con un código muy simple, tal que así:

Public Const APP = "ManejandoMondo"
Public Const TRACK = "track"
Public Const sSTART = "start"

Public Sub START()
Dim f As New frmTrack
f.Caption = APP & VERSION
f.txtPF.Text = 122
f.Show
End Sub

El formulario frmTrack

Cuando se inicializa el formulario, se realizan varias operaciones. La función PonFecha, se describe más adelante, es la que localiza la última fila de la solapa track para buscar la última fecha de la que hay datos. Además, se localizan los valores únicos de las distintas Actividades, para insertarlas en el ListBox.

Private Sub UserForm_Initialize()
Dim uFecha As String, f As Date, unicos As Variant, i As Integer
Me.lblTit.Caption = APP & VERSION
Sheets(TRACK).Select
PonFecha
        unicos = WorksheetFunction.Unique(Range("B2:B" & ufila))
        'Obtenemos los datos de la matriz y los pasamos a la hoja
        For i = LBound(unicos) To UBound(unicos)
            If Len(unicos(i, 1)) Then Me.lstTipo.AddItem unicos(i, 1)
        Next i
End Sub

La función PonFecha:

Esta función es la que se encarga de trabajar con la fecha. Si se marca la casilla de inserción, se selecciona la de la casilla correspondiente, pero si está desmarcada, se trabaja sobre la última actividad. Se verifica también que siempre haya alguna fecha disponible:

Private Sub PonFecha()
Dim uFecha As String, f As Date
Dim i As Integer
If Me.chkPF.Value Then
    i = Me.txtPF.Text
Vuelve:
    uFecha = Range("A" & i).Value
    If Len(uFecha) = 0 Then
mierror:
        i = i - 1
        If i < 3 Then GoTo Ending Else GoTo Vuelve
    End If
    On Error GoTo mierror
    f = CDate(uFecha)
    On Error Resume Next
Else
    ufila = ActiveSheet.UsedRange.SpecialCells(xlCellTypeLastCell).Row
LeeFecha:
    uFecha = Range("A" & ufila).Value
    If Len(uFecha) = 0 Then
        ufila = ufila - 1
        GoTo LeeFecha
    End If
    f = CDate(uFecha)
    f = DateAdd("d", 1, f)
End If
Me.txtFecha.Text = Str(f)
Ending:
End Sub

Para evitar tener que cambiar la fecha al día siguiente o anterior, se han creado dos botones para ello, con 3 funciones asociadas:

Private Sub ModFecha(v As Integer)
Dim uFecha As String, f As Date
f = CDate(Me.txtFecha.Text)
f = DateAdd("d", v, f)
Me.txtFecha.Text = f
End Sub

Private Sub cmdMas_Click()
ModFecha 1
End Sub

Private Sub cmdMenos_Click()
ModFecha -1
End Sub

Una función es la que ejecuta la modificación de la fecha, mientras que las otras envían si se quiere un día antes o un día después. Es simple, pero efectivo, reduciendo lo que el usuario tiene que escribir.

Para reducir también lo que el usuario debe escribir y que todos los datos numéricos sean insertables desde teclado numérico, y disponer de formatos adecuados de horas y ritmos, se crean dos funciones para modificar los . por lo que corresponda.

Private Function AjustaHora(s As String) As String
Dim i As Integer
s = Replace(s, ".", ":")
i = InStr(1, s, ":")
If i Then i = InStr(i + 1, s, ":")
If i = 0 Then s = "0:" & s
AjustaHora = s
End Function

Private Function AjustaRitmo(s As String) As String
AjustaRitmo = Replace(s, ".", ":")
End Function

Se incluye también otra función para limpiar el formulario, cuando se introducen más de una actividad:

Private Sub ResetForm()
Me.txtDist.Text = ""
Me.txtTiempo.Text = ""
Me.txtCal.Text = ""
Me.txtRitmo.Text = ""
Me.txtAsc.Text = ""
Me.txtDes.Text = ""
Me.txtFC.Text = ""
Me.txtFCMx.Text = ""
Me.txtObs.Text = ""
End Sub

Y por último, la función que pasa los datos desde el formulario a la solapa Track:

Private Sub cmdInsert_Click()
If Len(Me.lstTipo.Text) = 0 Then
    MsgBox "Actividad SIN seleccionar!", vbCritical, APP & VERSION
    Exit Sub
End If
    Dim sDate() As String, v As Variant
    Dim Y As Long, M As Long, D As Long, f As String
    
    If Me.chkPF.Value Then
        ufila = Me.txtPF.Text
        Rows(ufila & ":" & ufila).Select
        Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
        Me.txtPF.Text = ufila + 1
        ufila = ufila - 1
    End If

f = Me.txtFecha.Text: sDate = Split(f, "/")
    Y = sDate(2): M = sDate(1): D = sDate(0)
    f = Format(DateSerial(Y, M, D), "yyyy-mm-dd")
Range("A" & ufila + 1).Value = f ' Fecha
Range("B" & ufila + 1).Value = Me.lstTipo.Text  ' Tipo
Range("C" & ufila + 1).Value = Me.txtDist.Text  ' Distancia
Range("D" & ufila + 1).Value = AjustaHora(Me.txtTiempo.Text)  ' Tiempo
Range("E" & ufila + 1).Value = Me.txtCal.Text  ' Calorias

Range("F" & ufila + 1).Value = AjustaRitmo(Me.txtRitmo.Text)  ' Ritmo Mx
Range("G" & ufila + 1).Value = Me.txtAsc.Text  ' Asc
Range("H" & ufila + 1).Value = Me.txtDes.Text  ' Desc
Range("I" & ufila + 1).Value = Me.txtFC.Text  ' FC Media
Range("J" & ufila + 1).Value = Me.txtFCMx.Text  ' FC Mx

Range("K" & ufila + 1).Value = Me.txtObs.Text  ' Obs
Range("L" & ufila & ":O" & ufila).Select
    Selection.AutoFill Destination:=Range("L" & ufila & ":O" & ufila + 1), Type:=xlFillDefault
If Me.chkPF.Value Then
    ResetForm
    cmdMas_Click
Else
    Dim vv As VbMsgBoxResult
    vv = MsgBox("Incluir datos a Proyección de objetivos?", vbYesNo, APP)
    If vv = vbYes Then
        ToProyeccion
    End If
    Me.Hide
End If
ActiveWorkbook.Save
End Sub

Se verifica que se ha marcado un Tipo de Actividad, y tras insertar la fila en la solapa, se incorporan los datos del formulario, y se aplica para autocompletar varias columnas calculadas (de la L a la O).

Por último, si se está insertando actividades previas, se limpia y se reinicia todo, pero si es la última actividad, se guarda la actividad y también la hola, para evitar perder datos.

En la versión 0.4.0 se ha incluido una nueva solapa de Proyección, que permite guardar nueva información sobre proyecciones de tus estadísticas para el cierre del año.

Futuras versiones de ManejandoMondo

De momento, las actualizaciones de la hoja de Excel se han centrado en mejorar las estadísticas, y nuevas gráficas. Hay pocas novedades en el código VBA de ManejandoMondo en la actualización 0.4.0, centrada en la proyerción de objetivos, a la fecha con respecto a lo que se espera a 31 de diciembre de cada año. Para ello, se definen unos objetivos y se permite ir comprobando si durante el desenlace del año, lo vas alcanzando, y cómo va esa progresión.

ManejandoMondo 0.4.0

Y esto es todo.