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.
 
                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
 
        2 respuestas más de otros expertos
 
                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
 
         
                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
 
        