domingo, 17 de abril de 2011

VBA: Macro para crear y duplicar hojas en Excel.

En esta ocasión explicaré cómo usar una macro para crear y duplicar hojas en un Libro de Excel, en respuesta a la petición de un usuario:

...En la hoja 1, tengo una tabla con 10 valores diferentes (por mencionar un ejemplo)
En la hoja 2, tengo un formato prediseñado.
Lo que quiero hacer es que de manera automática, el valor 1, de la Hoja1, se pase a la Hoja 2 (en una celda en especifico)
El valor 2 de Hoja 1, se pase a la Hoja 3
El valor 3, Hoja1, se pase a la Hoja 4
Y asi sucesivamente.
OJO: Los 10 valores de la tabla, Hoja1, tienen que ser ilimitados (ya sea los 10 valores o 1000 valores)
OJO2: los valores son numéricos, texto y ambos
La cuestión es que necesito que todo sea automatizado.
Si yo ingreso 20 valores a la tabla, automáticamente, se abran las 20 Hojas nuevas, con los valores correspondientes...


Debemos tener claro cuál es nuestro objetivo, y es que desde un listado, al ejecutar nuestra macro, se dupliquen tantas hojas como valores tengamos en dicho listado, trasladando posteriormente a cada hoja duplicada nueva los valores correspondientes del listado original.
Nuestro punto de partida es el listado donde encontramos los registros desde donde obtendremos los valores para crear las hojas nuevas, y también de donde sacaremos los diferentes campos con los que rellenar estas nuevas hojas: Hoja 'origen'.


En otra hoja del fichero tenemos el modelo de plantilla a replicar para cada registro: Hoja 'modelo'.


La tarea consiste en elaborar un código VBA que a partir de la hoja donde se encuentra el modelo de la plantilla (Hoja 'modelo') la duplique y traslade, por orden, cada fila del listado de registros (Hoja 'origen').
Nuestro código VBA a incluir en un módulo del Explorador del proyecto dentro del Editor de VBA es:

Sub hojas()
Dim HojaOrigen As Worksheet, HojaNueva As Worksheet
Set HojaOrigen = Sheets("origen")

'para recorrer los 11 registros del listado
For i = 1 To 11
'desactivamos la actualización/refresco de pantalla
Application.ScreenUpdating = False

'duplicamos la Hoja 'modelo'
Sheets("modelo").Copy after:=Worksheets(Worksheets.Count)
Set HojaNueva = Sheets(Worksheets.Count)
nombrehoja = Worksheets("origen").Cells(7 + i, 4).Value
'damos nombre a la hoja con el valor de la celda D7+i
HojaNueva.Name = nombrehoja

'activamos la actualización/refresco de pantalla
Application.ScreenUpdating = True

'trasladamos el valor de la celda ID
HojaOrigen.Cells(7 + i, 4).Copy
HojaNueva.Cells(2, 8).PasteSpecial Paste:=xlValues
'trasladamos el valor de la celda Num folio
HojaOrigen.Cells(7 + i, 1).Copy
HojaNueva.Cells(5, 7).PasteSpecial Paste:=xlValues
'trasladamos el valor de la celda fecha
HojaOrigen.Cells(3, 6).Copy
HojaNueva.Cells(5, 8).PasteSpecial Paste:=xlValues
'trasladamos el valor de la celda ejemplo
HojaOrigen.Cells(3, 5).Copy
HojaNueva.Cells(5, 4).PasteSpecial Paste:=xlValues
'trasladamos el valor de la celda IDU (Di)
HojaOrigen.Cells(7 + i, 4).Copy
HojaNueva.Cells(9, 5).PasteSpecial Paste:=xlValues
'trasladamos el valor de la celda ODU (Ei)
HojaOrigen.Cells(7 + i, 5).Copy
HojaNueva.Cells(10, 5).PasteSpecial Paste:=xlValues
'trasladamos el valor de la celda LNB (Fi)
HojaOrigen.Cells(7 + i, 6).Copy
HojaNueva.Cells(11, 5).PasteSpecial Paste:=xlValues

'limpiamos el portapapeles
Application.CutCopyMode = False
Next i
End Sub


Si asignamos la macro Hojas() creada a una autoforma, con el texto 'Generar ODS', que tenemos localizada en la Hoja 'origen', y ejecutamos dicho código, veremos el resultado:

58 comentarios:

  1. Si solamente se va a copiar el valor de las celdas en vez de esto:
    HojaOrigen.Cells(7 + i, 6).Copy
    HojaNueva.Cells(11, 5).PasteSpecial Paste:=xlValues

    recomiendo utilizar esta sintaxis:
    HojaNueva.Cells(11, 5).Value = HojaOrigen.Cells(7 + i, 6).Value

    De esta manera evitamos utilizar el portapapeles y la ejecución resulta más rápida.

    ResponderEliminar
  2. 'para recorrer los 11 registros del listado
    For i = 1 To 11
    ""
    Next i

    Pero y si los registros fuesen variables?, es decir pueden ser 11 como pueden ser 22.. como se podría hacer en ese caso?

    SaludoS!!!

    ResponderEliminar
  3. Hola Francis75,
    podrías hacer
    For i=1 to variable
    definiendo previamente el valor de esa variable, bien en fución del valor de una celda o dentro de la misma macro, a través de Inputbox o cualquier otra instrucción... dependiendo de cuáles pudieran ser esas opciones (11, 22, etc).
    Si tienes alguna duda concreta, envíame tu ejemplo a
    excelforo@gmail.com

    Un saludo

    ResponderEliminar
  4. Excelente, muy buena entrada Ismael.

    Saludos.

    ResponderEliminar
  5. Ismael buena tarde tedras o podras publicar este ejemplo en archivo de Excel. estoy haciendo un archivo parecido y necesito saber como agregarlo a mi macro para que funcione al 100% soy nuevo con macros te agradezco mucho saludos desde mexico.

    ResponderEliminar
    Respuestas
    1. Hola Orlando,
      lamentablemente ya no cuento con ese ejemplo.. es algo viejo, y por circunstancias lo he perdido.
      Pero sólo sigue las indicaciones y copia y pega el código de la macro, puedes guiarte por las imágenes y por el vídeo para determinar las relaciones y referencias sobre las dos hojas de cálculo...

      Lo siento. Mucha suerte!
      Un cordial saludo

      Eliminar
  6. Hola Ismael,
    Arme el formato tal cual la imagen y jalo tal cual lo expones en tu planteamiento, solo un detalle habrá alguna forma para que no sea necesario indicarle en el código VBA cuantos datos son? por ejemplo en tu ejercicio esta:
    for i = 1 to 11
    pregunto esto porque en mi lista a veces ingreso desde 0 a 80 datos dependiendo el numero (en el caso particular de mi ejercicio) de personas que ingresan tiempo extra. si no hay algún problema puedo escribirte a tu correo para poder resolver mejor mi duda y pueda mandarte mi ejercicio te agradezco y estamos en contacto saludos desde poza rica Veracruz mexico.

    ResponderEliminar
    Respuestas
    1. Hola Orlando,
      si claro, sólo define una variable que determine cuál es la fila del último registro.
      Por ejemplo,
      Dim ultfla as Long
      ultfila= Range("D" & Rows.Count).end(xlup).Row

      luego en el código reemplaza el 11 por 'ultfila'
      For i = 1 To ultfila

      Saludos

      Eliminar
    2. hola Ismael,
      Va de maravilla solo como un pequeño detalle también le genera hoja a la fila siguiente vacía
      ej. si tengo 10 datos genera 11 (esta ultima coloca el nombre modelo (2) porque la fila 11 esta vacia). el siguiente código es el de mi ejercicio podrias indicarme como lo coloco y donde para poder realizar lo mismo que tu ejemplo?
      en mi ejercicio la celda de donde quiero comenzar a sacar los datos son AI10 (LO QUE EQUIVALE EN EL TUYO A D8) y estos datos sustraídos quiero pegarlos en una celda combinada llamada CB10 como coloco tu código en el mio para que funcione? gracias y estamos en contacto
      código de mi ejercicio
      Sub Crear_Hojas()
      Dim iX As Long
      Dim Lista As Range
      Dim HojaOrigen As Worksheet, HojaNueva As Worksheet
      Set HojaOrigen = Sheets("03 Consolidado")


      On Error GoTo Cancelar
      Set Lista = Application.InputBox(prompt:="Selecciona el rango de FICHAS", _
      Title:="Lista de Fichas", Type:=8)
      Application.ScreenUpdating = False
      For iX = Lista.Count To 1 Step -1
      If checar_hoja(Lista(iX)) = False Then
      Sheets("04 Formato_Blanco").Copy after:=ActiveWorkbook.Sheets(Sheets.Count)
      End If
      Next iX

      Sheets("03 Consolidado").Activate
      Sheets("03 Consolidado").Select
      Sheets("03 Consolidado").Move Before:=Sheets(3)
      Application.ScreenUpdating = True

      Cancelar:
      End Sub

      Eliminar
    3. Hola Orlando, si te fijas en el ejemplo del post, en la fila 06. tenemos:
      For i = 1 To 11
      'desactivamos la actualización/refresco de pantalla
      Application.ScreenUpdating = False
      'duplicamos la Hoja 'modelo'
      Sheets("modelo").Copy after:=Worksheets(Worksheets.Count)
      Set HojaNueva = Sheets(Worksheets.Count)
      'FIJATE EN LA LÍNEA SIGUIENTE
      nombrehoja = Worksheets("origen").Cells(7 + i, 4).Value
      'damos nombre a la hoja con el valor de la celda D7+i
      HojaNueva.Name = nombrehoja

      como ves en la línea remarcada en negrita ajusto con el i del recorrido la celda que me interesa, sumándole 7
      .Cells(7 + i, 4)
      celda (7+1,4) equivale a la celda D8
      celda (7+2,4) equivale a la celda D)
      etc

      Saludos

      Eliminar
  7. Hola Ismael,
    Con la noticia de que ya jala copia mi formato las veces que tengo datos ingresados, pero también me crea una hoja de mas con el nombre de "04 Formato_Blanco (2)", como hacerle para que no me cree esta utima hoja, asi quedo mi código:

    Sub Crear_Hojas()
    Dim HojaOrigen As Worksheet, HojaNueva As Worksheet
    Set HojaOrigen = Sheets("03 Consolidado")
    Dim ultfla As Long
    ultfila = Range("AI" & Rows.Count).End(xlUp).Row

    On Error GoTo Cancelar

    For i = 1 To ultfila
    'desactivamos la actualización/refresco de pantalla
    Application.ScreenUpdating = False
    'duplicamos la Hoja 'modelo'
    Sheets("04 Formato_Blanco").Copy after:=Worksheets(Worksheets.Count)
    Set HojaNueva = Sheets(Worksheets.Count)
    'damos nombre a la hoja con el valor de la celda D7+i
    nombrehoja = Worksheets("03 Consolidado").Cells(9 + i, 35).value
    HojaNueva.Name = nombrehoja
    'activamos la actualización/refresco de pantalla
    Application.ScreenUpdating = True
    'trasladamos el valor de la celda ID
    HojaOrigen.Cells(9 + i, 35).Copy
    HojaNueva.Cells(10, 80).PasteSpecial Paste:=xlValues
    'limpiamos el portapapeles
    Application.CutCopyMode = False
    Next i

    Sheets("03 Consolidado").Activate
    Sheets("03 Consolidado").Select
    Sheets("03 Consolidado").Move Before:=Sheets(3)
    Application.ScreenUpdating = True

    Cancelar:
    End Sub

    gracias y excelente tarde saludos

    ResponderEliminar
    Respuestas
    1. Hola Orlando,
      desconozco la distribución de tus datos, pero la instrucción que te dí en el anterior comentario era orientativo, quiero decir, que es susceptible de algún ajuste.
      Por ejemplo, si tus datos empiezan en A2 y terminan en A100, la variable ultfila devolverá=10, y tu loop irá desde 9+1 hasta 100..
      es decir, debes ajustar el número de fila con el número de datos reales que tengas, aplicando alguna suma o resta...

      No es un problema de la acciones, si no de la definición correcta de la variable.
      Slds

      Eliminar
  8. Hola Ismael buena tarde desde México:

    Mi comentario es basado a que con tu macro funciona muy bien solo con el detalle que me crea siempre una hoja mas (en este caso una hoja de la ultima fila vacia). Por ejemplo:
    si yo ingreso mis datos desde la celda a10 a la celda a14 con los datos
    a10 = a
    a11=b
    a12=c
    a13=d
    a14=e
    la macro me crea 5 hojas (nombradas con las letras anteriores) y una hoja mas llamada "04 Formato_Blanco(2)" (esta es mi hoja modelo) porque toma el valor de referencia de la celda a15(pero como esta vacia le asigna el valor de la hoja modelo).

    MI PREGUNTA ES: como hacerle para que no cree esa ultima hoja nombrada desde una celda vacia. te agradezco saludos y estamos en contacto.

    ResponderEliminar
    Respuestas
    1. Hola Orlando,
      como te indicaba en un comentario anterior la clave es tener claro hasta donde llegan tus datos y como los ajustas en la variable.
      Si tienes datos hasta la fila 14
      y haces tu bucle

      ....
      For i = 1 To ultfila
      ....
      nombrehoja = Worksheets("03 Consolidado").Cells(9 + i, 35).value
      ....
      primero irá a la celda AI10, luego AI11, AI12, AI13,AI14,AI15,AI16,AI17,AI18,AI19,AI20,AI21,AI22 y AI23
      es decir, intentará recorrer 14 celdas!! y no las 5 que tienes.
      Por tanto debes ajustar tu recorrido, con:
      For i = 1 To ultfila - 9

      para que sólo llegue de la fila 10 a la 14, es decir, .Cells(9 + i, 35).value desde la celda 9+1 hasta la celda 9+ (14-9)

      Saludos

      Eliminar
  9. Ismael saludos.
    Tengo una consulta que hacerte tendras algún otro medio para contactarme contigo correo celular numero te lo agradecería, urge mas o menor espero entenderme.

    Tengo una hoja llamada consolidado donde tengo 50 datos (numéricos) en la columna a, necesito buscar esos datos en las 50 hojas que tengo y copiar ciertas celdas de la hoja donde encuentre el dato (supongamos que encuentra el dato en la hoja 23 en la celda b1, yo quiero copiar la celda g7 (donde tengo otro valor numérico)) y pegarlo de regreso en la hoja "consolidado" a partir de la celda c1, c2,c3 y asi sucesivamente hasta localiza los 50 datos.
    Nota: LA CANTIDAD DE DATOS ES VARIABLE, PUEDEN SER DESDE 1 HASTA 80 MAXIMO.
    espero puedas apoyarme ya que necesito terminar esta base de datos para poder realizar los soportes de tiempo extra de trabajadores.
    saludos desde mexico excelente noche espero noticias

    gracias totales

    ResponderEliminar
    Respuestas
    1. Hola Orlando,
      para este tipo de desarrollos a medida mejor lee las Normas de Uso, punto 4.
      Si te interesa puedes adjuntar un fichero de ejemplo (o el real) con las explicaciones oportunas.

      un saludo

      Eliminar
  10. Buenas tardes, partiendo de este mismo supuesto, lo que necesito es que a partir de que los datos que se carguen en una "hoja base" se vean reflejados en una hoja...

    ResponderEliminar
    Respuestas
    1. Hola Rodolfo,
      si desde una hoja base tienes que completar un única hoja 'destino'/informe bastará con que apliques fórmulas de búsqueda (BUSCARV, BUSCAR,...) desde el informe hacia la hoja base.
      Saludos cordiales

      Eliminar
    2. Gracias por el concepto ....

      Eliminar
  11. Ojo con el hardcode... les propongo este código para que consideren el título "crear y duplicar hojas"

    Sub Lista()
    ' Seleccionar celda B3, *primera línea de datos*.
    Sheets("Listado").Select
    Range("B3").Select
    Dim cedula As String
    Dim nombre As Variant
    ' Configurar el bucle Do para que se detenga al llegar a una celda vacía.
    Do Until IsEmpty(ActiveCell)
    ' Inserte el código aquí.
    cedula = Selection.Value
    Sheets("modelo").Select
    Range("D11").Select
    ActiveCell.FormulaR1C1 = cedula

    Range("D10").Select
    nombre = Selection.Value
    Sheets("modelo").Select
    Sheets("modelo").Copy After:=Sheets(3)
    Sheets("modelo (2)").Select
    Sheets("modelo (2)").Name = nombre(1, 1)
    Cells.Select
    Selection.Copy
    Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
    :=False, Transpose:=False

    ' Bajar 1 fila de la ubicación actual.
    Sheets("Listado").Select
    ActiveCell.Offset(1, 0).Select
    Loop
    End Sub

    contiene 3 hojas
    Modelo: hoja con una plantilla a ser diligenciada, solo se debe cambiar el id del cliente y con buscarv cambia todos los demás datos.
    Datos: una hoja con la base de datos a ser consultada
    Listado: una hoja con un listado de ID's de clientes a ser generados empezando en B3

    espero comentarios y dudas al respecto.

    ResponderEliminar
    Respuestas
    1. Gracias William por el aporte...
      aunque no estoy de acuerdo con tu propuesta y afirmación de 'hardcode' y tu solución al respecto (casi idéntica).

      Seguro que el código es mejorable, sin duda, pero sólo se pretende exponer y explicar diferentes procedimientos...
      en este caso concreto, cómo duplicar una hoja y cambiarle el nombre; situación que en tu propuesta queda demasiado restringida, y desde mi perspectiva cerrada a modificaciones en el código.

      En todo caso, queda aquí tu propuesta para que cualquiera pueda implementarla.

      Un cordial saludo

      Eliminar
  12. Hola Ismael. El problema que me surge es que a mi el archivo de donde saco los datos me viene un orden de A1 a A11, la siguiente de B1 a B11 y así sucesivamente, y encima la cantidad es variable. Yo no entiendo mucho y la idea es automatizarme el proceso este que es bastante tedioso porque a veces son más de 140 hojas las que tengo que crear.
    Yo reemplazo donde dice "For i = 1 To 11" a "For 1 = A To Variable" y me selecciona el 1 y me pone todo el dato en rojo, ¿alguna idea de lo que pueda ser?

    ResponderEliminar
    Respuestas
    1. Hola Lucho,
      no sé si entendí bien el problema, pero para recorrer un rango de celdas 'bidimensional' (tipo A1:D11), puedes aplicar un bucle
      FOR EACH celda IN Range("A1:D11")
      ... resto de acciones
      NEXT celda

      Espero al menos te oriente.
      Saludos

      Eliminar
  13. Hola Ismael, modifique tu código para que me copiara desde un listado los nombres de varios clientes de los cuales no puedo determinar su cantidad, por lo que asigne la variable "ultfila" al FOR como lo indicaste y funciona de maravilla, el problema es que cuando se detiene en la ultima fila que esta vacía, me sale un error y me copia la hoja destino como copia(1),¿ Como hago para que se detenga en la ultima fila y no me genere el error?, agradezco que me puedas ayudar, mi código es totalmente idéntico al tuyo, no cambia en nada, gracias desde Colombia

    ResponderEliminar
    Respuestas
    1. Hola Carlos,
      podrías añadir un condicional IF..THEN para que si el valor fuera vacío saliera del bucle.. algo así (dentro del for...next)
      IF celda="" THEN exit for

      Espero haber entendido la cuestión.

      Saludos

      Eliminar
    2. Hola Ismael, te adjunto el código a como lo tengo, como veras solo modifique los nombres de las hojas "origen", "destino" y los rangos a donde quiero que me copie y pegue la información. Cuando se ejecuta la macro subraya la linea "HojaNueva.Name = nombrehoja" y un mensaje de alerta que dice, "Error en el método Name", me podrías indicar donde puedo ajustar el condicional, a que se debe este error o como lo puedo solucionar?
      Agradezco enormemente que me puedas ayudar. Saludos

      Sub CrearCompCam()
      Dim HojaOrigen As Worksheet, HojaNueva As Worksheet
      Set HojaOrigen = Sheets("comprocam")
      Dim ultfla As Long

      ultfila = Range("A" & Rows.Count).End(xlUp).Row

      'para recorrer los n registros del listado
      For i = 1 To ultfila
      'desactivamos la actualización/refresco de pantalla
      Application.ScreenUpdating = False

      'duplicamos la Hoja 'modelo'
      Sheets("COMPROC").Copy after:=Worksheets(Worksheets.Count)
      Set HojaNueva = Sheets(Worksheets.Count)
      nombrehoja = Worksheets("comprocam").Cells(1 + i, 1).Value
      'damos nombre a la hoja con el valor de la celda D7+i
      HojaNueva.Name = nombrehoja

      'activamos la actualización/refresco de pantalla
      Application.ScreenUpdating = True
      HojaOrigen.Cells(1 + i, 1).Copy
      HojaNueva.Cells(18, 8).PasteSpecial Paste:=xlValues
      HojaOrigen.Cells(1 + i, 2).Copy
      HojaNueva.Cells(18, 5).PasteSpecial Paste:=xlValues
      HojaOrigen.Cells(1 + i, 3).Copy
      HojaNueva.Cells(18, 6).PasteSpecial Paste:=xlValues
      HojaOrigen.Cells(1 + i, 4).Copy
      HojaNueva.Cells(18, 7).PasteSpecial Paste:=xlValues

      ' HojaOrigen.Cells.................
      'HojaNueva.Cells..................

      Application.CutCopyMode = False
      Next i
      End Sub

      Eliminar
    3. Aclaro que el error sale cuando termina de ejecutase la macro al encontrar la ultima fila vacía.

      Eliminar
    4. Hola Carlos,
      quizá el fallo está en que no ajustas la última fila.. por eso encuentra una fila vacía.
      Date cuenta que con UltFila consigues el número de fila último donde hay un registro (en el ejemplo del post es la fila 18), de hecho date cuenta que mi bucle va desde 1 hasta 11 por que quiero recorrer las filas de la 8 (7+1) a la 18 (7+11).. no sé si has tenido en cuenta esta situación...
      Sería mejor me enviaras el fichero a
      excelforo@gmail.com
      Saludos

      Eliminar
  14. Hola Ismael,
    ya te envie el archivo, agradezco en lo que me puedas ayudar

    ResponderEliminar
    Respuestas
    1. ;-)
      ya te contesté... el problema/solución es ajustar la ultifila en el bucle
      for i=1 to ultfila-1

      Un saludo

      Eliminar
    2. Mil gracias Ismael, la solucion a sido perfecta....Saluds

      Eliminar
    3. Gracias a sus comentarios pude resolver el problema.

      Eliminar
  15. Hola Ismael, te voy a molestar otravez, ya una vez solucionado lo anterior (gracias a tu ayuda), resulta que tengo varias hojas "origen" y varias hojas "destino" diferentes segun el tipo de informacion que lleve cada una, para las cuales he creado un boton por cada SUB (en total son 4 Sub) para que me genere las hojas en su respectiva hoja base, lo que quiciera que me ayudaras, es que no tenga que hacer cuatro botones sino que con un solo boton pueda ejecutar las 4 macros en forma consecutiva, es decir Sub 1() luego Sub 2(), Sub 3() y por ultimo Sub 4().
    Espero haberme explicado, gracias en lo que me puedas ayudar.

    Saludos

    ResponderEliminar
    Respuestas
    1. Hola Carlos
      puedes crear una quinta macro que reúna las cuatro anteriores:
      Sub MacroFinal()
      call Sub1:call Sub2:call Sub3:call Sub4
      En Sub

      Luego asociar esta Sub5 a un solo botón
      Saludos

      Eliminar
    2. Hola Ismael,
      Perfecto, discúlpame si soy muy atenido a que me ayudes por tantas preguntas, pero quisiera que cuando me genere todas la hojas al ejecutar todas las macros con el botón, estas se generen en otro libro, espero haberme explicado bien. Nuevamente mil gracias.

      Saludos

      Eliminar
    3. Hola,
      tendrás que abrir primero el otro archivo (método WorkBooks.Open) y luego dirigir los pegados de destino a ese archivo...
      Workbooks("nombre archivo.xlsx").Sheets .....

      Saludos

      Eliminar
    4. Hola Ismael, primero que todo, te doy las gracias ya que por tu ayuda oportuna he podido terminar mi proyecto el cual me estaba estancando y cada día me salían mas problemas que soluciones, nuevamente mil gracias.
      Por favor te pido este ultimo favor, ya que como habrás notado, el proyecto lo hice en Office 2010 y el problema es que la empresa el equipo con que trabajo no tiene actualizado este Office, aun tiene la version 2003. En otros Foros he visto que algunas persona con el mismo problema ha copiado los archivos donde se encuentra las Referencias (VBA-->Herramientas--> Referencias) y las copian a la capeta correspondiente a Office 2010, la verdad no se como se hace y me da miedo que dañe o afecte la funcionalidad del Office que actualmente manejo en la empresa. Quiciera que me ayudaras como debo hacer para trabajar con el Form si que me salga errores como "Error Compilacion: No se encuentra el proyecto o la biblioteca", que tengo que instalar, habilitar o des habilitar, y preferiblemente que pueda seguir trabajando en mi equipo con Office 2003.

      Mil gracias Ismael

      Saludos

      Eliminar
    5. Hola Carlos,
      como dices esto es un tema bastante delicado (no difícil), lo primero es saber qué Referencias faltan o fallan.. y luego localizarla para 'copiarla' y pegarla (o instalarla) en su localización de 2003..
      Pero no es tan sencillo por que no todas las librerias/referencias son compatibles entre versiones.

      En cuanto a ubicaciones, tendrás que tener instalado Office 2003 (al menos una de sus aplicaciones, Excel por ejemplo) ya que se genera un carpeta específica...

      Slds

      Eliminar
    6. Listo Ismael, muchas gracias por todo...saludos desde Colombia

      Eliminar
  16. Bueno dias como duplico valores y resalto en rojo en excel sheets de google. tiene que ser por formula por que no encuentro la funcion con el conditional formatting. gracias

    ResponderEliminar
  17. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  18. Hola Ismael, hola a tod@s!
    Estoy comenzando con este mundo de las macros y ya tengo un primer desafío interesante.

    En una hoja llamada Hoja1, tengo datos en el rango de celdas R(a11:a200), los cuales, al presionar un botón, al que le asigné una macro, cree tantas hojas como valores diferentes tenga, y que esta hoja sea la copia de una plantilla, que llamé Modelo.

    el codigo que usé es el siguiente

    Sub crear_copias_hoja_modelo()
    Dim celda As Range
    For Each celda In Sheets("Hoja1").Range("O11:O200").Cells
    If celda.Value <= " " Then Exit Sub
    On Error Resume Next
    Sheets("Modelo").Copy After:=Sheets("Hoja1")
    ActiveSheet.Name = celda.Value
    Next

    End Sub

    Hasta ahí, todo bien. Crea las hojas y evita las diferentes de 0, sino crearia 200 siempre.
    Pero, mi problema es que cada vez que le doy al botón, vuelve a crear la cantidad de hojas según los valores, pero con el nombre Modelo(1), (2), (3) etc. y cuando el valor está repetido, también.

    Muchas gracias a todos.

    ResponderEliminar
    Respuestas
    1. Hola Emiliano!
      la cuestión es que esperarías que hiciera??....
      El procedimiento genera las hojas.. y al haberle incluido un salto de error:
      On Error Resume Next
      cuando intenta generar una nueva hoja que ya existe (de un lanzamiento anterior de la macro).. normalmente fallaría, pero en tu caso, salta el error y deja la hoja creada sin haberle cambiado el nombre...
      Slds

      Eliminar
    2. Hola Ismael, antes que nada gracias por la respuesta tan pronta.

      Ahi modifiqué el codigo, quite el salto del error, y no crea la misma cantidad de hojas que de valores en el rango, con el nombre Modelo(1), Modelo(2), etc.
      Pero, crea una sola hoja, y salta un error de que dos hojas no pueden tener el mismo nombre,
      La idea, es generar una hoja por cada valor de la lista (que va a ir aumentando de tamaño con el tiempo), sin generar duplicados ni errores.

      el codigo me quedó así

      Sub crear_copias_hoja_modelo()
      Dim celda As Range
      For Each celda In Sheets("Estado de Pinzas").Range("O11:O200").Cells
      If celda.Value <= " " Then Exit Sub
      Sheets("Modelo").Copy After:=Sheets("Estado de Pinzas")
      ActiveSheet.Name = celda.Value
      Next

      End Sub

      Eliminar
    3. Hola!
      la idea es que emplees y controles los errores que te vayan a surgir,
      echa un vistazo a este ejemplo publicado:
      http://excelforo.blogspot.com.es/2015/10/vba-un-hipervinculo-dentro-de-un-listbox.html

      Debes tratar de controlar qué pasa cuando el nombre de la hoja ya exista... entre otras formas empleando On Error GoTo...

      Saludos

      Eliminar
    4. Hola como estas, escribo porque use tu codigo pero al agregar mas datos no se actualiza se que le dijiste al chico de arriba que habia que manejar los errores, yo logre que me genere una hoja mas pero no con el nombre del dato agregado, de verdad agradeceria tu ayuda.

      adjunto codigo

      Sub Generarhoja()

      Dim HojaOrigen As Worksheet, HojaNueva As Worksheet
      Set HojaOrigen = Sheets("UF_Dolar")
      Dim ultfla As Long
      ultfila = Range("A" & Rows.Count).End(xlUp).Row
      u = ultfila - 1
      'para recorrer los registros del listado
      For i = 1 To u



      'desactivamos la actualización/refresco de pantalla
      Application.ScreenUpdating = False



      'duplicamos la Hoja 'modelo'
      Sheets("PPTO_UF").Copy after:=Worksheets(Worksheets.Count)
      Set HojaNueva = Sheets(Worksheets.Count)
      nombrehoja = Worksheets("UF_Dolar").Cells(1 + i, 1).Value
      On Error GoTo ErrorHandler
      'damos nombre a la hoja con el valor de la celda A0+i
      HojaNueva.Name = nombrehoja

      Next i


      ErrorHandler:
      u = nombrehoja
      Exit Sub


      'activamos la actualización/refresco de pantalla
      Application.ScreenUpdating = True

      'limpiamos el portapapeles
      Application.CutCopyMode = False



      End Sub

      Eliminar
    5. Hola,
      una opción sería, en la parte del control:
      ErrorHandler:
      HojaNueva.Name = nombrehoja & i
      Exit Sub

      o directamente para evitar duplicidades hacerlo:
      Sheets("PPTO_UF").Copy after:=Worksheets(Worksheets.Count)
      Set HojaNueva = Sheets(Worksheets.Count)
      nombrehoja = Worksheets("UF_Dolar").Cells(1 + i, 1).Value
      HojaNueva.Name = nombrehoja & i

      Espero te oriente
      Saludos

      Eliminar
  19. Ismael, buenas tardes. Estuve aplicando el código de este apartado para copiar una plantilla. Todo funciona bien, pero tengo el inconveniente que cuando la ejecuto sale error 1004 y me copia una hoja adicional,a pesar de haber configurado ultfila.

    Asi mismo, en vista que el ingreso de datos en la hoja origen "Inventario" es constante, me gustaría que la macro se pueda ejecutar en mas de una oportunidad, pero que no repita los nombres de las hojas ya creadas (solo los nuevos ingresos). Eso es posible? Estaba leyendo sobre rangos variables, pero no capto la idea, disculpa.

    Este es la macro hasta el momento:

    Sub CopiarPlantilla()
    Dim HojaOrigen As Worksheet, HojaNueva As Worksheet
    Set HojaOrigen = Sheets("Inventario")
    Dim ultfla As Long
    ultfila = Range("A" & Rows.Count).End(xlUp).Row

    For i = 1 To ultfila - 1

    Application.ScreenUpdating = False

    Sheets("Plantilla").Copy after:=Worksheets(Worksheets.Count)
    Set HojaNueva = Sheets(Worksheets.Count)
    nombrehoja = Worksheets("Inventario").Cells(7 + i, 1).Value
    HojaNueva.Name = nombrehoja

    HojaOrigen.Cells(7 + i, 2).Copy
    HojaNueva.Cells(2, 3).PasteSpecial Paste:=xlValues
    HojaOrigen.Cells(7 + i, 4).Copy
    HojaNueva.Cells(3, 3).PasteSpecial Paste:=xlValues
    HojaOrigen.Cells(7 + i, 5).Copy
    HojaNueva.Cells(5, 3).PasteSpecial Paste:=xlValues
    HojaOrigen.Cells(7 + i, 6).Copy
    HojaNueva.Cells(6, 3).PasteSpecial Paste:=xlValues
    HojaOrigen.Cells(7 + i, 7).Copy
    HojaNueva.Cells(11, 3).PasteSpecial Paste:=xlValues
    HojaOrigen.Cells(6, 7).Copy
    HojaNueva.Cells(12, 3).PasteSpecial Paste:=xlValues

    Next i

    Application.ScreenUpdating = True

    Application.CutCopyMode = False

    End Sub


    Todos los datos a copiar inician en la fila 8. Espero puedas apoyarme.
    Saludos.

    ResponderEliminar
    Respuestas
    1. Hola Jimmy,
      ¿quizá tu columna A tenga un dato adicional???...

      Eliminar
    2. Hola Ismael.
      En la columna A, a partir de A8, están los códigos (C-0001, C-0002, C-0003...) que se utilizan para dar nombre a las hojas cuando se ejecuta la macro.
      He probado cambiando la descripción de estos códigos a un orden numérico (1,2,3,...) pero el error se mantiene y cuando ejecuto la macro despues de ingresar nuevos códigos, solo se copia 1 hoja (plantilla2) sin los valores de las celdas que deberían copiarse.
      Algo debo estar haciendo mal, pero no se que :-S

      Eliminar
    3. Entiendo solo ejecutas una vez la macro??.
      Si el nombre de la hoja ya existe (por que hayas lanzado previamente la macro) el proceso tal cual está fallará... y se detendrá tras crear la hoja
      Slds

      Eliminar
  20. Hola ismael, gracias por tu respuesta.
    Ajá, ejecuto la macro con el listado original, pero tengo diariamente ingresos de nuevos códigos.
    De que forma podría configurar la macro para que pueda ejecutarse nuevamente cada vez que se ingresen códigos nuevos saltando la repetición? Eso es posible?
    Disculpa por tantas preguntas, no domino mucho el tema de macros, son de mucha ayuda en mis labores y tus ideas y aportes me están ayudando un montón.

    Salu2 y mcuhas gracias por tu atención.

    ResponderEliminar
    Respuestas
    1. Hola,
      incorpora esta función dentro de tu proyecto

      Private Function ExisteHoja(NombreHoja As String) As Boolean
      ExisteHoja = Evaluate("ISREF('" & NombreHoja & "'!A1)")
      End Function

      y úsala para verificar si ya existe o no como control.
      Slds

      Eliminar
  21. Hola Ismael. Excelente la macro para crear hojas la probe y funciona. Pero tengo un caso bastante complejo. Te envie un correo el dia de ayer con un formato y una explicacion. Te agradezco que por favor me ayudes.

    ResponderEliminar
    Respuestas
    1. ok,
      lo recibí.
      En cuanto me sea posible lo reviso y te contesto por email.
      Slds

      Eliminar

Nota: solo los miembros de este blog pueden publicar comentarios.