Cómo copiar y pegar celdas con VBA

Copiar y pegar valores en Excel es una tarea muy común por lo que será casi inevitable que en algún momento necesites hacer un copiado y pegado de celdas dentro de una macro. Para copiar y pegar celdas con VBA haremos uso de los métodos Copy y PasteSpecial del objeto Range.

Copiar y pegar celdas en la misma hoja

Si los valores serán pegados dentro de la misma hoja, entonces puedes utilizar un código como el siguiente:

Cómo copiar y pegar celdas con VBA

Este código copiara el contenido de la celda A1 y lo pegará en la celda B1. El argumento xlPasteAll ocasiona que se pegue todo el contenido en la celda B1incluyendo el formato de la celda y las fórmulas.  Finalmente la instrucción Application.CutCopyMode = False hace que Excel de por finalizada la acción de copiado y pegado.

Copiar y pegar los valores de una celda con VBA

Si en lugar de copiar todo el contenido de una celda deseas copiar solamente los valores, entonces debes hacer una pequeña modificación en el argumento del método PasteSpecial de la siguiente manera:

Copiar los valores de una celda usando VBA

Observa que ahora el argumento utilizado es xlPasteValues el cual ocasionará que se peguen solamente los valores de las celdas copiadas.

Copiar y pegar una fila o columna con VBA

Es posible copiar y pegar columnas con VBA si modificamos el rango indicado en el método Range. Por ejemplo, para copiar la columna A en la columna B utiliza el siguiente código:

Cómo copiar una columna de Excel con VBA

Si en lugar de copiar la columna A, necesitas copiar la fila 1 y pegarla en la fila 2, entonces puedes usar el siguiente código:

Cómo copiar y pegar una fila usando VBA

Copiar y pegar a otra hoja

Para pegar los valores a una hoja diferente, solamente debemos especificar la hoja destino haciendo uso del objeto Worksheets de la siguiente manera:

Copiar y pegar celdas a otra hoja de Excel con VBA

Ahora bien, si tanto la hoja origen como la hoja destino son diferentes a la hoja activa, entonces será necesario indicar el nombre de la hoja tanto al momento de copiar como al momento de pegar. En el siguiente código estoy suponiendo que el botón que ejecuta la macro se encuentra en la Hoja1 y copiaré todo el contenido de la celda A1 de la Hoja2 hacia la celda B1 de la Hoja3:

Copiar rangos o celdas con VBA

Método abreviado para copiar celdas con VBA

En todos los ejemplos anteriores he utilizado el método PasteSpecial para pegar los valores en las celdas destino. Una ventaja de ese método es que puedo elegir si deseo copiar el contenido completo de la celda (xlPasteAll) o solo sus valores (xlPasteValues) sin embargo existe otro método alterno en caso de querer copiar siempre todo el contenido de una celda. Observa el siguiente código:

Método abreviado para copiar celdas con VBA

Este código copia todo el contenido de la celda A1 (incluyendo fórmulas y formato) a la celda B1 de la misma hoja. El argumento Destination es el que nos permite especificar el rango en el cual se pegarán los valores. A continuación puedes observar, en el mismo bloque de código, diferentes ejemplos utilizando este mismo método abreviado para copiar celdas con VBA:

Ejemplos de código VBA para copiar celdas en Excel

Como has visto en los ejemplos de este artículo, el primer método que utilizamos nos ofrece una gran flexibilidad a través del método PasteSpecial  el cual nos permite elegir si deseamos pegar todo el contenido de una celda o solo sus valores. Pero si estás seguro de querer copiar siempre todo el contenido de las celdas, entonces el método abreviado, utilizando el argumento Destination del método Copy, será suficiente para lograr nuestro objetivo.

Ahora ya sabes cómo copiar y pegar celdas con VBA y solo es cuestión de que elijas el método adecuado a tus necesidades.

Artículos relacionados
Introducción a las macros en Excel

43 pensamientos en “Cómo copiar y pegar celdas con VBA

  1. David Franco

    Buenos dias, felicitaciones por este articulo. Tengo una pregunta, digamos que tengo una tabla cuyos encabezados sea: Identificacion, nombre, cargo que desempeña, ventas por vendedor. Y quiero que en la medida que ingrese los datos por cada fila o registro estos se copien en otra hoja. El problema seria que digamos, el primer registro quedaria copiado en la fila 2 de la hoja dos, al ingresar otro registro este se ubique en la fila 3 de la hoja dos y asi sucesivamente. Que complemento para la macro me sugieres? Gracias.

    1. Moisés Ortíz Autor

      Hola David, no me queda claro el problema. Tú controlas tanto el origen como el destino por lo que no necesariamente los registros serán copiados a la misma fila.
      De todos modos, si quieres crear una especie de bucle para hacer el copiado, te recomiendo utilizar la intrucción Range.Cells(1, 1) para indicar la celda destino de manera que tengas el control por medio de código de la fila a la cual se copiarán los valores.

  2. Julio

    Gracias por esta clase que es de gran utilidad, sobre todo lo de la parte abreviada que no me la sabia.

  3. Alberto

    Hola Moises. Tengo semanas generando un reporte, he pasado por multiples problemas para conseguir lo que quiero y constantemente he recurrido a los foros encontrandome con la solucion a mis dudas, esto gracias a tus tutoriales. En esta ocasion no encuentro la solucion y por eso te solicito ayuda. Muchas gracias por todo desde ya… :D

    Tengo un reporte al que le agrege un combobox, esto de despliega una lista de modelos de algunos articulos. cuando elijo alguno de estos, automaticamente me aparece en la celda de enseguida el numero de parte que le corresponde. (en el rango estan todos ordenados uno al lado del otro) ejemplo de rango.

    todo ensta en la hoja 1

    todos los modelos estan en la columna “M” y todos los numeros de parte estan en la columna “N”.

    M1= atg560 azul N1=gh69-89562 1.1 (estos datos estan en el rango MODELOS).
    la lista desplegable esta en A1, cuando elijo el modelo= at560 azul, automaticamente me aparece su respectivo numero de parte gh69-89562 1.1 en la celda B1. Hasta alli estamos bien. Ahora, una vez elegido, debo darle la cantidad de produccion en la celda C1, esta cantidad quiero que se acumule cada vez que active una macro, pero quiero que se acumule en la celda O1 (despues del numero de parte) y si al otro dia activo de nuevo la macro, que se acumule en la celda P1, y al otro dia Q1 y asi sucesivamente. En otras palabras. que se acumule la produccion al lado derecho del numero de parte que le corresponda.

    Espero que me puedas ayudar. Gracias.

    1. Moisés Ortíz Autor

      Alberto, tu problema es complejo como para darte una solución en este comentario, pero tengo algunas recomendaciones para ti.

      1) Utiliza una variable “Global” para guardar el número de columna que contiene el último valor de producción. Una variable global se define en VBA con la palabra clave: Public.
      2) En el evento Workbook_BeforeClose guarda el valor de la variable global en alguna celda del libro de manera que puedas volver a leer su valor la próxima vez que abras el libro.
      3) En el evento Workbook_Open inicializa la variable Global leyendo de la celda donde guardaste su valor (punto 2).

      Obviamente, cada vez que ejecutas la macro deberás actualizar el valor de la variable global de manera que se guarde el último valor.

  4. Julieta

    Hola Moises,
    Estoy haciendo una macro para crear y nombrar una hoja segun el valor en una celda, por ejemplo tengo la celda en la que escribo “Clavo” y cuando tenga seleccionada la celda y lance mi macro tome en cuenta el valor “Clavo” para la creacion de la hoja y para nombrarla. El punto es que no consiguo tomar en cuenta el valor de la celda (soy nueva en Macros) intente con nombrehoja = Worksheets(“Product”).Range(ActivCell) pero creo que no tiene sentido
    Me podrias orientar?
    Gracias

      1. Julieta

        Hola Moises Creo que no supe explicar, la macro que crea las hojas yq lq tengo hecha, lo que quiero es poder borrar un hoja, me explico mejor: Tengo tres hojas: 1 hoja con con una lista de todas las hojas en el archivo, 2 Una hoja con otra lista de las hojas a la que hago referencia en algunos calculos, 3 una Hoja que tiene un nombre que esta presente en las listas.
        Cree un macro que borra con un If pero pôngo if”clavo” then borrar, lo que no me es util porque no siempre voy a querer borrrar clavo, lo aue auiero es que borre la hoja con el nombre de la celda activa, es decir si la celda activa es “clavo” borre clavo pero si es “tornillo” borre tornillo.
        Ahora bien la verdad es que no se como tomar en cuenta el valor de la celda activa. Aqui te dejo mi macro:
        Sub DeleteSheet()

        ‘ DeleteSheet Macro
        Dim hoja As Worksheet, hojaprincipal As Worksheet
        Set hojaprincipal = Sheets(“Product”)
        Application.DisplayAlerts = False

        For Each hoja In Sheets

        If hoja.Name = “Miller” (aqui quisiera poner celda activa de la hoja principal) Then
        hoja.Delete

        End If
        Next hoja

        End Sub

        1. Moisés Ortíz Autor

          Hola Julieta, el valor de la celda activa lo obtienes con la siguiente instrucción:
          ActiveCell.Value

          En tu macro quedaría de la siguiente manera:

          For Each hoja In Sheets
          If hoja.Name = ActiveCell.Value Then
          hoja.Delete
          End If

          1. Julieta

            Muchas Gracias!!! Es algo simple pero no lo habia pensado. Por cierto muy buen blog he aprendido mucho de Excel

  5. Xabier

    Hola Moises,
    Estoy trabajando con una tabla compuesta de un formulario, una tabla que recoge los datos y a su vez alimenta varios formatos de impresión.
    El modo de copiado de datos desde el formulario que he venido utilizando hasta ahora era el copiado del contenido mediante Selection.Insert Shift:=xlDown de manera que cada entrada me cree una fila nueva arriba de la tabla para poder tenerla actualizada de forma temporal.
    Mejorando la tabla, he añadido listas a dos campos mediante Validación de Datos y han empezado los problemas; el comando que utilizo me copia el formato completo de la celda y en las celdas con lista me copia la lista completa con el valor seleccionado.
    Para evitar esto he probado con el consejo que das en este artículo pero he perdido la opción de que me desplace las celdas existentes hacia abajo. Ahora me lo escribe en la celda que contenía la entrada anterior por lo que ya no se almacenan.
    Además, sigue copiando el formato de lista aunque ahora solo presenta el valor que selecciono en el formulario y el resto la muestra en blanco.
    Es evidente que no lo estoy haciendo bien y, como soy autodidacta en esto, me he bloqueado y no sé por dónde seguir. ¿Puedes ayudarme para que se copie solo el valor sin lista en una celda nueva creada sobre las anteriores?
    El código que venia utilizando hasta ahora es este:
    Sheets(“ENTRADA”).Select
    Range(“C2″).Select
    Application.CutCopyMode = False
    Selection.Copy
    Sheets(“DATOS”).Select
    Range(“B2″).Select
    Selection.Insert Shift:=xlDown

    Muchas gracias

    1. Moisés Ortíz Autor

      Hola Xabier, el método que utilizas y el método presentado en este artículo son diferentes. Como bien lo mencionas, al utilizar el método Insert obtienes el beneficio de desplazar las celdas hacia abajo. Si este comportamiento lo deseas conservar, entonces debes continuar haciendo una inserción en lugar de un simple pegado.

      Por otro lado, suponinedo que la cedal C2 tiene la validación de datos, para copiar y pegar tanto el funcionamineto como el valor seleccioado a la celda B2, puedes utilizar el siguiente código:
      Range(“C2″).Copy
      Range(“B2″).PasteSpecial xlPasteAll

  6. jorge

    muchas gracias por tu explicacion te agradezco lo que haces por los que vamos aprendiendo.

  7. nithael

    Hola,
    estoy aprendiendo o intentando aprender vb y llevo todo el día buscando codigo para copiar celdas de una hoja a otra, los que encontré son eternos comparado con tu simple instrucción “destination”, aun no lo puedo creer que sea tan sencillo, gracias. Está explicado muy claro en los ejemplos, muchas veces la gente se pierde decorando sus instrucciones e incluyendo programación mas compleja para controlar “posibles errores” y otras derivadas. Para los que estamos aprendiendo, nos vale mas lo sencillo y si se complica seguir buscando… Gracias por partir del origen de verdad.
    Saludos

  8. Gustavo

    Hola Moises:
    Quisiera que me ayudes con una macro para aumentar por ejemplo un 25% fijo a todos los precios de mis artículos.

    Los precios de los artículos están en una columna “PRECIO” y como tengo mas de 500 productos pues quisiera poner ejecutar una macro para ello.

    soy nuevito en excel y este blog es mi tutor favorito… mil gracias

    1. Moisés Ortíz Autor

      Hola Gustavo, creo que una macro sería la solución más compleja. Es suficiente con multiplicar la columna “PRECIO” por 1.25 y obtendrás el nuevo precio.
      Suponiendo que el precio del primer artículo está en la celda A2, coloca la siguiente fórmula en la celda B2 (u otra columna vacía):
      =A2*1.25

      Después copia la fórmula de la columna B hacia abajo, puede ser con un doble clic en la esquina inferior derecha de la celda, y en menos de 30 segundos habrás calculado los nuevos precios de todos tus artículos.

  9. René

    Gracias por compartir su conocimiento

  10. Victor Luis

    Holas, tengo una pregunta: Al copiar celdas de una hoja a otra, es necesario indicar que el área de Destino sea similar al area de Origen? como el ejemplo:
    [1] Worksheets(“Hoja2”).Range(“AB10:AY39″). Copy Destination:= Worksheets(“Hoja3”).Range(“B7″)

    [2] Worksheets(“Hoja2”).Range(“AB10:AY39″). Copy Destination:= Worksheets(“Hoja3”).Range(“B7:Y36″)

    Qué método es correcto?

    1. Moisés Ortíz Autor

      Hola Victor, Ambas instrucciones que has proporcionado funcionarán correctamente. Por otro lado, no es necesario indicar un área similar a la de origen, los datos siempre serán pegados a partir de la primera celda indicada (B7).

      1. Irving Fdez

        Hola Moises, gracias por tus invaluables aportes.
        Con respecto a esta pregunta.
        ¿Hay alguna forma de que el destino de los datos no sea fijo?
        ¿Puedo definir en la macro que el destino sea la celda que este seleccionada en el momento de correr la macro?
        Gracias, saludos

        1. Moisés Ortíz Autor

          Hola Irving, por supuesto que puedes indicar que los datos sean pegados en la celda activa, solo debes utilizar el objeto ActiveCell para el argumento Destination por ejemplo:
          Destination:=ActiveCell

  11. Miguel Angel

    Mil gracias por tus aportes Moises.
    Me han ayudado mucho

  12. Natalia Quintero

    Hola Moisés,
    Tengo una duda y es la siguiente, estoy tratando de copiar algunos valores por celdas, el código que tengo es el siguiente, sin embargo el primer rango puede variar es decir puedo iniciar en la D14.. pero también podría colocar valores en la E15 y de ahi en adelante, existe alguna forma de yo decirle que a partir de la celda actual me copie hasta el rango 2?
    Sub Copiar()
    Range(“D14″).Select
    Selection.Copy
    Range(“E14:O14″).Select
    ActiveSheet.Paste
    End Sub

    Agradezco tu ayuda.

    1. Moisés Ortíz Autor

      Hola Natlia, puedes indicar la celda activa como el primer argumento del método Range:
      Range(ActiveCell, “C5″).Select

      Esta instrucción seleccionará el rango que inicia en la celda activa y termina en la celda C5. Si ademas quieres que se seleccione un número determinado de celdas por debajo de la celda activa, entonces puede utilizar el método Offset, por ejemplo:
      Range(ActiveCell, ActiveCell.Offset(5, 0)).Select

      Con esta modificación se seleccionarán siempre 5 celdas por debajo de la celda activa.

  13. Juan Pineda

    Hola Moisés !
    No tengo, en este momento pregunta que hacer, pero, quiero felicitarte por tu Blog. Me ha llamado la atención lo fácil de tus explicaciones a las dudas planteadas y como te responden los conectados a tu Blog.

    Desde Santiago de Chile.
    Un abrazo !
    Juanpi.

  14. Tony

    muy bueno la introduccion, bastante sencilla y clara.

    solo tengo una duda. si como cambia el range si deseas copiar de dos archivos excel distintos.
    ¿se debe especificar el nombre del archivo mas la pestaña cierto?

    Gracias de antemano por la respuesta.

    1. Moisés Ortíz Autor

      Hola Tony, en este caso no funcionará modificando el argumento del método Range.
      Es necesario utilizar Application.Workbooks.Open para abrir el segundo libro y después crear un objeto Workbook de manera que puedas hacer referencia a las hojas y celdas de dicho libro.

  15. Pili

    Genial! no sabes como me ayudo esta información. Gracias.

  16. Luz

    Muchas gracias por compartir tus conocimientos! Soy medio nueva en la programación con macros y estoy intentando programar una que me copie y pegue rangos pero variables, alguna idea que me puedas dar?
    Muchas gracia!

    1. Moisés Ortíz Autor

      Hola luz, si por “rangos variables” te refieres a que la macro pregunte el rango que debe ser copiado, entonces te recomiendo utilizar la instrucción InputBox que permite obtener una respuesta del usuario. Otra opción es utilizar el evento Worksheet_SelectionChange de manera que se inicie la copia después de hacer la selección de un rango.

  17. Luis Alvizures

    Hola, ¿como puedo hacer para que al copiar los datos de una hoja y pegarlos en otra, no se vea que se abre la hoja destino y pega los datos? es decir, me gustaria que se efectuara el procedimiento copiar en hoja 1 pegar en hoja 2 pero que no se viera el procedimiento, Muchas gracias de antemano y muchas felicitaciones por tan valiosos aportes…..

    1. Moisés Ortíz Autor

      Hola Luis, antes de iniciar la operación incluye la siguiente instrucción:
      Application.ScreenUpdating = False

      Al finalizar vuelve a colocar la propiedad en True y listo, Excel no mostrará en pantalla los pasos ejecutados.

  18. Luis Alvizures

    Muchas Gracias Por Tu ayuda, eso era justo lo que necesitaba.
    Saludos!!!

  19. honjoren

    Hola Moisés!
    Me ha venido de perlas este artículo. Muchas gracias, estoy aprendiendo mucho.
    Mi problema es que yo dispongo de 3 hojas de excel y quiero copiar el contenido de ellas en una hoja4, de manera que en ella se aniden las filas de las 3 primeras hojas.
    Para ello quiero agregar alguna instrucción para indicar el número de filas a copiar de cada hoja, por ejemplo encontrando el número de la primera fila vacía.

    ¿Qué código me sugieres?

    1. Moisés Ortíz Autor

      Hola honjoren, te sugiero utilizar la función CONTARA (COUNTA en inglés) desde tu macro para contar el número de celdas ya ocupadas dentro de una columna, por ejemplo:
      fila = Application.WorksheetFunction.CountA(Range(“A:A”)) + 1

      De esta manera el siguiente dato deberá ser insertado en el número fila contenido en la variable fila.

  20. Victor RV

    Venga venga… veamos, ya me revolvi un poco entre todos los ejemplos asi que me animare a preguntar…
    Tengo un libro donde tengo un listado de productos en una misma hoja, en la primera columna el nombre del producto, en las siguientes columnas viene el detalle o especificación. Por ejemplo: Color de frasco, Etiqueta, Color de tapa, color de producto, etc.
    El detalle es que requiero hacer por “normatividad” un documento de cada producto y lo estoy haciendo manualmente copiando y haciendo pegado especial Tranpondiendo a un libro en el cual tengo una macro para que me lo guarde el documento con el nombre y codigo del producto.
    Se puede hacer un copiado de fila a partir de una celda activa hasta una columna determinada? y que lo pegue en el documento que necesito de modo vertical?

    1. Moisés Ortíz Autor

      Hola Víctor, por supuesto que es posible. De hecho puedes utilizar la misma función TRANSPONER desde VBA:
      Application.WorksheetFunction.Transpose

  21. Manuel Alfaro

    Estimado Moisés
    Agradecerte tu blog, y que pongas a disposición de los que sabemos menos o nada tus conocimientos. Por favor, como tendría que que hacer para copiar unas celdas de una hoja activa de un libro elquesea.xls, por ejemplo, hoja datos1, y que siempres son las mismas pero no correletavias, ejemplo A2, B4, H4, a otro libro que no está abierto, que se llamaría historico.xls, a la hoja Resumen, y celdas pues por ejemplo C1, C2, C3 y que lo cerrara, y siguiera abierto el libro del que copiamos,
    espero haberme explicado, seria algo así
    copy de hoja activa, celdas A2, B4, H4
    abre el libro destino, historico.xls, hoja Resumen
    Paste en C1, C2, C3, o en donde correponda, porque segun vamos pegando se desplazará hacia abajo para mantener los datos pegados anteriormente, es decir, si C1, C2, C3 estan ya ocupados con datos por un pegado anterior, pues seria la siguiente fila libre
    cierra el libro historico.xls
    y seguimos trabajando en el libro origen del copiado
    Lamento que el correo sea tan largo pero no se como decirlo mejor

    Muchas gracias de antemando

    1. Moisés Ortíz Autor

      Hola Manuel, puedes basarte en el siguiente código:

      Dim destino As Workbook
      Set destino = Workbooks.Open(“C:\historico.xls”)

      destino.Sheets(“Resumen”).Range(“C1″).Value = Range(“A2″).Value
      destino.Sheets(“Resumen”).Range(“C2″).Value = Range(“B4″).Value
      destino.Sheets(“Resumen”).Range(“C3″).Value = Range(“H4″).Value

      destino.Close

  22. martin

    hola moises te queria consultar por que estoy usando un macro que copia un rango de celdas de una hoja a otra
    Worksheets(“STOCK”).Range(Cells(FILA_STOCK, 1), Cells(FILA_STOCK, 4)).Copy
    Worksheets(“HISTORY”).Range(Cells(HISTORY_CONTADOR, 2), Cells(HISTORY_CONTADOR, 5)).PasteSpecial
    pero los dos me tiran error si antes no esta activa sus respectiva hojas yo ejecuto el macro desde la hojas ventas pero si no esta activa la hoja stock el primero me tira error y si luego si no paso a history la segunda también me tira error me podrias decir que puede ser desde ya muchas gracias

    1. Moisés Ortíz Autor

      Hola martin, tal vez algo tiene que ver las variables FILA_STOCK y HISTORY_CONTADOR. Prueba reemplazando estas variables por un número fijo a ver si sigues obteniendo el mismo error.
      Yo he hecho el mismo procedimiento, con un botón en la Hoja1, copio valores de la Hoja2 a la Hoja3 sin mayor problema.

  23. iago

    Hola ¡¡
    Soy nuevo en vba, igual mi pregunta es una tonteria, estoy creando un formulario en el cual me dandole a un botón me copia los datos a otra hoja. En esta hoja destino me los ordena por fecha, el problema q tengo es q si le doy al botón y tengo celdas sin datos me copia una celda en blanco. El objeto del formulario es q si hay casillas vacias no las copie. Alguna idea….GRACIAS…

    1. Moisés Ortíz Autor

      Hola iago, antes de hacer la copia debes comparar el valor de cada celda para saber si no está en blanco, por ejemplo:
      If(Range(“A1″).Value <> “”) Then
      ‘Copiar los datos
      End If