Introducir datos utilizando un formulario

Una de las formas más vistosas para introducir datos en una hoja de cálculo, es utilizando un formulario. Cuando usamos esta técnica, a través del uso de un UserForm, le pedimos al usuario que introduzca una serie de datos, y una vez cumplimentado todo, se graban en la hoja de cálculo, en la línea que le corresponda. Si la primera celda vacía es la B14, pues será en esa celda donde empezaremos a escribir. Si la primera celda vacía es la J4, pues será esa la celda elegida.

De la misma forma que digo que es una forma vistosa de introducir datos, también he de decir que es una de las formas menos útiles de introducir datos en una hoja de cálculo, pues es mucho más rápido hacerlo directamente sobre la celda donde queremos escribir, que sobre un formulario. Eso sí, si los datos a introducir son pocos, puede sernos de cierta utilidad.

Vamos a ver como funciona la entrada de datos en una hoja de cálculo, a través de un formulario, utilizando un sencillo ejemplo para llevar un control de compras. Solicitaremos el nombre del producto, la cantidad, y el precio unitario. El sistema nos calculará el total, y grabaremos todos los datos en la primera fila vacía.


Una vez hecho el formulario con sus correspondientes Label y TextBox, así como los dos botones, nos bastará con introducir el código VBA. Para ello, lo primero que haremos será proteger la hoja, al arrancar el libro, utilizando el macro Auto_open():


Sub Auto_open()
'Protegemos la hoja
ActiveSheet.Protect
End Sub

Este otro sencillo macro nos lanzará el formulario:

Sub introducir_datos()
'llamamos al formulario
UserForm1.Show
End Sub

Ahora dentro del UserForm (recordemos que los dos macros anteriores deben estar en un módulo VBA), introduciremos estos otros procedimientos. El primero de ellos evalúa si estamos cambiando el TextBox3, para calcular el total, siempre y cuando el TextBox2 y el TextBox3 sean datos numéricos:

Private Sub TextBox3_Change()
'si hay errores, que continúe
On Error Resume Next
'Cuando cambiemos el TextBox3 (precio unitario)
'miraremos si hay datos también en el TextBox2 (cantidad)
'para multiplicar ambos datos, siempre que sean números

If TextBox2 <> "" And IsNumeric(TextBox2) And _
TextBox3 <> "" And IsNumeric(TextBox3) Then
TextBox4 = TextBox2 * TextBox3
End If
End Sub

Este otro, será el código del botón que tiene por rótulo el texto "Grabar datos" (el CommandButton1:

Private Sub CommandButton1_Click()
'Desprotegemos la hoja
ActiveSheet.Unprotect
'Nos situamos al principio
Range("B4").Select
'Bajamos hasta encontrar la fila vacía
Do While Not IsEmpty(ActiveCell)
'Bajamos una fila
ActiveCell.Offset(1, 0).Select
Loop
'grabamos los datos en la primera fila vacía
'primero el nombre del producto

ActiveCell = TextBox1
'ahora la cantidad
ActiveCell.Offset(0, 1) = CDbl(TextBox2)
'ahora el precio unitario
ActiveCell.Offset(0, 2) = CDbl(TextBox3)
'ahora el total
ActiveCell.Offset(0, 3) = CDbl(TextBox4)
'limpiamos los textbox
TextBox1 = ""
TextBox2 = ""
TextBox3 = ""
TextBox4 = ""
'ponemos el focus en el TextBox1
TextBox1.SetFocus
'protegemos la hoja
ActiveSheet.Protect
End Sub

Y este es el código del botón que borra el contenido de los TextBox:

Private Sub CommandButton2_Click()
'borramos los datos
TextBox1 = ""
TextBox2 = ""
TextBox3 = ""
TextBox4 = ""
End Sub



Desde aquí podéis descargar el fichero, con el ejemplo que hemos visto en este artículo.


Calendarios para imprimir

Suele ser habitual que cuando finaliza un año, mucha gente empieza a planificar sus proyectos para el año siguiente: dejar de fumar, apuntarse al gimnasio, hacer dieta, viajar fuera del país, etc. Seguramente, muchos de los afortunados que tenemos empleo, lo primero que hacemos es buscar un calendario para mirar en qué días cae la Semana Santa, miramos también las vacaciones de verano, los días de Navidad, fin de año, y algún que otro puente, porque lo que más deseamos es disfrutar esos días, desconectando alejados de la fábrica o de la oficina.

Lo normal es que no dispongamos de un calendario del año que viene, hasta unos pocos días antes de la llegada del nuevo año, bien porque nos manda una agenda un proveedor, bien porque nos regala un calendario de pared una entidad financiera, o bien porque nos lo manda una empresa que no conocemos y que quiere vendernos algún producto o servicio.

Pues bien, hoy vamos a ver como podemos generar nuestros propios calendarios, para imprimirlos y tenerlos siempre a mano, para cuando los necesitemos. Para ello utilizaremos Excel, esa potente herramienta que nos permite tratar no solo datos numéricos, o de texto, sino también fechas y unidades de tiempo. Excel tiene una limitación en cuanto al tratamiento de fechas, que hace que solo podamos operar con ellas, si están comprendidas entre el 01-01-1900 y el 31-12-9999. En el caso de utilizar Excel en su versión para un ordenador Macintosh, el rango de fechas permitidas, pasa a ser desde el 01-01-1904, hasta el 31-12-9999.

Nosotros vamos a generar un calendario para imprimir que cubra el rango desde el año 1920 hasta el 2100. ¿Parece suficiente, verdad?. Pues bueno, si todavía quieres más años, simplemente cambiando una línea del código fuente, podrás alterar ese rango, por si deseas acomodarlo adaptándolo completamente las posibilidades de Excel (si usas una versión para PC, desde el año 1900 al 9999, y si utilizas Excel para Mac, desde el año 1904 al 9999).

Lo primero que haremos será crear los 12 cuadros, cada uno para cada mes. Cada cuadro estará formado por una celda combinada, donde incluiremos el nombre del mes, y 49 celdas de 7x7, para los días de la semana.


Lo que haremos, será solicitar vía un InputBox, el año para el cual queremos crear el calendario. Una vez introducido, se nos generarán los días de cada mes, colocándose donde les corresponde. Si el día 1 de enero cae en martes, pues aparecerá él martes, y si cae en viernes, pues aparecerá en viernes. Para hacer todo esto, utilizaremos exclusivamente funciones de Excel. Concretamente, para el nombre del mes, tomaremos como referencia el año, que está en la celda K2. En el caso concreto del mes de enero, por ejemplo, la función será esta:


=FECHA($K$2;1;1)

Para la primera fila, y en el caso del mes de enero, bajo el rótulo lunes pondremos esta fórmula:

=SI(ELEGIR(DIASEM(B5);"Do";"Lu";"Ma";"Mi";"Ju";"Vi";"Sa")=B6;1;"")

Para el resto de días de la semana, pondremos un condicional. En el caso del martes, utilizaremos por ejemplo, esta:

=SI(B7="";SI(ELEGIR(DIASEM($B$5);"Do";"Lu";"Ma";"Mi";"Ju";"Vi";"Sa")=C6;1;"");B7+1)

En la segunda fila, bajo el lunes, y en el caso de estar trabajando con el mes de enero, pondremos esta fórmula:

=SI(H7<>"";SI(H7+1>DIA(FIN.MES($B$5;0));"";H7+1);"")

Para el resto de días de la semana, haremos algo parecido, cambiando en la fórmula anterior, la celda H7, por la celda inmediatamente anterior al día de la semana con el que estemos trabajando.

El modelo, como veis, no tiene mucha complicación, Tan solo hay que utilizar la fórmula ELEGIR, para saber junto con DIASEM, el día de la semana, y compararlo con los datos que aparecen arriba y que contienen el día de la semana (Lu, Ma, Mi, etc.), aunque podéis utilizar otras fórmulas, para obtener esos mismos resultados. También utilizaremos la función FIN.MES, para saber cual es el último día del mes, y que no siga rellenando el calendario más allá del día 30 o 31 (en el caso de febrero, del 28 o 29, según proceda).

Si la función FIN.MES os devuelve el error #¿NOMBRE?, hay que tener habilitadas las herramientas para análisis. Eso es tan sencillo como marcar la opción Herramientas para análisis, desde el menú Herramientas, y seleccionando a continuación Complementos...

Por otra parte, me comentan, que al abrir el fichero desde una versión de Excel en inglés, la función FIN.MES no la traduce de forma automática. En ese caso hay que hacer un reemplazo (desde Edición, seleccionando la opción Reemplazar), y sustituir FIN.MES por EOMONTH.

Como parece que estar leyendo todo esto, puede parecer un poco lioso, si no tenemos delante el fichero de Excel, lo mejor es que lo descarguéis, y lo probéis. Al final de este artículo, hay un enlace para descargarlo.

Los macros que utilizaremos, son realmente sencillos. El primero será este, que hará que se proteja la hoja, para que nadie cambie ni borre nada. La protección no tiene ningún password:

Sub Auto_open()
'Al abrir el libro,
'protegemos la hoja (sin ningún password)

ActiveSheet.Protect
End Sub

El segundo macro es para imprimir el calendario, definiendo el área a imprimir, ajustado a las dimensiones de 1 página de alto y 1 de ancho, y encajándolo todo, horizontal y verticalmente:

Sub imprimir_calendario()
'Seleccionamos el área para imprimir
ActiveSheet.PageSetup.PrintArea = "$A$1:$Y$40"
'definimos las preferencias de impresión
With ActiveSheet.PageSetup
'Centramos la impresión
.CenterHorizontally = True
.CenterVertically = True
'Ajustamos la impresión a 1 página
'tanto de alto como de ancho

.Zoom = False
.FitToPagesWide = 1
.FitToPagesTall = 1
End With
'Imprimimos el calendario
ActiveWindow.SelectedSheets.PrintOut Copies:=1
End Sub

Este último macro, es para el año. Pondremos el texto en un tamaño de fuente de 18 pixels, lo centraremos en un rango de celdas, y le añadiremos delante el texto "Año", entre otras cosas:

Sub anio()
'Ocultamos el procedimiento
Application.ScreenUpdating = False
'Desprotegemos la hoja
ActiveSheet.Unprotect
'fichamos la celda donde estamos
celda = ActiveCell.Address
'Presentamos un inputbox para preguntar el año
respuesta = InputBox("Introduce el año:", "Año")
'Si el año está entre 1950 y 2100, lo escribimos
'en la celda K2, en caso contrario, mostramos un mensaje

If Not IsNumeric(respuesta) Or respuesta < 1920 Or respuesta > 2100 Then
'mostramos un mensaje
MsgBox ("No es un año válido. Debe estar entre 1920 y 2100")
Exit Sub
Else
'si el año es válido, lo escribimos en la celda K2
Range("K2").Select
ActiveCell = respuesta
Selection.NumberFormat = """Año"" ###0"
'ponemos el año en grande, y lo centramos
With Selection.Font
.Size = 18
End With
Range("K2:O2").Select
With Selection
.HorizontalAlignment = xlCenter
End With
Selection.Merge
End If
'volvemos donde estábamos
Range(celda).Select
'protegemos la hoja
ActiveSheet.Protect
'Mostramos el procedimiento
Application.ScreenUpdating = True
End Sub

Por cierto, a este último macro, le he puesto por nombre “anio” en lugar de “año”, por si algún usuario no tiene en su teclado la letra ñ, o por si usa una versión inglesa de Excel, y para evitar posibles problemas al convertir las funciones y los procedimientos.

Aquí podéis ver un pantallazo de cómo nos quedaría el calendario, una vez elegido el año. Evidentemente esto no será lo que saldrá por la impresora cuando imprimamos el calendario, pues se trata de un pantallaza para ilustrar este artículo, y aquí salen visibles los botones para los macros:


Para los más curiosos, en el calendario se utiliza también el formato condicional, con el fin de poner de color amarillo suave, aquellas celdas que no contienen ningún día, y diferenciarlas así, de aquellas que tienen un número. Si nos situamos en cualquier celda, y vamos a la opción de menú Formato, y a continuación a Formato condicional…, veremos esto (aunque no se pueda apreciar muy bien, aparece en color amarillo pálido, el fondo de la celda):


Si preferís utilizar calendarios con más decoración, con imágenes, y que no estén hechos en Excel, sino con otras aplicaciones, podéis pasaros por algunos sitios de la red. Entre otros, podéis visitar por ejemplo, este blog que contiene abundante información sobre cómo obtener calendarios para imprimir, o esta web donde también hay bonitos y decorativos calendarios para imprimir, aunque posiblemente este último sitio esté dirigido más a un público infantil, al que seguramente Excel todavía les suena a chino :-)

Desde aquí podéis descargar el fichero, con el ejemplo que hemos visto en este artículo.


Enviar un email desde Excel

Hace ya un tiempo, en forosdelweb.com, un usuario preguntaba si era posible enviar un email desde nuestra aplicación Excel. Otro usuario le contestaba que sí, que se podía hacer, y le remitía a una página web en inglés, donde se explicaba paso a paso, como llevar a cabo esta operación.

Como hace solo unos pocos días, otro usuario volvió a preguntar sobre el tema en ese mismo foro, se me despertó la curiosidad, y me puse a mirar aquella web en inglés, y a la que en su día no le había prestado mucha atención. La web en cuestión era esta: http://www.rondebruin.nl/sendmail.htm.

Allí hay abundante información sobre como enviar un email desde Excel (la documentación está en inglés), y hay ejemplos de cómo adjunta un archivo, como mandar una copia del email a otro usuario, etc. Yo me limitaré a hacer lo más sencillo, que no es otra cosa que enviar un email de texto, haciendo algunas adaptaciones muy sencillas al código original, para facilitar la entrada de datos por parte del usuario. Solo necesitaremos estos 6 datos:

  • La cuenta de correo desde la que vamos a mandar nuestro email: Este dato lo informaremos directamente en el código fuente del macro.

  • El password de nuestra cuenta de correo: Este dato lo informaremos directamente en el código fuente del macro.

  • El nombre y cuenta de correo, para el "reply": Este dato lo informaremos directamente en el código fuente del macro.

  • La cuenta de correo del destinatario: Este dato lo informaremos a través de un UserForm.

  • El asunto del email: Este dato lo informaremos a través de un UserForm.

  • El cuerpo del mensaje (el mensaje en sí): Este dato lo informaremos a través de un UserForm.

Como veis, hay 3 datos que siempre serán fijos, y son nuestra cuenta de correo, el password, y el nombre más el email (esto va junto, así que lo consideraremos como un solo dato), por si contesta o hace un "reply" el usuario. Los otros 3 datos que son variables, los introduciremos a través de un UserForm, es decir, informaremos del email del destinatario, el asunto del email, y

Vamos a enviar un email utilizando el servicio de correo electrónico de Google, es decir, el servicio de su aplicación Gmail. Podemos utilizar una cuenta de Yahoo, Hotmail, o cualquier otra, pero el correo de Gmail, es en mi opinión el mejor de todos. Si utilizáis otro servicio de correo, habrá que cambiar el servidor de correo saliente smtp, cambiando en el código fuente, la línea correspondiente (el código que veréis en este ejemplo, está debidamente comentado).

Lo primero que haremos será crear un macro desde el que llamaremos al UserForm. Tan sencillo, como hacer esto:

Sub Enviar_email()
'llamamos al userform1
UserForm1.Show
End Sub

El UserForm constará de 4 etiquetas de texto o Label (Label1, Label2, Label3, y Label4), 3 cuadros de texto o TextBox (TextBox1, TextBox2, TextBox3), y un botón de comando o CommandButton, tal y como podéis ver en la siguiente imagen:


Cuando diseñéis el UserForm, al situaros encima del TextBox3, que es el del cuerpo del mensaje, fijaos que en las propiedades (ventana de la izquierda), habéis cambiado EnterKeyBehavior a true, y MultiLine también a true, para que cuando usemos la tecla intro en el cuerpo del mensaje, bajemos a la línea siguiente, y para que cuando escribamos un email largo, automáticamente salte de línea al llegar al final por la derecha. Debéis cambiarlo, para que quede como en la siguiente imagen (ver lo marcado en color rojo atenuado):


El botón de comando (ese que pone "Enviar el email"), tendrá este código:

Private Sub CommandButton1_Click()
'Si hay errores, que continúe
On Error Resume Next
'Creamos el Message y Configuration, para
'enviar emails a través del objeto CDO de Windows

Set oMsg = CreateObject("CDO.Message")
Set oConf = CreateObject("CDO.Configuration")
'Cargamos los valores por defecto
oConf.Load -1
'Configuramos el objeto CDO, con los datos
'de nuestra cuenta de correo

Set Flds = oConf.Fields
With Flds
.Item("http://schemas.microsoft.com/cdo/configuration/smtpusessl") = True
.Item("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 1
'ponemos nuestra cuenta de correo de GMAIL
.Item("http://schemas.microsoft.com/cdo/configuration/sendusername") = "mi_email@gmail.com"
'ponemos nuestro password de GMAIL
.Item("http://schemas.microsoft.com/cdo/configuration/sendpassword") = "mi_password"
'este es el smtp de GMAIL. Si usamos Hotmail, yahoo, o cualquier otro
'servicio de correo, deberemos configurar el smtp, y evidentemente
'también el nombre de usuario y el password para esa cuenta

.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "smtp.gmail.com"
.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 465
.Update
End With
'recogemos el mensaje del TextBox3 del Userform
mensaje = TextBox3
With oMsg
Set .Configuration = oConf
'ponemos el nombre y correo para el reply
.From = """mi_nombre"" <mi_email@gmail.com>"
'recogemos el resto de datos del Userform,
'es decir, el destinatario y el asunto del mensaje

.To = TextBox1
.Subject = TextBox2
.TextBody = mensaje
.Send
End With
'Mostramos un mensaje, tanto si hay
'errores como si no los hay

If Err <> 0 Then
MsgBox ("Se ha producido un error, y no se ha podido enviar el email.")
Else
MsgBox ("El email se ha enviado correctamente.")
End If
End Sub

Cuando tengáis todo listo, tan solo deberéis llamar al macro Enviar_email(), para que os presente un formulario como este, para poder enviar un correo electrónico desde nuestra aplicación Excel:


Como ya sabéis, este macro podéis guardarlo en nuestro libro personal de Excel, para poder utilizarlo desde cualquier hoja de cálculo.

Desde aquí podéis descargar el fichero, con el ejemplo que hemos visto en este artículo.