martes, 15 de junio de 2021

Extraer valor numérico

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...
Extraer valor numérico
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) ) )

Extraer valor numérico


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) ) )

Extraer valor numérico
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.