Macro para copiar fila completa basado en información de columna especifica
Tengo varias hojas, necesito una macro que me copie en una hoja todas las filas de todas las hojas donde la columna PROYECTO diga ARROYO TORO.
El problema es que la columna PROYECTO varia de posición a veces es la E otras la D…
No se si me entienden.
2 Respuestas
Hice una macro que hasta donde entiendo hace lo que necesitas. Si te fijas, tu pregunta es bastante corta, por ejemplo, no dices en que hoja quieres pegar los datos, tampoco dices que contienen las otras hojas a parte de la columna D o E.
Así que, para que mi macro funcione, deben cumplirse varias reglas (por ahora, hasta que des mas detalles):
1- Que la hoja donde se van a pegar los datos sea la primera hoja (index 1) ya que mi código va a recorrer todas las hojas del libro empezando por la 2da (osea la 1 no se toma en cuenta en el bucle porque se supone que es la hoja destino)
2- La columna A de cada hoja debe tener siempre algún dato. Esto se puede cambiar a cualquier otra columna, pero almenos una columna en cada tabla NO debería admitir espacios en blanco.
Este es el código:
Sub RecorrerHojas() With Application .ScreenUpdating = False .DisplayStatusBar = False .Calculation = xlCalculationManual End With Const PROYECTO As String = "PROYECTO" Const ARROYOTORO As String = "ARROYO TORO" Dim HojaDestino As Worksheet: Set HojaDestino = Sheets("Sheet1") Dim shtCount As Integer: shtCount = ThisWorkbook.Sheets.Count Dim ColCount As Integer, sht As Integer, ProjPos As Integer, uF As Long, nF As Long, dstCol As Integer Dim rCell As Range, rRng As Range For sht = 2 To shtCount ColCount = Sheets(sht).Cells(1, Sheets(sht).Columns.Count).End(xlToLeft).Column If ColCount > 1 Then ProjPos = Sheets(sht).Cells(1, 1).EntireRow.Find(What:=PROYECTO, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByColumns, SearchDirection:=xlNext, MatchCase:=False).Column uF = Sheets(sht).Cells(Rows.Count, ProjPos).End(xlUp).Row Set rRng = Sheets(sht).Range(Sheets(sht).Cells(2, ProjPos), Sheets(sht).Cells(uF, ProjPos)) For Each rCell In rRng.Cells If rCell.Value = ARROYOTORO Then uF = HojaDestino.Range("A" & Rows.Count).End(xlUp).Row + 1 For dstCol = 1 To ColCount HojaDestino.Cells(uF, dstCol).Value = Sheets(sht).Cells(rCell.Row, dstCol).Value Next dstCol End If Next rCell Set rRng = Nothing End If Next sht With Application .ScreenUpdating = True .DisplayStatusBar = True .Calculation = xlCalculationAutomatic End With End Sub
El codigo es ejecutable desde cualquier hoja, no necesitas estar en la hoja 1 para correrlo. Siempre va a apuntar a la hoja 1 como la hija destino.
No es necesario usar Copy & Paste (yo lo evito lo mas que pueda)
¿Cómo funciona?:
1-Recorre cada hoja desde la 2 hasta la ultima
2-En cada una busca en la fila 1 (en el encabezado) la palabra PROYECTO y define su columna
3-Una vez encontrada la columna, busca la ultima fila con datos en esa columna
4-Define ese rango, y dentro de ese rango busca cada vez que aparece ARROYO TORO
5-Cada vez que lo encuentre, lo manda a la hoja 1, a la próxima fila vacía.
Revisando el código me doy cuenta que, si en alguna hoja el encabezado "PROYECTO" no existe, da error. Este código corrige ese error:
Sub RecorrerHojas() With Application .ScreenUpdating = False .DisplayStatusBar = False .Calculation = xlCalculationManual End With Const PROYECTO As String = "PROYECTO" Dim ProjRng As Range Const ARROYOTORO As String = "ARROYO TORO" Dim HojaDestino As Worksheet: Set HojaDestino = Sheets("Sheet1") Dim shtCount As Integer: shtCount = ThisWorkbook.Sheets.Count Dim ColCount As Integer, sht As Integer, ProjPos As Integer, uF As Long, dstCol As Integer Dim rCell As Range, rRng As Range For sht = 2 To shtCount ColCount = Sheets(sht).Cells(1, Sheets(sht).Columns.Count).End(xlToLeft).Column If ColCount > 1 Then Set ProjRng = Sheets(sht).Cells(1, 1).EntireRow.Find(What:=PROYECTO, SearchOrder:=xlByColumns) If Not ProjRng Is Nothing Then ProjPos = ProjRng.Column uF = Sheets(sht).Cells(Rows.Count, ProjPos).End(xlUp).Row Set rRng = Sheets(sht).Range(Sheets(sht).Cells(2, ProjPos), Sheets(sht).Cells(uF, ProjPos)) For Each rCell In rRng.Cells If rCell.Value = ARROYOTORO Then uF = HojaDestino.Range("A" & Rows.Count).End(xlUp).Row + 1 For dstCol = 1 To ColCount HojaDestino.Cells(uF, dstCol).Value = Sheets(sht).Cells(rCell.Row, dstCol).Value Next dstCol End If Next rCell Set rRng = Nothing End If End If Next sht With Application .ScreenUpdating = True .DisplayStatusBar = True .Calculation = xlCalculationAutomatic End With End Sub
Best
¿Has ajustado los rangos? El código es general, tu debes adaptarlo a tu libro.
Va a ser mejor si lo subes a Google Drive y lo compartes, así los otros expertos también pueden ver el libro y colaborar.
A una nueva que se genere, te explico, lo que deseo es de ese archivo, que tiene como 100 hojas, sacar las filas que en la columna proyecto diga arroyo toro, el ejemplo tiene pocas hojas pero en realidad son como 100
No hay consistencia en la estructura de las hojas, además de que la columna PROYECTO varia, también la fila del encabezado varia. Con el ejemplo que me mandaste he logrado hacer lo que necesitas, pero si en el libro real siguen variando más cosas, esto se convertirá en un espagueti.
Mira lo que obtiene la macro:
¿Es así como lo quieres?
Ese es el problema que no hay una uniformidad, consistencia. Si de esa manera esta bien así en tabla, ponme esa macro por favor en el archivo que subí a la red o cópiala para correrla aquí en el archivo mio a ver que pasa
Son dos macros, pero solo debes ejecutar la primera la que se llama RecorrerHojas. Pega todo esto en el modulo:
Sub RecorrerHojas() With Application .ScreenUpdating = False .DisplayStatusBar = False .Calculation = xlCalculationManual End With Call CrearHojaDestino Const FECHA As String = "FECHA" Dim FechaRng As Range Const PROYECTO As String = "PROYECTO" Dim ProjRng As Range Const ARROYOTORO As String = "ARROYO TORO" Dim HojaDestino As Worksheet: Set HojaDestino = Sheets("HojaDestino") HojaDestino.Cells.ClearContents Dim shtCount As Integer: shtCount = ThisWorkbook.Sheets.Count Dim ColCount As Integer, sht As Integer, ProjPos As Integer, uF As Long, dstCol As Integer, FechaPos As Integer Dim rCell As Range, rRng As Range For sht = 2 To shtCount Set FechaRng = Sheets(sht).Range("A:A").Find(What:=FECHA, SearchOrder:=xlByRows) If Not FechaRng Is Nothing Then FechaPos = FechaRng.Row ColCount = Sheets(sht).Cells(FechaPos, Sheets(sht).Columns.Count).End(xlToLeft).Column Set ProjRng = Sheets(sht).Cells(FechaPos, 1).EntireRow.Find(What:=PROYECTO, SearchOrder:=xlByColumns) If Not ProjRng Is Nothing Then ProjPos = ProjRng.Column uF = Sheets(sht).Cells(Rows.Count, ProjPos).End(xlUp).Row Set rRng = Sheets(sht).Range(Sheets(sht).Cells(FechaPos, ProjPos), Sheets(sht).Cells(uF, ProjPos)) For Each rCell In rRng.Cells If rCell.Value = ARROYOTORO Then uF = HojaDestino.Range("A" & Rows.Count).End(xlUp).Row + 1 For dstCol = 1 To ColCount HojaDestino.Cells(uF, dstCol).Value = Sheets(sht).Cells(rCell.Row, dstCol).Value Next dstCol End If Next rCell Set rRng = Nothing End If End If Next sht With Application .ScreenUpdating = True .DisplayStatusBar = True .Calculation = xlCalculationAutomatic End With End Sub Sub CrearHojaDestino() Dim newSheetName As String Dim checkSheetName As String newSheetName = "HojaDestino" On Error Resume Next checkSheetName = Worksheets(newSheetName).Name If checkSheetName = "" Then Worksheets.Add.Name = newSheetName End If End Sub
Best
En la segunda macro, donde dice:
If checkSheetName = "" Then Worksheets.Add.Name = newSheetName End If
agrega esta linea:
ActiveSheet.Move Before:=ActiveWorkbook.Sheets(1)
de manera que quede así:
If checkSheetName = "" Then Worksheets.Add.Name = newSheetName ActiveSheet.Move Before:=ActiveWorkbook.Sheets(1) End If
Para que la hoja se ponga de primera, ya que dices que son como 100 hojas, para que no te vuelvas loco buscandola
- Compartir respuesta
Esta macro recorre todas las hojas descartando la hoja5, busca en estas la palabra proyecto e identifica la columna donde se encuentra por ejemplo si esta en la columna E entonces E sera igual a 5, si esta en DE, DE sera igual a 4, luego aplicando un filtrado usando el valor de la columna y la palabra Arroyo toro filtra los valores que va a copiar y los envía a la hoja5, ojo para eficientizar la macro el proceso para ti sera invisible, cuando la macro acabe ve a la hoja5
Sub filtrarycopiar() For Each HOJA In Worksheets NOMBRE = UCase(HOJA.Name) = "HOJA5" If NOMBRE Then Else Set DATOS = Sheets(HOJA.Name).Range("a1").CurrentRegion col = DATOS.Columns.Count columna = WorksheetFunction.Match("PROYECTO", DATOS.Rows(1), 0) DATOS.AutoFilter columna, "ARROYO TORO" DATOS.Offset(1).Resize(DATOS.Rows.Count - 1).Copy FILAS = Sheets("HOJA5").Range("A1").CurrentRegion.Rows.Count If FILAS = 1 Then Sheets("HOJA5").Range("A2").PasteSpecial If FILAS > 1 Then Sheets("HOJA5").Range("A2").Rows(FILAS).PasteSpecial DATOS.AutoFilter End If Next HOJA shhets("hoja5").select Set DATOS = Nothing End Sub
Hola,
Intente correrla pero no me funciona.
Da error en : columna = WorksheetFunction.Match("PROYECTO", DATOS.Rows(1), 0)
Si ya vi el problema tienes la referencia en la A12 mientras la macro trabaja sobre la referencia A1, prueba con esta macro, hace lo mismo que la otra solo que ya esta adaptada a tus datos, el resultado es este, en la hoja 5 cin importar en que columna este colocada la palabra proyecto la macro la buscara y sobre esa columna en especifico hara un filtrado y copiado de datos hacia la hoja 5
Sub FILTRARYCOPIAR() For Each HOJA In Worksheets NOMBRE = HOJA.Name If UCase(NOMBRE) <> "HOJA5" Then FILAS = Sheets(NOMBRE).Range("A" & Rows.Count).End(xlUp).Row Set DATOS = Sheets(NOMBRE).Range("A12").Resize(FILAS, 24) With DATOS INDICE = WorksheetFunction.Match("PROYECTO", .Rows(1), 0) .AutoFilter INDICE, "ARROYO TORO" .Offset(1).Copy FILAS = Sheets("HOJA5").Range("A1").CurrentRegion.Rows.Count If FILAS = 1 Then Sheets("HOJA5").Range("A1").PasteSpecial If FILAS > 1 Then Sheets("HOJA5").Range("A1").Rows(FILAS + 1).PasteSpecial DATOS.AutoFilter End With End If Next HOJA Set DATOS = Nothing End Sub
- Compartir respuesta
Ya subió el archivo, me puso el link en una respuesta. Echale un vistazo tu.. Está muy enredado. - Andy Machin