🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

VBA NumberFormat en Excel — cambia cómo se muestra un número sin cambiar su valor

|

VBA NumberFormat en Excel — cambia cómo se muestra un número sin cambiar su valor

TL;DRRange.NumberFormat es la capa de visualización: cambia cómo se lee un número guardado y nunca toca el número en sí. Range("A1").Value = 5.4999 con Range("A1").NumberFormat = "0" muestra 5 en pantalla — pero A1.Value sigue siendo 5.4999, y A1 + A1 es 10.9998. NumberFormat no es redondear. Esta es la capa donde «la apariencia frente al valor» te cuesta dinero de verdad, porque una fecha es solo un número de serie disfrazado, y NumberFormat es el disfraz — no el número.

Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets("Report")
ws.Range("A1").Value = 5.4999
ws.Range("A1").NumberFormat = "0"           ' muestra 5...
Debug.Print ws.Range("A1").Value            ' ...pero el valor sigue siendo 5.4999

De las tres capas de formato — Font para el texto, Interior para el relleno, y NumberFormat para la visualización — esta es la que engaña a la gente, porque el disfraz es convincente. Una fuente en rojo nunca hace pensar a nadie que el valor cambió. Una celda que muestra 5, desde luego que sí. Esta guía se construye alrededor de ese único hecho: NumberFormat cambia lo que ves, nunca lo que está guardado, y en cuanto lo tienes claro, las fechas, la moneda, los porcentajes y el clásico error de «mis totales no cuadran» cobran todos sentido.

Lo que aprenderás

  • El modelo mental — NumberFormat es la capa de visualización, y la visualización no es el valor
  • La regla más importante — no es redondear, y el número guardado no cambia
  • Por qué una fecha es un número de serie disfrazado
  • NumberFormat (la propiedad de la celda) frente a la función Format (una cadena)
  • El lenguaje de los códigos de formato — #, 0, las cuatro secciones, moneda y color
  • La trampa de configuración regional — NumberFormat frente a NumberFormatLocal

El modelo mental: NumberFormat es la capa de visualización

Cada celda guarda un valor y, por separado, una regla de cómo dibujar ese valor. NumberFormat es esa regla. Ponerla en "0.00", "$#,##0", "yyyy-mm-dd" o "0%" cambia la presentación — los glifos que Excel pinta — mientras que el número subyacente queda intacto en Range.Value. Piensa en la celda como algo que contiene un número, y en NumberFormat como una lente que le pones delante. Cambia la lente y la vista cambia; el número que hay detrás no se mueve.

Esa separación es todo el tema. Es la razón por la que puedes mostrar el mismo 0.5 como 50%, 0.50 o 1/2 sin cambiar nunca el valor que usan las fórmulas — y por la que ocultar decimales para la visualización no hace que desaparezcan.

La regla más importante: no es redondear

Dilo una vez y no lo olvides nunca: NumberFormat no redondea el valor guardado. Redondea la imagen.

ws.Range("A1").Value = 5.4999
ws.Range("A2").Value = 5.4999
ws.Range("A1:A2").NumberFormat = "0"        ' ambas se muestran como 5
ws.Range("A3").Formula = "=A1+A2"           ' muestra 11? No - muestra 10.9998 redondeado a la vista...
' La suma real es 10.9998. El formato oculto los decimales; no los elimino.

Este es el error de NumberFormat más habitual de todos: formatea una columna a "0" para «dejarla limpia», y luego mira cómo un total sale desviado por uno porque cada celda sigue arrastrando decimales que el ojo no ve. Si necesitas que el valor en sí sea de verdad 5, tienes que cambiar el valor, no el formato:

ws.Range("A1").Value = WorksheetFunction.Round(ws.Range("A1").Value, 0)   ' ahora si es de verdad 5

Regla general: da formato cuando solo necesitas que se vea bien; Round cuando el número tiene que estar bien. Los informes que deben cuadrar al céntimo redondean los valores; los cuadros de mando que solo necesitan leerse limpios dan formato a la visualización. Confundir los dos es como las hojas de cálculo acaban «desviadas por un error de redondeo».

Una fecha es un número de serie disfrazado

Las fechas hacen vívida la separación entre apariencia y valor. Excel guarda una fecha como un número de serie — días desde el 1899-12-30 — y una fecha «es» una fecha solo por su NumberFormat:

ws.Range("B1").Value = 45900                 ' solo un numero
ws.Range("B1").NumberFormat = "yyyy-mm-dd"   ' ahora se LEE como fecha - el numero sigue siendo 45900

De aquí salen directamente dos consecuencias. Primera: para obtener una fecha real, con la que se pueda hacer matemáticas, tienes que poner un valor de fecha real en la celda (ws.Range("B1").Value = DateSerial(2025, 9, 15)) y luego darle formato — dar formato por sí solo sobre el valor equivocado muestra una fecha equivocada. Segunda: aplicar "yyyy-mm-dd" a una cadena de texto como "2025-09-15" no hace nada útil: el texto no tiene ningún número de serie detrás, así que no hay número que disfrazar. Si las fechas llegan como texto, conviértelas (CDate, o consulta VBA CStr para el problema inverso) antes de dar formato. El disfraz solo funciona sobre un número real.

NumberFormat frente a la función Format

Hay dos cosas en VBA con «format» en el nombre, y confundirlas es una fuente real de errores. Son opuestas en un sentido importante:

  • Range.NumberFormat es una propiedad de la celda. Fija una regla de visualización persistente y deja el número subyacente totalmente intacto y editable. Esto es lo que quieres en una hoja de cálculo.
  • Format(value, "pattern") es una función que devuelve una String. Se trata en VBA Format, y sirve para construir texto — un cuadro de mensaje, un nombre de archivo, una etiqueta concatenada — no para dar formato a una celda.

La trampa es usar Format para meter un «número formateado» en una celda:

ws.Range("C1").Value = Format(1234.5, "$#,##0.00")   ' escribe la CADENA "$1,234.50"
' C1 ahora es texto. No puedes hacerle SUM, ordenarlo numericamente ni graficarlo.

Esa celda parece con formato, pero ahora contiene texto, y su número ha desaparecido. La versión correcta conserva el número y fija la regla de visualización:

ws.Range("C1").Value = 1234.5
ws.Range("C1").NumberFormat = "$#,##0.00"            ' muestra $1,234.50, sigue siendo un numero real

La regla: NumberFormat para celdas, Format para cadenas. Si el resultado tiene que seguir siendo un número, nunca lo hagas pasar por Format.

El lenguaje de los códigos de formato

Los códigos de formato son un pequeño lenguaje, y cuatro reglas leen casi todos:

  • 0 es un dígito forzado, # es uno opcional. "0.00" siempre muestra dos decimales (5 pasa a 5.00); "#.##" muestra hasta dos y descarta los ceros finales (5 se queda en 5).
  • , agrupa los millares. "#,##0" convierte 1234567 en 1,234,567.
  • Los símbolos literales pasan tal cual. $, %, los espacios y el texto entre comillas aparecen como se escriben — "$#,##0.00", "0%" (que además multiplica por 100 para la visualización), "0.0 kg".
  • Los puntos y coma lo dividen en secciones: positive;negative;zero;text. Esta es la potente:
' Positivos en negro, negativos en rojo entre parentesis, cero como guion, texto entre comillas literal.
ws.Range("D2:D100").NumberFormat = "#,##0.00;[Red](#,##0.00);\-;@"

[Red] (y otros nombres de color entre corchetes) fija el color de visualización por sección, y @ es el marcador de posición del texto. Rara vez necesitas las cuatro secciones, pero saber que existen te permite leer cualquier cadena de formato que te encuentres. Para las fechas los tokens son d/m/y y h/m/s"yyyy-mm-dd hh:mm" — con la peculiaridad de que m significa mes después de y o d, y minuto después de h.

La trampa de configuración regional: NumberFormat frente a NumberFormatLocal

La última trampa muerde en los libros compartidos. NumberFormat siempre usa códigos de formato en inglés de EE. UU., para los millares, . para el decimal, m/d/y para las fechas — sin importar la configuración regional que tenga el usuario. NumberFormatLocal usa los símbolos locales del usuario (en alemán, . agrupa los millares y , es el decimal).

ws.Range("E1").NumberFormat = "#,##0.00"        ' portable: mismo resultado en toda maquina
ws.Range("E2").NumberFormatLocal = "#.##0,00"   ' codigos al estilo aleman - solo correcto en configuracion regional alemana

Escribe tus macros contra NumberFormat con códigos de EE. UU. y se comportarán igual en todas partes. Echa mano de NumberFormatLocal solo cuando lees o igualas a propósito lo que un usuario tecleó en su propia configuración regional. Meter códigos al estilo local en NumberFormat (o al revés) es un error sutil que funciona en tu máquina y se rompe en la de un colega.

Cómo ayuda ExcelMaster

NumberFormat esconde más decisiones que cualquier otra capa de formato: si necesitas redondear el valor o solo la visualización, si una celda de fecha contiene un serial real o una cadena de texto, si una celda «con formato» es en secreto texto de Format, y cuál de NumberFormat o NumberFormatLocal mantiene el código portable. Cada giro equivocado devuelve una celda de aspecto plausible con un número roto detrás.

ExcelMaster te deja decir qué aspecto deben tener los números. Pídele «muestra la columna D como moneda con los negativos en rojo» o «haz que las fechas se lean como 2025-09-15», y fija NumberFormat en la celda — manteniendo el valor como un número real con el que se puede hacer matemáticas — redondea con Round cuando el total tiene que cambiar de verdad, y usa códigos de formato de EE. UU. portables. Te quedas con el libro y con el código; te ahorras el informe que cuadró mal porque los decimales solo estaban ocultos, no eliminados.

Preguntas frecuentes

¿NumberFormat cambia el valor real de una celda en VBA?

No. Range.NumberFormat cambia solo cómo se muestra el número guardado. Una celda que contiene 5.4999 formateada como "0" muestra 5 pero sigue conteniendo 5.4999, y las fórmulas usan el valor completo — así que las sumas pueden parecer «desviadas por uno». Para cambiar el valor en sí, usa WorksheetFunction.Round(value, digits) y vuelve a asignarlo; dar formato por sí solo nunca redondea el número guardado.

¿Cómo formateo una celda como moneda o fecha en VBA?

Fija el valor, luego el formato. Para moneda, Range("A1").Value = 1234.5 y luego Range("A1").NumberFormat = "$#,##0.00". Para una fecha, Range("B1").Value = DateSerial(2025, 9, 15) y luego Range("B1").NumberFormat = "yyyy-mm-dd". Fijar solo el formato sobre una cadena de texto no hace nada, porque no hay ningún número subyacente que mostrar.

¿Cuál es la diferencia entre NumberFormat y la función Format?

Range.NumberFormat es una propiedad de celda que fija una regla de visualización y mantiene el valor como un número real. Format(value, "pattern") es una función que devuelve una String. Usa NumberFormat en las celdas de la hoja; usa Format para construir texto para mensajes, nombres de archivo o etiquetas. Escribir Format(...) en una celda la convierte en texto que ya no puedes sumar ni graficar.

¿Por qué mis totales salen mal después de formatear los números?

Porque NumberFormat oculta los decimales sin eliminarlos. Formatear una columna a "0" muestra números enteros, pero cada celda sigue guardando sus decimales, así que el total real los incluye y puede diferir de la suma de las cifras mostradas. Si el total tiene que coincidir con lo que se muestra, redondea los valores con WorksheetFunction.Round en lugar de solo formatearlos.

¿Cuál es la diferencia entre NumberFormat y NumberFormatLocal?

NumberFormat usa códigos de formato en inglés de EE. UU. (coma para los millares, punto para el decimal) en todas las máquinas, así que es portable. NumberFormatLocal usa los símbolos regionales del usuario, que varían según la configuración regional. Escribe las macros contra NumberFormat para un comportamiento coherente en todas partes, y usa NumberFormatLocal solo cuando igualas a propósito lo que un usuario ve en su propia configuración.

Probado en

Probado en: Excel 365 (Windows 11), VBA 7.1 — última verificación el 11/08/2026.

Guías relacionadas: VBA Font · VBA Color de celda · VBA Format · VBA CStr · VBA Range