Hace algunos días, durante una formación, un asistente me preguntaba por un problema que le surgía muchas veces al recuperar valores numéricos de cierto lugar... y es que esos números cada vez se importaban de distintas maneras, con distintos separadores de miles y/o decimales (coma o punto), mezclado con caracteres no numéricos, espacios en blanco, símbolos de monedas, etc...
Aquí explico una versión mejorada de la que le aporte inicialmente...
La fórmula buscada sería:
=LET(dato;B2;
calculo1;UNIRCADENAS("";VERDADERO; SI(ESNUMERO(--EXTRAE(dato;SECUENCIA(1;LARGO(dato));1))+(EXTRAE(dato;SECUENCIA(1;LARGO(dato));1)=".")+(EXTRAE(dato;SECUENCIA(1;LARGO(dato));1)=",");EXTRAE(dato;SECUENCIA(1;LARGO(dato));1);""));
Separadores;UNIRCADENAS("";VERDADERO;UNICOS(SI(NO(ESNUMERO(--EXTRAE(calculo1;SECUENCIA(1;LARGO(calculo1));1)));EXTRAE(calculo1;SECUENCIA(1;LARGO(calculo1));1);"");1));
negativo;SI.ERROR(SI(ENCONTRAR("-";dato)>0;"-";"");"");
separador1;EXTRAE(Separadores;2;1);
separador2;EXTRAE(Separadores;1;1);
SI.CONJUNTO(LARGO(Separadores)=0;VALOR((negativo&calculo1));
LARGO(Separadores)=1;VALOR.NUMERO((negativo&calculo1);separador2);
LARGO(Separadores)=2;VALOR.NUMERO((negativo&calculo1);separador1;separador2) ) )
Bajo ciertas condiciones respecto a los separadores decimales y de miles (indistintamente coma y/o punto) la fórmula parece responder adecuadamente, incluso para números negativos...
Desglosamos el paso a paso:
En el primer paso
calculo1;UNIRCADENAS("";VERDADERO; SI(ESNUMERO(--EXTRAE(dato;SECUENCIA(1;LARGO(dato));1))+(EXTRAE(dato;SECUENCIA(1;LARGO(dato));1)=".")+(EXTRAE(dato;SECUENCIA(1;LARGO(dato));1)=",");EXTRAE(dato;SECUENCIA(1;LARGO(dato));1);""));
La función recupera cualquier valor numérico de la cadena de texto dada, así como los caracteres coma y punto.
Nota la condición triple dada en el condicional para quedarnos con esos caracteres:
ESNUMERO(--EXTRAE(dato;SECUENCIA(1;LARGO(dato));1))+(EXTRAE(dato;SECUENCIA(1;LARGO(dato));1)=".")+(EXTRAE(dato;SECUENCIA(1;LARGO(dato));1)=",")
Dado como suma para replicar el operador lógico O
En el segundo paso recuperamos únicamente los separadores de miles y decimales, de manera única:
Separadores;UNIRCADENAS("";VERDADERO;UNICOS(SI(NO(ESNUMERO(--EXTRAE(calculo1;SECUENCIA(1;LARGO(calculo1));1)));EXTRAE(calculo1;SECUENCIA(1;LARGO(calculo1));1);"");1));
Aplicamos la función UNICOS para obtener una cadena de dos caracteres... del orden en el que aparezcan dependerá de cómo entendemos dichos separadores:
El primero que aparezca será el separador de miles
El segundo el decimal
En los siguientes pasos recuperamos posibles separadores y signo negativo:
negativo;SI.ERROR(SI(ENCONTRAR("-";dato)>0;"-";"");"");
separador1;EXTRAE(Separadores;2;1);
separador2;EXTRAE(Separadores;1;1);
Para finalmente aplicar al valor obtenido la función VALOR o VALOR.NUMERO según el número de separadores obtenidos: valor que solo debería ser 0,1 ó 2 (esto es, ningún separador; uno solo que entenderemos que será el decimal!!!; o dos separadores con el orden establecido: primero decimal y segundo de miles):
SI.CONJUNTO(LARGO(Separadores)=0;VALOR((negativo&calculo1));
LARGO(Separadores)=1;VALOR.NUMERO((negativo&calculo1);separador2);
LARGO(Separadores)=2;VALOR.NUMERO((negativo&calculo1);separador1;separador2) ) )
En este caso la función SI.CONJUNTO es la encargada de evaluar nuestros criterios...
Solo quedaría aplicar el formato deseado al ya número conseguido...
Nota final: obviamente se requiere al menos un valor numérico en la cadena de texto. ;-)
Aquí explico una versión mejorada de la que le aporte inicialmente...
La fórmula buscada sería:
=LET(dato;B2;
calculo1;UNIRCADENAS("";VERDADERO; SI(ESNUMERO(--EXTRAE(dato;SECUENCIA(1;LARGO(dato));1))+(EXTRAE(dato;SECUENCIA(1;LARGO(dato));1)=".")+(EXTRAE(dato;SECUENCIA(1;LARGO(dato));1)=",");EXTRAE(dato;SECUENCIA(1;LARGO(dato));1);""));
Separadores;UNIRCADENAS("";VERDADERO;UNICOS(SI(NO(ESNUMERO(--EXTRAE(calculo1;SECUENCIA(1;LARGO(calculo1));1)));EXTRAE(calculo1;SECUENCIA(1;LARGO(calculo1));1);"");1));
negativo;SI.ERROR(SI(ENCONTRAR("-";dato)>0;"-";"");"");
separador1;EXTRAE(Separadores;2;1);
separador2;EXTRAE(Separadores;1;1);
SI.CONJUNTO(LARGO(Separadores)=0;VALOR((negativo&calculo1));
LARGO(Separadores)=1;VALOR.NUMERO((negativo&calculo1);separador2);
LARGO(Separadores)=2;VALOR.NUMERO((negativo&calculo1);separador1;separador2) ) )
Bajo ciertas condiciones respecto a los separadores decimales y de miles (indistintamente coma y/o punto) la fórmula parece responder adecuadamente, incluso para números negativos...
Desglosamos el paso a paso:
En el primer paso
calculo1;UNIRCADENAS("";VERDADERO; SI(ESNUMERO(--EXTRAE(dato;SECUENCIA(1;LARGO(dato));1))+(EXTRAE(dato;SECUENCIA(1;LARGO(dato));1)=".")+(EXTRAE(dato;SECUENCIA(1;LARGO(dato));1)=",");EXTRAE(dato;SECUENCIA(1;LARGO(dato));1);""));
La función recupera cualquier valor numérico de la cadena de texto dada, así como los caracteres coma y punto.
Nota la condición triple dada en el condicional para quedarnos con esos caracteres:
ESNUMERO(--EXTRAE(dato;SECUENCIA(1;LARGO(dato));1))+(EXTRAE(dato;SECUENCIA(1;LARGO(dato));1)=".")+(EXTRAE(dato;SECUENCIA(1;LARGO(dato));1)=",")
Dado como suma para replicar el operador lógico O
En el segundo paso recuperamos únicamente los separadores de miles y decimales, de manera única:
Separadores;UNIRCADENAS("";VERDADERO;UNICOS(SI(NO(ESNUMERO(--EXTRAE(calculo1;SECUENCIA(1;LARGO(calculo1));1)));EXTRAE(calculo1;SECUENCIA(1;LARGO(calculo1));1);"");1));
Aplicamos la función UNICOS para obtener una cadena de dos caracteres... del orden en el que aparezcan dependerá de cómo entendemos dichos separadores:
El primero que aparezca será el separador de miles
El segundo el decimal
En los siguientes pasos recuperamos posibles separadores y signo negativo:
negativo;SI.ERROR(SI(ENCONTRAR("-";dato)>0;"-";"");"");
separador1;EXTRAE(Separadores;2;1);
separador2;EXTRAE(Separadores;1;1);
Para finalmente aplicar al valor obtenido la función VALOR o VALOR.NUMERO según el número de separadores obtenidos: valor que solo debería ser 0,1 ó 2 (esto es, ningún separador; uno solo que entenderemos que será el decimal!!!; o dos separadores con el orden establecido: primero decimal y segundo de miles):
SI.CONJUNTO(LARGO(Separadores)=0;VALOR((negativo&calculo1));
LARGO(Separadores)=1;VALOR.NUMERO((negativo&calculo1);separador2);
LARGO(Separadores)=2;VALOR.NUMERO((negativo&calculo1);separador1;separador2) ) )
En este caso la función SI.CONJUNTO es la encargada de evaluar nuestros criterios...
Solo quedaría aplicar el formato deseado al ya número conseguido...
Nota final: obviamente se requiere al menos un valor numérico en la cadena de texto. ;-)
No hay comentarios:
Publicar un comentario
Nota: solo los miembros de este blog pueden publicar comentarios.