Indicación de una columna por un nombre
Resuelto
Tom 44
Mensajes publicados
47
Estado
Miembro
-
yg_be Mensajes publicados 23437 Fecha de registro Estado Colaborador Última intervención -
yg_be Mensajes publicados 23437 Fecha de registro Estado Colaborador Última intervención -
Hola a todas y a todos,
Me encuentro ante un pequeño problema de programación:
Tengo que recuperar datos de un archivo (A) para volcarlos en un archivo de seguimiento (B). Hasta aquí, nada fuera de lo común...
Lo que pasa es que la cantidad y el posicionamiento de las columnas de (A) varían de una semana a otra, lo que me impide recuperar mis datos con facilidad.
Me preguntaba si sería posible "indexar" las columnas no por su posición en la hoja (A=1, B=2, ...) sino por una prueba de nombre a buscar en una fila. De hecho, cada columna tiene un "título" que nunca variará y todos esos títulos permanecerán invariables en la misma fila.
¿Tendríais alguna pista para mi problema?
Agradecido de antemano a la comunidad.
Cordialmente.
Me encuentro ante un pequeño problema de programación:
Tengo que recuperar datos de un archivo (A) para volcarlos en un archivo de seguimiento (B). Hasta aquí, nada fuera de lo común...
Lo que pasa es que la cantidad y el posicionamiento de las columnas de (A) varían de una semana a otra, lo que me impide recuperar mis datos con facilidad.
Me preguntaba si sería posible "indexar" las columnas no por su posición en la hoja (A=1, B=2, ...) sino por una prueba de nombre a buscar en una fila. De hecho, cada columna tiene un "título" que nunca variará y todos esos títulos permanecerán invariables en la misma fila.
¿Tendríais alguna pista para mi problema?
Agradecido de antemano a la comunidad.
Cordialmente.
Enlaces relacionados:
- [VBA Excel] número de celdas no vacías en una columna
- Código VBA Excel: Función para sumar una columna.
- Suma de una columna ListView
- cambiar el color de una celda de una columna en listview
- Insertar comillas dobles en los datos de una columna de Excel (2007)
- Seleccionar una columna según el nombre del primer valor
19 respuestas
-
Hola,
Puedes buscar como indicas utilizando lo que se llama una variable:
sub variable
dim columna, linea as variant
línea = 2
columna = 1
do while cells (línea, columna) <> "título" ' mientras la celda ubicada en la fila 2 y la columna 1 es diferente de título
columna = columna + 1 'añadimos 1 a columna para pasar a la columna siguiente
loop
a = magbox("La columna donde se encuentra título es " & columna)-
Hola,
Veo esta publicación con 9 años de retraso, pero aun así lo intento :-)
Probé tu código y funciona muy bien. Sin embargo, obtener la info en un msgbox no me interesa. Lo que quiero es que en cuanto encuentre mi "título" mediante el bucle, seleccione toda la columna para que pueda renombrarla?
dim columna, linea as variant
linea = 1
columna = 1
do while cells (linea, columna) <> "titre" ' mientras la celda en la fila 2 y columna 1 es diferente de título
columna = columna +1 'sumar 1 a la columna para pasar a la columna siguiente
loop
a=magbox("La columna donde se encuentra título es " & columna)Les agradezco su ayuda
Atentamente
-
-
Hola Mélanie,
Gracias por el truco.
Pero, ¿me permitirá activar esta columna para que pueda recuperar los datos que estoy buscando?
Gracias de antemano. -
Hola,
puedes hacer lo que quieras reutilizando la variable columna después, por ejemplo:
sub variable
dim columna, línea as variant
sheets("Feuille1").select
línea = 2
columna = 1
do while cells(línea, columna) <> "título" ' mientras la celda situada en la fila 2 y la columna 1 sea diferente de título
columna = columna + 1 'añade 1 a columna para pasar a la siguiente columna
loop
columns(columna).copy sheets("Feuille2").columns(1)
' copia la columna definida en la variable columna a la columna 1 de la hoja2
end sub -
Hola,
Gracias por la información.
Sin embargo, me preguntaba si sería posible “almacenar” varias columnas definidas por tantos “títulos” y luego usarlas en una macro de este tipo:
Immeuble = 'datos a recuperar en la columna almacenada nº1
Workbooks(A_wbook).Activate
Sheets("XX").Activate 'a definir en función del nombre de la hoja objetivo
Cells(Liga, 1) = Immeuble 'a definir en función del número de la columna objetivo
Workbooks(B_wbook).Activate
Adresse = 'datos a recuperar en la columna almacenada nº2
Workbooks(A_wbook).Activate
Sheets("XX").Activate 'a definir en función del nombre de la hoja objetivo
Cells(Liga, 1) = Immeuble 'a definir en función del número de la columna objetivo
Workbooks(B_wbook).Activate
Etc...
Sabiendo que los Wbooks A y B ya están definidos, así como los rangos de las filas a completar.
Gracias de nuevo por tu ayuda valiosa. -
Hola,
puedes hacer que todo funcione así.
Me parece correcto. -
Ok, intentaré algo durante el día.
Por cierto, ¿crees que es necesario pasar por una copia de seguridad "tampon" obligatoria de las columnas como lo programabas más arriba, o es posible almacenarlas "en memoria" y así llamarlas sobre la marcha?
Si es así, ¿podrías aclararme el procedimiento a seguir?
Una vez más, gracias por tu ayuda. -
Hola, Te propongo una pequeña variante... Un código que nombra todas las columnas en función del contenido de la fila de título:
Sub NommeColonnes() Dim intCol As Integer, intDrCol As Integer, byLig As Byte 'El número de la fila que contiene los títulos: byLig = 3 'El número de la última columna cuya fila "byLig" no está vacía: intDrCol = Cells(byLig, Cells.Columns.Count).End(xlToLeft).Column 'Bucle de la primera columna (Columna A) a la última (calculada arriba) For intCol = 1 To intDrCol ActiveWorkbook.Names.Add Name:=Cells(byLig, intCol).Value, RefersTo:= "&=" & ActiveSheet.Name & "!" & Columns(intCol).Address Next intCol End Sub
< i>Nota: la fila de títulos aquí es la fila 3, a adaptar. Luego, para tu copiar-pegar, basta indicar el nombre de la columna a copiar... Ejemplo de copiar-pegar la columna llamada Magie hacia la hoja Feuil2 columna A:Sub CopieColle() Range("Magie").Copy Sheets("Feuil2").Range("A1") End Sub-- Cordialmente, Franck -
Gracias por el código, pero no creo que sea adecuado para mi situación...
Sin embargo, al revisar tus publicaciones anteriores me surge la siguiente pregunta:
¿Es posible que tu código siguiente pueda buscar varios "títulos" en diferentes columnas de una misma fila antes de copiar el contenido de cada una de ellas a la hoja siguiente?
Porque si entiendo bien tu código, solo es posible buscar un único título que se define en la variable de columna.
Lo que intento adaptar no funciona (varias estructuras similares seguidas buscando títulos diferentes y pegando su contenido en otra hoja)
sub variable
dim columna, linea as variant
sheets("Hoja1").select
línea = 2
columna = 1
do while cells (línea, columna) <> "titulo" ' mientras la celda situada en la línea 2 y columna 1 es distinta de título
columna = columna +1 'sumo 1 a columna para pasar a la columna siguiente
loop
columns(columna).copy sheets("Hoja2").columns(1)
' copia la columna definida en la variable columna en la hoja2 columna 1
end sub
¿Crees que es posible?
Si es así, ¿tendrías alguna idea que puedas proponer (como seguramente tu nivel de codificación es limitado...)
Gracias de antemano por tu esfuerzo.-
-
Sí, exactamente.
Como ya he dicho, no tengo un alto nivel de codificación, pero al parecer el código no funciona.
De hecho, cuando cambio el título "Magie" por el que busco, no aparece ningún copiar-pegar.
Lo que me parece extraño es que la primera macro no define en ningún punto el mismo título (en este caso "Magie").
Eso probablemente venga de ahí... pero quizá me equivoque. -
Sí.
La primera macro que te di (Sub NommeColonnes()) renombra las columnas según el contenido de su tercera fila (byLig = 3).
Ya puedes empezar cambiando el número de la fila de títulos a byLig = 2...
Después, de los dos procedimientos que te di, el objetivo es convertirlos en uno solo.
Por ejemplo:Sub MaMacroAMoi()
Dim intCol As Integer, intDrCol As Integer, byLig As Byte
Dim tabNomsCol(), intIndic As Integer, intColcolle As Integer
'---------- PROCEDIMIENTO DE NOMBRADO DE COLUMNAS -----------
'El número de la fila que contiene los títulos :
byLig = 2 'A ADAPTAR!!!!
'El número de la última columna cuya fila "byLig" no está vacía :
intDrCol = Cells(byLig, Cells.Columns.Count).End(xlToLeft).Column
'Bucle desde la primera columna (Columna A) hasta la última (calculada arriba)
For intCol = 1 To intDrCol
'renombra las columnas
ActiveWorkbook.Names.Add Name:=Cells(byLig, intCol).Value, RefersTo:="=" & ActiveSheet.Name & "! " & Columns(intCol).Address
Next intCol
'---------------FIN NOMBRADO DE COLUMNAS-----------------------
'--------------DEFINICIÓN DE LAS COLUMNAS A COPIAR------------
'A ADAPTAR colocando los nombres de encabezados.........
tabNomsCol = Array("NOM", "Prénom", "Adresse", "Téléphone", "Ville", "CodePostal", "Mail")
'--------------COPIAR-PEGAR ---------------------------------
'A partir de qué columna pegar los datos :
intColcolle = 2 'A ADAPTAR aquí pegamos a partir de la columna B
For intIndic = 0 To UBound(tabNomsCol)
Range(tabNomsCol(intIndic)).Copy Sheets("Feuil2").Cells(1, intColcolle)
intColcolle = intColcolle + 1
Next intIndic
End Sub
Este código tiene, sin embargo, una desventaja... No puede haber un espacio ni un guion al inicio de las palabras en tus encabezados....
Pero ya sabes, no es más que un ejemplo, puedes seguir perfectamente con el código de Melanie si te parece mejor...
-
-
¿No habría algo que reemplazar en el código siguiente?
RefersTo:="=" & ActiveSheet.Name & "!"
Creo haber pasado por alto algo en este punto, ¿una referencia al título y a la hoja quizá?
Gracias de antemano por vuestra ayuda. -
Acabo de intentar adaptar tuMacro a mis necesidades y, lamentablemente, me encuentro con esto:
Error de ejecución '1004':
El nombre ingresado no es válido.
¿Es por esto que tengo "títulos" que contienen espacios en su nombre?
Muchas gracias de nuevo por toda tu ayuda. -
Sí, también debe evitar empezar con un espacio. Si el espacio está en el centro del título, como en "Id PM", no hay problema en separar por palabras; lo importante es que no haya un espacio inicial al inicio del texto.
-
Gracias por tu precisión. ¿Es entonces posible que al inicio del código se pueda emplear una maniobra desviada consistente en reemplazar todos los espacios por una secuencia de caracteres (por ejemplo, " " por "$$")?
-
Con este tipo de código, por ejemplo:
' Reemplazo de los espacios
Sub Remplacement()
Cells.Replace What:=" ", Replacement:="$$", LookAt:=xlPart, SearchOrder _
:=xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False
End Sub
Gracias por sus consejos expertos. -
Puedes usar Replace.
Por ejemplo, reemplazando los espacios por nada (es decir, eliminándolos):Replace(bla bla, " ", "")
ello daría en tu código:Sub MaMacroAMoi()
Dim intCol As Integer, intDrCol As Integer, byLig As Byte
Dim tabNomsCol(), intIndic As Integer, intColcolle As Integer
'---------- PROCÉDURE DE NOMMAGE DES COLONNES-----------
'El número de la fila que contiene los títulos :
byLig = 2 'A ADAPTAR!!!!
'El número de la última columna cuya fila "byLig" no está vacía :
intDrCol = Cells(byLig, Cells.Columns.Count).End(xlToLeft).Column
'Bucle de la 1ª columna (Columna A) a la última (calculada arriba)
For intCol = 1 To intDrCol
'renombra las columnas
ActiveWorkbook.Names.Add Name:=Replace(Cells(byLig, intCol).Value, " ", ""), RefersTo:="=" & ActiveSheet.Name & "!" & Columns(intCol).Address
Next intCol
'---------------FIN NOMMAGE COLONNES-----------------------
'--------------DÉFINITION DES COLONNES A COPIER------------
'A ADAPTAR colocando los nombres de las cabeceras.........
tabNomsCol = Array("NOM", "Prénom", "Adresse", "Téléphone", "Ville", "Code Postal", "Mail")
'--------------COPIE-COLLE ---------------------------------
'A partir de qué columna pegar los datos :
intColcolle = 2 'A ADAPTAR aquí se pega desde la columna B
For intIndic = 0 To UBound(tabNomsCol)
Range(tabNomsCol(intIndic)).Copy Sheets("Feuil2").Cells(1, intColcolle)
intColcolle = intColcolle + 1
Next intIndic
End Sub
Sin embargo, al copiar y pegar, no hay que olvidar que los nombres dados a nuestras columnas no tienen espacios... Así que hay dos opciones, ya sea los tenemos en cuenta en su definición:tabNomsCol = Array("NOM", "Prénom", "Adresse", "Téléphone", "Ville", "Code Postal", "Mail")a reemplazar por :
tabNomsCol = Array("NOM", "Prénom", "Adresse", "Téléphone", "Ville", "CodePostal", "Mail")
O bien se vuelven a usar Replace en la línea (no lo he probado) :Range(tabNomsCol(intIndic)).Copy Sheets("Feuil2").Cells(1, intColcolle)Como esto :Range(Replace(tabNomsCol(intIndic), " ", "")).Copy Sheets("Feuil2").Cells(1, intColcolle)
Lo ideal, por supuesto, al final de la macro, es eliminar todos estos nombres del libro para obtener un código limpio.
Tenga cuidado también con el uso de ActiveSheet.Name. No me gusta mucho... Lo ideal sería declarar, al inicio del procedimiento, una variable de tipo Worksheet donde se almacenaría el objeto "hoja" correspondiente a la copia...
Volveré mañana para terminar esto si quieres.
--
Atentamente,
Franck -
Hola,
Como regalo, aquí tienes el procedimiento completo:
1- Lee bien los comentarios,
2- adáptalo a lo indicado
3- Prueba
Sub MaMacroAMoi()
Dim intCol As Integer, intDrCol As Integer, byLig As Byte
Dim tabNomsCol(), intIndic As Integer, intColcolle As Integer
Dim shFeuilAcopier As Worksheet, shFeuilOuColler As Worksheet
'On définit la feuille contenant les données à copier
Set shFeuilAcopier = Worksheets("Feuil1") '*********A ADAPTAR********
'On définit la feuille ou coller les données
Set shFeuilOuColler = Workbooks("Blabla").Worksheets("Machin") '*********A ADAPTAR******** Nécessite que le classeur blabla soit ouvert!
With shFeuilAcopier 'On travaille Avec la feuille à copier
'---------- PROCÉDURE DE NOMMAGE DES COLONNES-----------
'Le numéro de la ligne contenant les titres :
byLig = 2 '*********A ADAPTAR********
'Le numéro de la dernière colonne dont la ligne "byLig" est non-vide :
'Note : ne pas oublier le point devant Cells car il se rattache à shFeuilAcopier
intDrCol = .Cells(byLig, Cells.Columns.Count).End(xlToLeft).Column
'Boucle de la 1ère colonne (Colonne A) à la dernière (calculée ci-dessus)
For intCol = 1 To intDrCol
'Si la cellule en ligne 2 n'est pas vide :
If .Cells(byLig, intCol) <> "" Then
'Nomme les colonnes (Définir un nom)
ActiveWorkbook.Names.Add Name:=Replace(.Cells(byLig, intCol).Value, " ", ""), _
RefersTo:="=" & shFeuilAcopier.Name & "!" & .Columns(intCol).Address
End If
Next intCol
'---------------FIN NOMMAGE COLONNES-----------------------
'--------------DÉFINITION DES COLONNES A COPIER------------
tabNomsCol = Array("NOM", "Prénom", "Adresse", "Téléphone", "Ville", "Code Postal", "Mail") '*********A ADAPTAR********
'--------------FIN DEFINITION------------------------------
'--------------COPIE-COLLE --------------------------------
'A partir de qu'elle colonne coller les données :
intColcolle = 2 '*********A ADAPTAR******** ici on colle à partir de la colonne B
For intIndic = 0 To UBound(tabNomsCol)
.Range(Replace(tabNomsCol(intIndic), " ", "")).Copy shFeuilOuColler.Cells(1, intColcolle)
intColcolle = intColcolle + 1
Next intIndic
'---------------FIN COPIE-COLLE----------------------------
'-------------SUPPRESSION DES NOMS-------------------------
For intCol = 1 To intDrCol
'Si la cellule en ligne 2 n'est pas vide :
If .Cells(byLig, intCol) <> "" Then
.Range(Replace(.Cells(byLig, intCol).Value, " ", "")).Name.Delete
End If
Next
'-------------FIN SUPPRESSION NOMS-------------------------
End With
End Sub
--
Cordialement,
Franck -
Muchas gracias por este trabajo tan profesional.
Pero resulta que he adaptado vuestro código a mi situación y al siguiente código:
Set shFeuilOuColler = Workbooks("Vannes").Worksheets("Feuil1")
Me responde que el índice no pertenece a la selección... ¿qué debo deducir?
Gracias por vuestra ayuda.-
Supongamos que:
1- el libro llamado "Vannes" no está abierto
2- la hoja "Feuil1" no existe en el libro "Vannes"
3- que solo hay un pequeño error de ortografía en el nombre del libro o de la hoja (a veces un espacio se esconde discretamente en los nombres)
4- Es posible que Excel quiera que especifices la extensión del libro .xls, .xlsx
5- etc...
-
-
Está bien, me acabo de apañar...
Por otro lado, creo que mi línea de título tiene demasiados caracteres especiales (p. ej.: N° / guiones, así como apostrofes) y, por ello, estas líneas de código no se validan:
ActiveWorkbook.Names.Add Name:=Replace(.Cells(byLig, intCol).Value, " ", ""), _
RefersTo:="=" & shFeuilAcopier.Name & "!" & .Columns(intCol).Address
¿Es posible acumular los valores de "replace" uno tras otro?-
En este caso, recomiendo utilizar una función de validación de nombres.
Esta función debe colocarse en el mismo módulo que la subrutina principal. No es obligatorio, pero será más sencillo. Le pasaremos por parámetro todas las cabeceras. La función realizará todas las sustituciones que quieras que haga y devolverá un nombre "válido" en la subrutina principal.
El código de esta función:Function ValideNom(ByVal Nom As String)
Puedes añadir lo que quieras en este código...
Nom = Replace(Nom, "°", "")
Nom = Replace(Nom, "'", "")
Nom = Replace(Nom, " ", "")
Nom = Replace(Nom, "/", "")
Nom = Replace(Nom, "", "")
Nom = Replace(Nom, ":", "")
Nom = Replace(Nom, "*", "")
Nom = Replace(Nom, "?", "")
Nom = Replace(Nom, "|", "")
Nom = Replace(Nom, "<", "")
Nom = Replace(Nom, ">", "")
ValideNom = Nom
End Function
La llamada a la función:
A continuación, la llamada a la función se realizará en la subrutina principal como esto:
ActiveWorkbook.Names.Add Name:=ValideNom(.Cells(byLig, intCol).Value)
o :
.Range(ValideNom(tabNomsCol(intIndic))).Copy
o aún :
.Range(ValideNom(.Cells(byLig, intCol).Value)).Name.Delete
El código de la Sub principal :Sub MaMacroAMoi()
Dim intCol As Integer, intDrCol As Integer, byLig As Byte
Dim tabNomsCol(), intIndic As Integer, intColcolle As Integer
Dim shFeuilAcopier As Worksheet, shFeuilOuColler As Worksheet
'On définit la feuille contenant les données à copier
Set shFeuilAcopier = Worksheets("Feuil1") '*********A ADAPTER********
'On définit la feuille ou coller les données
Set shFeuilOuColler = Workbooks("Blabla.xls").Worksheets("Machin") '*********A ADAPTER******** Nécessite que le classeur blabla soit ouvert!
With shFeuilAcopier 'On travaille Avec la feuille à copier
'---------- PROCÉDURE DE NOMMAGE DES COLONNES-----------
'Le numéro de la ligne contenant les titres :
byLig = 2 '*********A ADAPTER********
'Le numéro de la dernière colonne dont la ligne "byLig" est non-vide :
'Note : ne pas oublier le point devant Cells car il se rattache à shFeuilAcopier
intDrCol = .Cells(byLig, Cells.Columns.Count).End(xlToLeft).Column
'Boucle de la 1ère colonne (Colonne A) à la dernière (calculée ci-dessus)
For intCol = 1 To intDrCol
'Si la cellule en ligne 2 n'est pas vide :
If .Cells(byLig, intCol) <> "" Then
'Nomme les colonnes (Définir un nom)
ActiveWorkbook.Names.Add Name:=ValideNom(.Cells(byLig, intCol).Value), _
RefersTo:="=" & shFeuilAcopier.Name & "!" & .Columns(intCol).Address
End If
Next intCol
'---------------FIN NOMMAGE COLONNES-----------------------
'--------------DÉFINITION DES COLONNES A COPIER------------
tabNomsCol = Array("NOM", "Prénom", "Adresse", "Téléphone", "Ville", "Code Postal", "Mail") '*********A ADAPTER********
'--------------FIN DEFINITION------------------------------
'--------------COPIE-COLLE --------------------------------
'A partir de qu'elle colonne coller les données :
intColcolle = 2 '*********A ADAPTER******** ici on colle à partir de la colonne B
For intIndic = 0 To UBound(tabNomsCol)
.Range(ValideNom(tabNomsCol(intIndic))).Copy shFeuilOuColler.Cells(1, intColcolle)
intColcolle = intColcolle + 1
Next intIndic
'---------------FIN COPIE-COLLE----------------------------
'-------------SUPPRESSION DES NOMS-------------------------
For intCol = 1 To intDrCol
'Si la cellule en ligne 2 n'est pas vide :
If .Cells(byLig, intCol) <> "" Then
.Range(ValideNom(.Cells(byLig, intCol).Value)).Name.Delete
End If
Next
'-------------FIN SUPPRESSION NOMS-------------------------
End With
End Sub
-
-
Hola,
Eeeeh...
¿Gracias???
--
Atentamente,
Franck -
Hola,
Disculpa por el tiempo de mi respuesta.
Un gran agradecimiento por tu trabajo, que funciona perfectamente bien, y nuevamente gracias por tu paciencia con los no iniciados (como yo...)
@+