Hojas de cálculo en Excel - página principal

Forzar la escritura en mayúsculas (o minúsculas)

En otro artículo del blog expliqué como pasar un rango de celdas de mayúsculas a minúsculas (o viceversa). Evidentemente no comenté la posibilidad de utilizar la función =MAYUSC(texto), porque el macro solventaba todos los problemas que esa función no contempla, como por ejemplo que esa función debes utilizarla en otra celda, para luego hacer un copiado y pegado especial (pegando valores) en la celda de origen (siempre que lo que haya en la celda no sea una función, porque entonces la liaremos más todavía). Pues bien, ese macro solucionaba el tema de pasar un rango de celdas escrito en minúsculas, a mayúsculas, o viceversa. También contemplaba el hecho de que si lo que había en la celda era una función, entonces no debía hacer nada, pues solo nos interesaba el texto.

El macro deberemos copiarlo en la hoja que queramos controlar para que todo lo que se escriba en ella, se pase a mayúsculas (o bien a minúsculas):



Lo que tendremos que copiar es esto, si deseamos convertir todo lo que escribamos, automáticamente en mayúsculas:


Private Sub Worksheet_Change(ByVal Target As Range)
'Si hay errores, que continúe
On Error Resume Next
'pasamos los datos a variables
fila = Target.Row
columna = Target.Column
'reescribimos el dato introducido en la celda pasándolo
'a mayúsculas siempre que no sea una fórmula

If Left(Cells(fila, columna).Formula, 1) <> "=" Then Cells(fila, columna) = UCase(Cells(fila, columna))
End Sub

Si por el contrario, lo que queremos es que todo lo que escribamos se convierta automáticamente en minúsculas, lo que tendremos que poner es esto:

Private Sub Worksheet_Change(ByVal Target As Range)
'Si hay errores, que continúe
On Error Resume Next
'pasamos los datos a variables
fila = Target.Row
columna = Target.Column
'reescribimos el dato introducido en la celda pasándolo
'a minúsculas siempre que no sea una fórmula

If Left(Cells(fila, columna).Formula, 1) <> "=" Then Cells(fila, columna) = LCase(Cells(fila, columna))
End Sub

Si en cambio, lo que queremos es que estos cambios automáticos sucedan en todas las hojas del libro, deberemos cambiar la primera línea:

Private Sub Worksheet_Change(ByVal Target As Range)

Por esta otra, y además, pegar el código en ThisWorkbook:

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)


Si ponéis en práctica este sencillo ejemplo, veréis como todo lo que escribáis en la hoja (o en el libro, si lo habéis aplicado a ThisWorkbook) se convierte automáticamente en mayúsculas (o minúsculas, dependiendo de lo que hayáis elegido), pero que las funciones os las va a respetar dejándolas como siempre las trata Excel (normalmente siempre las pone en mayúsculas). Si no hubiésemos puesto ese condicional en el macro que evalúa si se trata de una fórmula o no, al cambiar o introducir una fórmula en una celda, lo que obtendríamos es el resultado de la citada función, como si hubiésemos hecho un pegado especial de valores, pues no nos respetaría la función introducida.

Como veis, se trata de un macro muy sencillo, al que en alguna ocasión seguramente le daréis buen uso.



33 comentarios:

Miguelon dijo...

Esta bien este truquillo ! Necesito pedirte una ayudita aunque debes estar ocupado preparando nuevas y magnificas macros. Intento que cuando D6 ponga "Cuota", entonces la macro mire la columna AG (desde la fila 16 hasta la 196) y aquella que tenga valor "SI" se vaya hasta la columna C (en la misma fila. Aquí se hará eso de Offset (-30,0)...) y entonces desbloquee esa celda. Mil gracias! Permíteme sugerirle un par de bucles para tus proximas clases. Aprendo muchisimo, de verdad!

El pilt®afilla - www.3piesalgato.com dijo...

Te doy pistas de como hacer eso:

1. Mírate esta entrada del blog donde hablo de como ejecutar una macro al cambiar una celda. En tu caso quieres que se ejecute al cambiar la celda D6. Simplemente debes incorporar un condicional que mire si además de cambiar la celda, hay escrita la palabra "Cuota". En ese caso, que vaya a la columna AG (esto puedes hacerlo con la grabadora de macros). Recorres con un bucle do while (casi todos los ejemplos del blog usan este bucle) toda la columna AG hasta dar con la palabra "SI", y con la propiedad Offset (hay infinidad de ejemplos en el blog) miras X columnas atrás (tantas columnas como haya desde la columna AG hasta la columna C, cosa que no he contado). Una vez ahí, desproteges la hoja, cambias las propiedades de la celda (con la grabadora de macros, por ejemplo, desde Formato, Celda, Proteger), vuelves a proteger la hoja, y vuelves a la columna AG (con la función offset), para que en el caso de que haya más "Si" en esa columna, baje para abajo en busca de la siguiente. Debes hacer todo eso hasta llegar a la primera fila vacía en la columna AG.

Si prefieres, hazlo solo buscando el primer "SI" que encuentres, y luego todo eso ya lo meterás en un bucle hasta acabar con toda la columna AG.

Saludos.

Walter E. dijo...

Acabo de conocer tu blog, Felicitaciones por esa labor titánica que has hecho !!!!!!

Eres un apasionado de Excel y un apasionado de la docencia.

Excelente trabajo !

Voy a seguir visitando tu blog regularmente para nutrirme de tus conocimeintos.

El pilt®afilla - www.3piesalgato.com dijo...

Muchas gracias por tu comentario, Walter.

Warloofer dijo...

Hola. Me gusta mucho tu blog. Hace tiempo que andaba buscando funciones avanzadas de excel en espanyol enfocadas a tareas concretas.

Yo tambien soy un usuario avanzado, aunque no es mi trabajo, me paso mas horas de las que me gustaria con formulas y scripts. Aun asi, he de reconocer que manejas funciones VBA que ni siquiera conocia (sobre todo en lo relativo a cargar objetos, administrar errores, etc.). Siempre que he necesitado algo relativo a archivos, etc..., lo he tenido que buscar en google (benditos foros ingleses).

Te escribo para comentarte que hay una forma de referirse a celdas en VBA mucho mas practica que la de offsets. Igual la conocer y prefieres utilizar los ofsets, en cualquier caso, la funcion es la siguiente:

- "Cells(x,y).value" se refiere al valor de una celda en la fila X y columna Y (numero).
- "range(cells(x1,y1).address, cells(x2,y2).address).value" devuelve un rango que va de la celda de la fila x1 y columna y1, a la x2 e y2.

Estos comandos son de muchisima utilidad cuando quieres hacer operaciones complejas, ya que es facil trabajar con bucles de esta forma.

Espero haberte podido ayudar en algo, ya que el esfuerzo desinteresado que muestras al compartir conocimientos de una forma tan detallada, merece ser reconocido.


(Sorry por las tildes, estoy en UK).

El pilt®afilla - www.3piesalgato.com dijo...

Antes de nada, disculpa por la tardanza, pero estaba de vacaciones :-)

Gracias por el comentario. Sí, conozco esas formas de referirte a las celdas, pero siempre me ha sido más sencillo desplazarme utilizando la función ofsset. Es como cuando me refiero a una celda en concreto, que por ejemplo, lo hago con Range("A1"), aunque se puede llamar a esa celda de infinidad de formas.

Supongo que me pasa porque cuando te acostumbras a algo, sueles utilizar eso habitualmente.

Un saludo, y muchas gracias por tu comentario.

Anónimo dijo...

Buenas tardes, me han sido muy utiles algunas de las propuestas que tienes en tu blog , por cierto , gracias!!!!. Pero ahora tengo un problema, tengo una hoja de excel(sheet1), en donde registros todos los datos de un flete(nombre del chofer, placas del camion y todo lo referente a un embarque)el cual imprimo y al final del dia tengo que registralos en otro libro de excel manualmente y eso me quita tiempo, habra alguna forma de agregarle un boton(command button ) a la hoja que lleno al principio que diga registrar y que al picarle ese boton me guarde automaticamente toda la informacion en el otro libro donde llevo el registro ?, de esta forma ya no tendria que hacerllo manualmente al final del dia. espero me puedas ayudar, muchas gracias. jnick025@hotmail.com

Unknown dijo...

Amigo

Me ha ayudo muchisimo esta macro

Elena Martínez dijo...

hola, acabo de dar con tu blog y la verdad estoy encantada, vi tu macro para poner en mayúsculas el contenido de las celdas, pero tengo una pregunta como hago lo mismo pero para un rango de celdas de la hoja y no todas

saludos cordiales desde mexico

El pilt®afilla - www.3piesalgato.com dijo...

El artículo que has leído habla de como "obligar" al usuario a escribir siempre en mayúsculas o minúsculas, pero entiendo que lo que pretendes, es convertir un párrafo ya está en mayúsculas a minuúsculas o viceversa. Para ello, mírate este artículo de como pasar de mayúsculas a minúsculas, o viceversa.

Si por el contrario, lo que quieres es hacer que solo un determinado rango de celdas se escriba obligatoriamente en mayúsculas o minúscilas, deberás adaptar el macro de este artículo donde dejo el comentario, junto con este otro donde explico como ejecutar una macro al cambiar una celda (aunque puedes adaptarlo para que se ejecute el macro (poniendo en mayúsculas o minúsculas), cuando cambie no solo una, sino varias celdas de un rango.

Miguel Pérez dijo...

Estimado Javier Marco,

Utilicé tu idea para forzar la escritura en mayúsculas:
Private Sub Worksheet_Change(ByVal Target As Range)

'Pasamos a mayúsculas la columna L (12 en situación)
'If Target.Column = 12 Then
fila = Target.Row
columna = Target.Column
Cells(fila, columna) = UCase(Cells(fila, columna))
End Sub
Pero cuando llega a la línea de Cells(fila, columna)..., se mete en una especie de bucle. Cuando sigo la ejecución paso a paso veo que, al llegar a esa línea que te he mencionado, se va a una función que tengo escrita para otra cosa; pero que afecta a la misma hoja y no tiene nada que ver con lo que quiero hacer.
Decirte que no conozco nada bien el lenguaje utilizado.
Porfi, ayuda.
Miguel

El pilt®afilla - www.3piesalgato.com dijo...

Prueba esto. Solo fuerza la escritura en mayúsculas, para la columna L:

Private Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next
fila = Target.Row
columna = Target.Column
If Not Application.Intersect(Target, [L:L]) Is Nothing Then
If Left(Cells(fila, columna).Formula, 1) <> "=" Then Cells(fila, columna) = UCase(Cells(fila, columna))
End If
End Sub

Saludos.

Miguel Pérez dijo...

Buenas tardes, Javier.
Muchas gracias por la celeridad de tu respuestas. Pero se sigue metiendo en una especie de bucle. Esto es de lo más raro.
Cuando llega a Cells(fila, columna) = UCase(Cells(fila, columna)), justo entonces, entra en una función que yo mismo hice para la columna B.
En tu propuesta creo que faltaba un end if. Por lo que puse:
Private Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next
fila = Target.Row
columna = Target.Column
If Not Application.Intersect(Target, [L:L]) Is Nothing Then
If Left(Cells(fila, columna).Formula, 1) <> "=" Then
Cells(fila, columna) = UCase(Cells(fila, columna))
End If
End If
End Sub
La función en la que entra, la mía es:
Dim mesNum As Integer
Dim mesName As String
Dim numDia As String


'Convierte el número del mes en su respectivo nombre.

Function MesTexto(mesNum) As String

Select Case mesNum
Case 1
MesTexto = "enero"
Case 2
MesTexto = "febrero"
Case 3
MesTexto = "marzo"
Case 4
MesTexto = "abril"
Case 5
MesTexto = "mayo"
Case 6
MesTexto = "junio"
Case 7
MesTexto = "julio"
Case 8
MesTexto = "agosto"
Case 9
MesTexto = "septiembre"
Case 10
MesTexto = "octubre"
Case 11
MesTexto = "noviembre"
Case 12
MesTexto = "diciembre"
End Select

End Function

Saludos,
Miguel

El pilt®afilla - www.3piesalgato.com dijo...

No es necesario poner el End If, cuando todo va en una línea, como es el caso de esta que incluí en el macro (aunque se vea cortado, si haces un copiar y pegar, verás que va todo en una sola línea):

If Left(Cells(fila, columna).Formula, 1) <> "=" Then Cells(fila, columna) = UCase

Eso, es lo mismo que esto:

If Left(Cells(fila, columna).Formula, 1) <> "=" Then
Cells(fila, columna) = UCase
End If

Por lo demás, mete estas líneas dentro de la función, no fuera como las tienes:

Dim mesNum As Integer
Dim mesName As String
Dim numDia As String

Miguel Pérez dijo...

Te juro por Dios bendito que no me explico lo que está pasando.

He pasado esas variables al ámbito de las funciones que las usan, y funcionan igualmente; pero no entiendo por qué esa línea: Cells..., de tu propuesta, que además cambia a mayúsculas, se mete en una función a la que no llama.

Porfi. Se que te estoy dando mucho la plasta, pero ya me he picado.

El pilt®afilla - www.3piesalgato.com dijo...

Prueba lo que te propuse en un fichero sin esa función y verás como funciona.

Por otra parte, la función debe ir en un módulo VBA, mientras que el macro que te puse debe ir en la hoja donde quieras forzar las mayúsculas (dentro de la carpeta que verás en modo VBA, llamada Microsoft Excel Objetos).

Descárgate esto, que contiene ambas cosas, donde deben ir: http://www.megaupload.com/?d=BZXGI1BI

Miguel Pérez dijo...

Lo tengo todo como tú me dices, por eso me parece tan raro lo que pasa.

Lo que tú propones claro que funciona. El problema es que, durante el proceso, cuando llega a la fila que te he comentado, se va a una función que tengo en un módulo. Eso hace que todo se relentice, claro.

En fin..., Serafín.

Miguel Pérez dijo...

Esto cambia a mayúsculas también:
Private Sub Worksheet_Change(ByVal Target As Range)
'On Error Resume Next
fila = Target.Row
columna = Target.Column
'Cells(fila, columna) = UCase(Cells(fila, columna))
Target.Value = UCase(Target)

End Sub
, pero sigue metiéndome en la otra función cuando llega a esta línea: Target.Value = UCase(Target)

Aalvarez dijo...

Buena tarde

Es de gran utilidad ti blog, esta genial.

Al mismo tiempo te consulto lo siguiente: tengo una base de datos en la cual los datos estan en mayusculas, estas las quiero pasar como Nombre propio, (CANNON a Cannon), Tengo que cambiar solo la primera Letra a Mayuscula, or otro lado en la misma base de datos tengo celdas vacias, quiero agregarle un valos "X". ¿como lo podria hacer? De antemano Gracias.

Anónimo dijo...

Justo andaba buscando algo similar y me encontré con tu blog. Solo quiero felicitarte por tu trabajo y agradecerte por compartirlo.

Anónimo dijo...

De grandísima utilidad.
Muy bueno el post.

Yair Alcocer dijo...

hola bueanas tardes pues primero felicitar al señor Javier Matco por la pagina excelente informacion par uno que esta empezando a provechar como se debe el excel ^_^ y aun asi los que tiene tiempo trabajando, siempre hay algo que aprender, y pues mi pregunta es referente a la dicha funcion que publicas que lo adapte a un celda especifica el detalle es que si elimino el contenido del celda me bota del programa, algun comentario al respecto que me ayude a subsanar este inconveniente?, de antemano muchas gracias por su apoyo.

El pilt®afilla - www.3piesalgato.com dijo...

Yair, es rarísimo lo que te ocurre. Yo lo he probado en Excel 2003 y Excel 2010, y funciona correctamente, tanto si borras el contenido, como si eliminas la fila.

Prueba en otro equipo con Excel instalado, a ver si te funciona correctamente. Si te fijas, ese código es sencillísimo, y debería funcionar hasta en las primeras versiones de Excel.

Saludos.

aescobar68 dijo...

Private Sub TextBox4_Change()
Set rango = Selection
For Each cell In rango
TextBox4.Value = UCase(TextBox4.Value)
Next
End Sub

Esta rutina dentro del Userform, comvierte todo texto en el textbox a mayuscula desde la entrada del mismo.

Anónimo dijo...

Grandioso aporte, habrá algo similar para poder capitalizar la primera letra de las palabras que escribas en una celda? por ejemplo, en una celda ocupo capturar los dos apellidos, y quiero que quede en mayuscula la primera letra de cada uno de ellos.

Gracias de antemano... y saludos!!!

Carlos Arce dijo...

Muchas gracias Javier Marco por la prontitud de tu respuesta, voy a buscar como hacer que funcione porque no quiere, mientras esperaba tu respuesta segui buscando e instalé otras funciones que a lo mejor estan bloqueando la tuya, a ver si encuentro que es, gracias!!!

Carlos Arce dijo...

Aqui de nuevo molestando, ya funciona, funciona bien cuando dentro de la celda es una sola palabra, instantáneamente la capitaliza, pero cuando escribo dos o mas palabras o simplemente agrego un espacio después de una palabra dentro de la celda, al darle enter o cambiar de celda se queda procesando y se traba la aplicacion de excel. Alguna idea?

Tengo el office 2007.

Carlos Arce dijo...

Ya encontré el error Javier Marco, en la linea donde dice:

Do While InStr(cadena, " ")
cadena = Replace(cadena, " ", " ")
Loop

lleva 2 espacios en:
InStr(cadena, " ")

Con eso se soluciona, ya que se quedaba ciclado en el while.

Muchas gracias por tu ayuda mi amigo, saludos...

Carlos Arce

El pilt®afilla - www.3piesalgato.com dijo...

Vuelvo a publicar el código porque al subirlo, blogger me ha eliminado el doble espacio, y debe llevarlo para que funcione:

Aquí tienes lo que buscas, para obtener la letra capital de cada palabra de una celda, de tal forma que si escribes en una celda javier marco, te lo reescribirá como Javier Marco:

Private Sub Worksheet_Change(ByVal Target As Range)
'Si hay errores, que continúe
On Error Resume Next
'pasamos los datos a variables
fila = Target.Row
columna = Target.Column
'reescribimos el dato introducido en la celda pasándolo
'a mayúsculas siempre que no sea una fórmula
If Left(Cells(fila, columna).Formula, 1) <> "=" Then
'Función para poner las iniciales de un campo en mayúsculas,
'con independencia del nº de palabras que conformen la cadena.
'Miramos si existen más de un espacio vacío,
'y lo reemplazamos por un único espacio vacío
cadena = Cells(fila, columna)
Do While InStr(cadena, "  ")
cadena = Replace(cadena, "  ", " ")
Loop
'Descomponemos la cadena, en subcadenas,
'para lo cual incidamos el delimitador " ", aunque
'por defecto, podríamos haberlo omitido, pues es ese mismo
cadena = Split(Trim(cadena), " ", -1, 1)
'miramos las palabras que componen la cadena,
'para lo cual le decimos que recorra desde el primer
'valor de la matriz (empieza en cero), hasta el máximo
'valor (nº de la última palabra) que lo obtenemos con el UBound
For i = 0 To UBound(cadena)
'ponemos la inicial en mayúsculas, y el resto en minúsculas
cadena(i) = UCase(Left(cadena(i), 1)) & LCase(Right(cadena(i), Len(cadena(i)) - 1))
Next
'Unimos las cadenas, con la función Join
Cells(fila, columna) = Join(cadena)
End If
End Sub


Es una adaptación de una función que ya publiqué en su día, en foros del web, en el subforo de ASP, concretamente en este aporte: http://www.forosdelweb.com/983589-post56.html

Borro el anterior mensaje, en el que no salían los dos espacios.

Saludos

fgomezal dijo...

Javier Marco:
Te agradezco todas las aportaciones que tienes en este espacio, las macros para mi eran un mundo aparte, no tenia idea; pero hoy dia con tu valiosa ayuda he despejado muchas dudas de las macros y puesto en practica tu enseñanza. Al respecto quiero consultarte si existe algun codigo para forzar la escritura de MAYUSCULAS o minusculas a letra capital o de tipo titulo; pero referidas a un rango de celdas definidas por el usuario, la explicacion o codigo que indicas a Carlos Arce, forza la escritura para todas las columnas o celdas. Se podra referir el codigo a un rango de celdas???. Gracias por tu apoyo desinteresado. DIOS te bendiga
Federico

Anónimo dijo...

Hola, La macro funciona bien pero tengo un problema. Cuando borro una celda, la macro se deshabilita automáticamente y no vuelve a pasa las palabras a mayúsculas. Soy nuevo en esto: ¿Qué podría hacer? Muchas gracias

El pilt®afilla - www.3piesalgato.com dijo...

Debería funcionarte correctamente, tanto si borras, o eliminas filas o columnas, pues el macro se activa cuando se cambia una celda (cuando introduces un texto, se produce un cambio).

Sinceramente, desconozco por qué no te funciona.

Unknown dijo...

Yo tenia el mismo problema, el macro se bugea cuando trabaja con formulas. Solo úsalo con texto y no pasará eso.