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 Sub
Observa 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 Sub
Si 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