30 noviembre, 2023

EXTRAER INFORMACIÓN ESPECÍFICA DE UNA CADENA ALFANUMÉRICA UTILIZANDO TEXTO EN COLUMNAS

Hace unos días os dejé un post de cómo se podía extraer información de una cadena de texto alfanumérica, utilizando varias funciones conseguíamos el dato que necesitábamos: EXTRAER INFORMACIÓN ESPECÍFICA DE UNA CADENA DE DATOS

Pues bien, me han vuelto a solicitar otra macro que sea capaz de extraer determinada información, el enunciado de la consulta es el siguiente:

Buenas! quisiera saber si se puede modificar el código de tal manera que permita extraer dos números diferentes que corresponden a diferentes cosas de una misma cadena de texto, y almacenarlas en dos celdas diferentes, por ejemplo: «las condiciones ambientales del experimento fueron 24,5 grados y 1,5 atmósferas » poder extraer ambos datos y almacenarlos en celdas contiguas.

Bien, al igual que el post original, podríamos solucionar este problema de forma sencilla utilizando la siguiente macro, de hecho esta fue la macro que hice en ese momento:

Sub Extrae_numeros()
Dim i As Integer, j As Integer, Micelda As String, nCifra As Double
With Sheets("Hoja1")
fin = Application.CountA(.Range("A:A"))
For j = 2 To fin
Micelda = .Cells(j, 1)
For i = Len(Micelda) To 1 Step -1
If Not IsNumeric(Mid(Micelda, i, 1)) And Mid(Micelda, i, 1) <>"," Then Mid(Micelda, i, 1) = " "
Next
Micelda = Trim(Micelda)
nCifra = Application.WorksheetFunction.Search(" ", Micelda)
.Cells(j, 2) = Trim(Mid(Micelda, 1, nCifra)) * 1
.Cells(j, 3) = Trim(Mid(Micelda, nCifra, 10000)) * 1
Next
End With
End Sub

Como podéis ver la macro nos permite extraer las dos cifras y colocarlas en celdas contiguas. Es decir, que en principio realiza todo lo que necesitamos.

Pero después de analizarlo detenidamente, concluyo que este código tiene limitaciones importantes, es decir: no contempla los números negativos, los puntos, que sean más de dos cifras las que debemos extraer, etc.

En efecto, si el lector necesitase extraer 3 cifras tendría un problema, de hecho tendría que definir un nuevo punto (nCifra) desde el cual extraer la cuarta cantidad. Esto se puede hacer, pero tenemos otras formas más eficientes para obtener la información.

Os voy a presentar una macro que he programado para extraer cualquier cantidad que se encuentre en una cadena de texto y que permite colocar esos datos en celdas contiguas. Pero primero vamos a ver los datos que queremos extraer:

EXTRAER INFORMACIÓN DE UNA CADENA DE TEXTO UTILIZANDO TEXTO EN COLUMNAS

Y ahora la vamos a ver la macro:

Sub Extrae_numeros()
'Definimos variables
Dim i As Integer, j As Integer, n As Integer, fin As Integer
Dim nCampos As Integer, n_Colum As Integer
Dim miCelda As String
Dim miArray As Variant, iArray As Variant
'Iniciamos la macro
With Sheets("DATOS")
Application.ScreenUpdating = False
fin = Application.CountA(.Range("A:A"))
'Borramos información a partir de la columna "B"
.Range(.Cells(2, 2), ActiveCell.SpecialCells(xlLastCell)).Select
Selection.ClearContents
'Iniciamos bucle para recorrar todas las filas
For j = 2 To fin
'Seleccionamos la fila
miCelda = .Cells(j, 1)
'Extraemos solo los números, los puntos, las comas y el signo - (si existen)
For i = Len(miCelda) To 1 Step -1
If Not IsNumeric(Mid(miCelda, i, 1)) And Mid(miCelda, i, 1) <> "," _
And Mid(miCelda, i, 1) <> "-" And Mid(miCelda, i, 1) <> "." Then Mid(miCelda, i, 1) = " "
Next
'Eliminamos espacios
miCelda = Trim(miCelda)
'Realizamos un segundo bucle y eliminamos todos los puntos, comas o signos - que aparezan antes de un
'carácter numérico
For n = Len(miCelda) To 1 Step -1
If Mid(miCelda, n, 1) = "," And Not IsNumeric(Mid(miCelda, n + 1, 1)) Then Mid(miCelda, n, 1) = " "
If Mid(miCelda, n, 1) = "." And Not IsNumeric(Mid(miCelda, n + 1, 1)) Then Mid(miCelda, n, 1) = " "
If Mid(miCelda, n, 1) = "-" And Not IsNumeric(Mid(miCelda, n + 1, 1)) Then Mid(miCelda, n, 1) = " "
Next
'Volvemos a eliminar espacios y ya tenemos la cadena de texto depurada.
.Cells(j, 2) = Trim(miCelda)
'Dimensionamos matrices con los datos que tenemos en miCelda
'para determinar las columnas de la función textToColumns
nCampos = Len(.Cells(j, 2))
nCampos = nCampos - 1
ReDim miArray(0 To nCampos)
For n_Colum = 0 To nCampos
ReDim iArray(0 To 1)
iArray(0) = n_Colum + 1
iArray(1) = 1
miArray(n_Colum) = iArray
Next n_Colum
'Aplicamos la función texto en columnas a partir de la segunda columna
'delimitamos el texto en caracteres (en este ejemplo utilizamos los espacios).
Cells(j, 2).TextToColumns Destination:=Range("B" & j), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=True, Space:=True, FieldInfo:=miArray
'Indicamos que todas las matrices tengan formato general, pero podríamos indicar que sea número, etc
Next
.Cells(j, 1).Select
End With
End Sub

Con esta macro, iniciamos varios procesos que debemos comentar (aunque ya lo indico en el código). En primer lugar necesitamos realizar dos bucles, en el primero eliminamos los caracteres no numéricos excepto los puntos, las comas y el signo -.

Por ejemplo, para la primera frase, después de aplicar el primer bucle, nos quedamos con estos datos en la variable «miCelda»:  24,5          1,5
Efectivamente, hemos eliminado los caracteres no numéricos y hemos dejado las comas y los números:

For i = Len(miCelda) To 1 Step -1
If Not IsNumeric(Mid(miCelda, i, 1)) And Mid(miCelda, i, 1) <> "," _
And Mid(miCelda, i, 1) <> "-" And Mid(miCelda, i, 1) <> "." Then Mid(miCelda, i, 1) = " "
Next

Pero en el segundo bucle, si tuviésemos por ejemplo, puntos o comas o guiones que no tienen que ver con números, por ejemplo un punto y seguido o una coma, los eliminaríamos, dejando solo dichos caracteres cuando están incluidos en números:

For n = Len(miCelda) To 1 Step -1
If Mid(miCelda, n, 1) = "," And Not IsNumeric(Mid(miCelda, n + 1, 1)) Then Mid(miCelda, n, 1) = " "
If Mid(miCelda, n, 1) = "." And Not IsNumeric(Mid(miCelda, n + 1, 1)) Then Mid(miCelda, n, 1) = " "
If Mid(miCelda, n, 1) = "-" And Not IsNumeric(Mid(miCelda, n + 1, 1)) Then Mid(miCelda, n, 1) = " "
Next

Una vez que tenemos los datos totalmente depurados, solo queda utilizar el texto en columnas para, precisamente, colocar cada número en la columna contigua.

Cells(j, 2).TextToColumns Destination:=Range("B" & j), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=True, Space:=True

Y de esta forma ya tendríamos la macro totalmente finalizada, ya podríamos extraer las cifras en cada cadena de texto y colocarlas en las columnas que automáticamente generará la función texto en columnas y aplicando formato «general».

Pero imaginad que queréis aplicar formato texto o formato de fecha a los datos que vayáis a extraer. Para poder hacer eso, debemos trabajar con matrices, dimensionando los campos a que vamos a pasar a cada columna y aprovechando para indicar el formato que queremos utilizar en cada uno de ellos:

nCampos = Len(.Cells(j, 2))
nCampos = nCampos - 1
ReDim miArray(0 To nCampos)
For n_Colum = 0 To nCampos
ReDim iArray(0 To 1)
iArray(0) = n_Colum + 1
iArray(1) = 1
miArray(n_Colum) = iArray
Next n_Colum

En este caso, el formato es general: iArray(1) = 1, si fuese texto, sería 2.

Por eso, ahora podemos especificar en el código «de texto en columnas» la información de los campos, es decir, podemos añadir que FielInfo sea igual a la matriz que hemos definido y dimensionado.

Cells(j, 2).TextToColumns Destination:=Range("B" & j), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=True, Space:=True, FieldInfo:=miArray

Para finalizar, este sería el resultado de aplicar la macro:

EXTRAER INFORMACIÓN DE UNA CADENA DE TEXTO UTILIZANDO TEXTO EN COLUMNAS1.jpg

Hemos extraído todas las cifras, conservando puntos, comas y signos negativos. El resto de información de la cadena de texto, simplemente la hemos omitido.

Si no necesitáis darle un formato específico a texto en columnas, podéis eliminar la parte de la macro que hace referencia a las matrices y el FielInfo de la función, aunque yo lo conservaría.

Y aunque seguro que llegarán otras consultas con nuevos planteamientos, creo que esta macro es válida para un amplio abanico de situaciones y necesidades.

Descarga el archivo de ejemplo pulsando en: EXTRAER INFORMACIÓN ESPECÍFICA DE UNA CADENA ALFANUMÉRICA UTILIZANDO TEXTO EN COLUMNAS

 

Comparte este post

8 comentarios en «EXTRAER INFORMACIÓN ESPECÍFICA DE UNA CADENA ALFANUMÉRICA UTILIZANDO TEXTO EN COLUMNAS»

  1. excelente manera de abarcar la solución, muy didáctico.
    agradeceré tu ayuda si te el tiempo te lo permite, una modificación a lo ya explicado,
    resulta que tengo la estructura de una hoja fuente.(codigo, identificador y comentario)

    Codigo Identificador comentario
    AF0002545 ID47492ID47493ID47494 nuevo
    AF0002926 ID69990 ID69991 ID69992 Antiguo
    AF0003927 ID 15524, ID 20178 pendiente
    AF0003928 OSCAR2 ID 77421 ID 77411 ID 77417 ID 77418 ID 77346 extra
    AF0004529 ID: 75958 – 75959 – 75960 – 75961 nuevo
    AF0004620 ID: 36256 pendiente
    AF0005031 ID: 77426 LIMA ICA ID 77424 LIMA CHINCHA Antiguo
    AF0004620 FR: 36256 Nuevo

    se requiere colocar en otra hoja e identificar cada paquete de números (almacenándolos en un arreglo) – para luego presentarlos de forma vertical – cada grupo con su código y comentario respectivo. permitiendo obtener el siguiente resultado:

    Codigo Identificador Comentario
    AF0002545 ID 47492 nuevo
    AF0002545 ID 47493 nuevo
    AF0002545 ID 47494 nuevo
    AF0002926 ID 69990 Antiguo
    AF0002926 ID 69991 Antiguo
    AF0002926 ID 69992 Antiguo
    AF0003927 ID 15524 pendiente
    AF0003927 ID 20178 pendiente
    AF0003928 ID 77421 extra
    AF0003928 ID 77411 extra
    AF0003928 ID 77417 extra
    AF0003928 ID 77418 extra
    AF0004529 ID 75958 nuevo
    AF0004529 ID 75960 nuevo
    AF0004529 ID 75960 nuevo
    AF0004620 ID 36256 pendiente
    AF0005031 ID 77426 Antiguo
    AF0005031 ID 77424 Antiguo
    AF0004620 FR 36256 Nuevo

    gracias desde ya por tu apoyo.
    Oscar V

    1. Hola Oscar:

      Realizar el proceso que indicas en VBA es complejo debido a la calidad de los datos que me muestras. El problema está en la estructura de información de los ID, es decir en cada caso es distinto. Precisamente eso impide automatizar la tarea que requieres. Deberías previamente conseguir datos uniformes, de otra forma no es posible realizar una rutina.

      Saludos.

      1. gracias Segu por tu presta atención, habrá posibilidad de contactar por correo?
        estuve pensando que una caracteristica comun es que todos los valores numéricos siempre tendrán 5 dígitos, En verdad estoy necesitado en encontrarle solucion a este proceso.

        saludos

        1. Hola Oscar:

          El correo es que tengo en la web: excelsignum@yahoo.es

          Aunque los número tengan 5 dígitos, el problema es la estructura, no se puede automatizar porque no existe una rutina. El % de error es muy alto, dado que no conocemos como siguen las estructuras próximas.

  2. Hola que tal , gracias por darnos una luz en excel

    Quisiera saber si podriamos lograr el siguiente cometido.

    Tratare de explicar el siguiente tema sin resolver (y ojala se pueda sin la accion a un boton para realizar la macro)

    En las siguientes columnas C3, D3 y E3 recibo el valor entregado de una funcion buscarv la cual tiene una estructura casi siempre de la forma siguiente:

    MONITOR LED AOC 15.6 / NEGRO / USB POWERED / VGA / ASPECTO 16:9 / TIEMPO DE RESPUESTA 16 MS / RESOLUCION 1366 X 768 / CONSUMO DE ENERGIA 7 V / CONTRASTE 20,000,0001 / BRILLO 220 CD/M2

    otros ejemplos podrian ser

    MONITOR LED SAMSUNG 21.5 WIDESCREEN FULL HD 1920X1080 LS22F350FHLXZX NEGRO D-SUB HDMI
    MONITOR LED SAMSUNG 24 WIDESCREEN FULL HD 1920X1080 LS24F350FHLXZX NEGRO D-SUB HDMI

    eh intentado algunas funciones y macros sin un resultado aproximado a lo que requiero

    ya sea con funcion o macro desearia en base a los datos entregados por buscarv en las columnas mencionadas antes extraer solamente

    Caso 1 : MONITOR LED AOC………. Solo extraer «15.6»
    Caso 2: «21.5»
    Caso 3 «24» este ultimo es donde eh tenido el siguiente resultado 2419 🙁 al no emplear bien mis formulas o funciones resulta que para los primeros caracteres numericos de izq a derecha coloca el 24 y despues continua hasta los siquientes caracteres numericos que encuentra despues de las palabras WIDESCREEEN FULL HD 1920X1080 y no eh logrado solo captar lo que indicaria las pulgadas. Tal se convirtio en mi problema ya que me devuelve 2419

    Nota: Eh logrado corroborar y en todos los registros ya capturados los primeros caracteres numericos que se presentan son los que corresponden a las pulgadas pero las variantes con punto o las cifras con solo 2 caracteres numericos me lo ha complicado

Si te ha gustado o tienes alguna duda, puedes dejar aquí tu comentario.

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies, pinche el enlace para mayor información.plugin cookies

ACEPTAR
Aviso de cookies