Reducir macro que copia datos de una libro a otro
Podrían ayudarme a optimizar una macro que me copia datos de un libro a otro, ahora repito la sentencia para cada hoja, pero se ralentiza mucho.
Puedes utilizar las áreas de un rango para pasar todo el rango de celdas, en lugar de hacerlo por celda.
Si en lugar de copiar y pegar, pasas los valores, el proceso será más rápido.
Revisa esta opción:
Sub MetodoAbrirLibro_2()
Dim wbOr As Workbook, wbDes As Workbook
Dim ar As Range
Dim i As Long
'
Set wbOr = ThisWorkbook
Set wbDes = Workbooks.Open("C:\Users\jctorres\Desktop\Programaciones vba\Partes presenciales\C2020-0136_Carga_Horas (1)2.xls")
With wbOr.Sheets("EPYC1")
wbDes.Sheets("Personal").Range("A8:F108").Value = .Range("A8:F108").Value
wbDes.Sheets("Personal").Range("G3").Value = .Range("F2").Value
wbDes.Sheets("Personal").Range("H3").Value = .Range("I2").Value
End With
'
For i = 1 To 8
With wbOr.Sheets("EPYC" & i)
For Each ar In Union(.Range("H2"), .Range("H3"), .Range("l2"), .Range("G8:H108"), .Range("J8:K108"), .Range("M8:M108")).Areas
wbDes.Sheets("OT" & i).Range(ar.Address).Value = ar.Value
Next ar
End With
Next i
End Sub
- Compartir respuesta
2 respuestas más de otros expertos
La macro se puede reducir con el uso de un bucle For ... Next, de este modo:
Sub MetodoAbrirLibro()
Dim rngCopy As Range, rngCopyOT2 As Range, rngOT1 As Range, rngOT2 As Range, cel As Range, cel2 As Range, adres$
Dim wbOr As Workbook, wbDes As Workbook
Dim nombre As String, Ruta As String
Application.ScreenUpdating = False
Set wbOr = ThisWorkbook
Set wbDes = Workbooks.Open("C:\Users\jctorres\Desktop\Programaciones vba\Partes presenciales\C2020-0136_Carga_Horas (1)2.xls")
With wbOr.Sheets("EPYC1")
. Range("A8:F108"). Copy
WbDes. Sheets("Personal"). Range("A8:F108"). PasteSpecial xlPasteValues
. Range("F2"). Copy
WbDes. Sheets("Personal"). Range("G3"). PasteSpecial xlPasteValues
. Range("I2"). Copy
WbDes. Sheets("Personal"). Range("H3"). PasteSpecial xlPasteValues
End With
For i = 1 To 8
nbreHo1 = "EPYC" & i
nbreHo2 = "OT" & i
With wbOr.Sheets(nbreHo1)
Set rngOT1 = .Range("A:U")
Set rngCopy = Intersect(rngOT1, Union(.Range("H2"), .Range("H3"), .Range("l2"), .Range("G8:H108"), .Range("J8:K108"), .Range("M8:M108")))
For Each cel In rngCopy
wbDes.Sheets(nbreHo2).Range(cel.adres) = cel.Value
Next cel
End With
End With
Next i
Application.CutCopyMode = False
End SubObserva que para la hoja EPYC1 la primer parte se mantiene y solo entra al bucle desde la definición del rango 'rngOT1'
Ahora, el tiempo de demora también se debe al modo de copiar/pegar, que vas haciendo celda x celda. Pero no puedo hacer cambios allí ya que desconozco cómo es cada rango (con formato, con fórmulas, combinadas o no, etc).
Debes copiar el código TAL COMO se te envía:
wbDes.Sheets(nbreHo2).Range(cel.adres) = cel.Value
Cuando se utiliza una variable para indicar el nombre de un libro u hoja, NO va entre comillas.
Sdos!
Si está configurada la opción de exigir la declaración de variables (generalmente ya no la utilizamos), al inicio debes agregar también estas líneas:
Dim i as Byte
Dim nbreHo1 as String, nbreHo2 as String
Sdos. Recuerda que tienes 2 opciones para votar: Buena o Excelente ;)
Elsa
Cópiala tal cual:
Sub MetodoAbrirLibro()
Dim rngCopy As Range, rngOT1 As Range, cel As Range, cel2 As Range, adres$
Dim wbOr As Workbook, wbDes As Workbook
Dim nombre As String, Ruta As String
Dim i As Byte
Dim nbreHo1 As String, nbreHo2 As String
Application.ScreenUpdating = False
Set wbOr = ThisWorkbook
Set wbDes = Workbooks.Open("C:\Users\jctorres\Desktop\Programaciones vba\Partes presenciales\C2020-0136_Carga_Horas (1)2.xls")
With wbOr.Sheets("EPYC1")
. Range("A8:F108"). Copy
WbDes. Sheets("Personal"). Range("A8:F108"). PasteSpecial xlPasteValues
. Range("F2"). Copy
WbDes. Sheets("Personal"). Range("G3"). PasteSpecial xlPasteValues
. Range("I2"). Copy
WbDes. Sheets("Personal"). Range("H3"). PasteSpecial xlPasteValues
End With
For i = 1 To 8
nbreHo1 = "EPYC" & i
nbreHo2 = "OT" & i
With wbOr.Sheets(nbreHo1)
Set rngOT1 = .Range("A:U")
Set rngCopy = Intersect(rngOT1, Union(.Range("H2"), .Range("H3"), .Range("l2"), .Range("G8:H108"), .Range("J8:K108"), .Range("M8:M108")))
For Each cel In rngCopy
adres = cel.Address
wbDes.Sheets(nbreHo2).Range(adres).FormulaR1C1 = cel.Value
Next cel
End With
End With
Next i
Application.CutCopyMode = False
End SubSi te da algún error presioná el botón DEpurar y tomá captura de imagen del Editor para que vea en qué línea se detiene y el mensaje que te devuelve.
Sdos!
Ahora si que funciona, pero no sigue igual de lento. Sera lo que dijiste sobre copiar y pegar los datos en las celdas.
Ahora si que funciona, pero no sigue igual de lento... je je... Esas fueron tus palabras y por eso no continué el tema ;)
Reducir la macro fue la solicitud... y no me detuve a mejorar el pase ya que eso requería, quizás, de mayores aclaraciones. Como bien dice el otro experto, siempre es más ágil copiar por rangos o áreas que fila por fila.
Pero a veces los usuarios quieren solo valores (sin fórmulas), otras veces quieren mantener, o no, los formatos... por lo que el tema requería de mayores aclaraciones. Qué bueno que lo tuyo era un pase simple nomás.
Sdos!
- Compartir respuesta
Sub MetodoAbrirLibro()
Dim rngCopy As Range, rngCopyOT2 As Range, rngOT1 As Range, rngOT2 As Range, cel As Range, cel2 As Range, adres$
Dim wbOr As Workbook, wbDes As Workbook
Dim nombre As String, Ruta As String
Application.ScreenUpdating = False
Set wbOr = ThisWorkbook
Set wbDes = Workbooks.Open("C:\Users\jctorres\Desktop\Programaciones vba\Partes presenciales\C2020-0136_Carga_Horas (1)2.xls")
With wbOr.Sheets("EPYC1")
. Range("A8:F108"). Copy
WbDes. Sheets("Personal"). Range("A8:F108"). PasteSpecial xlPasteValues
. Range("F2"). Copy
WbDes. Sheets("Personal"). Range("G3"). PasteSpecial xlPasteValues
. Range("I2"). Copy
WbDes. Sheets("Personal"). Range("H3"). PasteSpecial xlPasteValues
Set rngOT1 = .Range("A:U")
Set rngCopy = Intersect(rngOT1, Union(.Range("H2"), .Range("H3"), .Range("l2"), .Range("G8:H108"), .Range("J8:K108"), .Range("M8:M108")))
For Each cel In rngCopy
adres = cel.Address
wbDes.Sheets("OT1").Range(adres).FormulaR1C1 = cel.Value
Next cel
End With
With wbOr.Sheets("EPYC2")
Set rngOT2 = .Range("A:U")
Set rngCopy = Intersect(rngOT2, Union(.Range("H2"), .Range("H3"), .Range("l2"), .Range("G8:H108"), .Range("J8:K108"), .Range("M8:M108")))
For Each cel In rngCopy
adres = cel.Address
wbDes.Sheets("OT2").Range(adres).FormulaR1C1 = cel.Value
Next cel
End With
With wbOr.Sheets("EPYC3")
Set rngOT2 = .Range("A:U")
Set rngCopy = Intersect(rngOT2, Union(.Range("H2"), .Range("H3"), .Range("l2"), .Range("G8:H108"), .Range("J8:K108"), .Range("M8:M108")))
For Each cel In rngCopy
adres = cel.Address
wbDes.Sheets("OT3").Range(adres).FormulaR1C1 = cel.Value
Next cel
End With
With wbOr.Sheets("EPYC4")
Set rngOT2 = .Range("A:U")
Set rngCopy = Intersect(rngOT2, Union(.Range("H2"), .Range("H3"), .Range("l2"), .Range("G8:H108"), .Range("J8:K108"), .Range("M8:M108")))
For Each cel In rngCopy
adres = cel.Address
wbDes.Sheets("OT4").Range(adres).FormulaR1C1 = cel.Value
Next cel
End With
With wbOr.Sheets("EPYC5")
Set rngOT2 = .Range("A:U")
Set rngCopy = Intersect(rngOT2, Union(.Range("H2"), .Range("H3"), .Range("l2"), .Range("G8:H108"), .Range("J8:K108"), .Range("M8:M108")))
For Each cel In rngCopy
adres = cel.Address
wbDes.Sheets("OT5").Range(adres).FormulaR1C1 = cel.Value
Next cel
End With
With wbOr.Sheets("EPYC6")
Set rngOT2 = .Range("A:U")
Set rngCopy = Intersect(rngOT2, Union(.Range("H2"), .Range("H3"), .Range("l2"), .Range("G8:H108"), .Range("J8:K108"), .Range("M8:M108")))
For Each cel In rngCopy
adres = cel.Address
wbDes.Sheets("OT6").Range(adres).FormulaR1C1 = cel.Value
Next cel
End With
With wbOr.Sheets("EPYC7")
Set rngOT2 = .Range("A:U")
Set rngCopy = Intersect(rngOT2, Union(.Range("H2"), .Range("H3"), .Range("l2"), .Range("G8:H108"), .Range("J8:K108"), .Range("M8:M108")))
For Each cel In rngCopy
adres = cel.Address
wbDes.Sheets("OT7").Range(adres).FormulaR1C1 = cel.Value
Next cel
End With
With wbOr.Sheets("EPYC8")
Set rngOT2 = .Range("A:U")
Set rngCopy = Intersect(rngOT2, Union(.Range("H2"), .Range("H3"), .Range("l2"), .Range("G8:H108"), .Range("J8:K108"), .Range("M8:M108")))
For Each cel In rngCopy
adres = cel.Address
wbDes.Sheets("OT8").Range(adres).FormulaR1C1 = cel.Value
Next cel
End With
Application.CutCopyMode = False
End Sub
El codigo
- Compartir respuesta
