jueves, 9 de junio de 2011

Estructuras repetitivas: Do While ... Loop

Descargar el fichero: do_while_loop.xlsm


Cuando conocemos cuantas veces se ha de repetir el bucle usamos la estructura FOR ... NEXT, pero cuando desconocemos el número de veces que se ha de repetir el bucle debemos ir a una estructura del tipo DO WHILE ... LOOP, o alguna de sus variantes. Esto es lo que vamos a ver en esta ocasión.

Do While ... Loop

Hacer mientras se cumpla la condición.

La sintaxis de esta estructura es la siguiente:

Do While condición
....
....
Loop
Esta estructura permite hacer un bucle que se repetirá mientras se siga cumpliendo la condición. El flujo del programa se ejecuta de arriba hacia abajo. Al llegar a la linea superior del bucle se analiza la condición y si es verdadera se ejecutan las líneas interiores del bucle. Al llegar al Loop se devuelve el flujo del programa al inicio, y se vuelve a analizar la condición. Este proceso se repite mientras la condición sea verdadera, por tanto, en algún momento se debe producir algún cambio en las sentencias interiores del bucle que hagan que la condición se transforme en falsa para que no se siga repitiendo el bucle de forma indefinida. En el momento en el que la condición es falsa el bucle ya no se ejecuta y se devuelve el control del flujo del programa a las sentencias que se encuentres debajo del Loop.

Hemos diseñado un ejemplo donde generamos números aleatorios entre 1 y 100, y se los asignamos a la variable i.

i = Int(Rnd * 100) + 1

Con la variable s vamos a sumar los valores que va tomando i. Esto es lo que se denomina un ACUMULADOR, que va añadiendo valores a la variable s.

s = s + i

Esta expresión no se debe interpretar como lo haríamos en matemáticas. En programación el signo igual indica que lo que hay a la derecha se va a asignar a la variable que hay a la izquierda.

La interpretación correcta es que tomamos el antiguo valor de la variable s y le sumamos lo que vale i, y esa suma se asigna al nuevo valor que ahora toma la variable s.

Los valores que van tomando las variables i y s se escriben en las columnas 2 y 3, que son las columnas B y C.

Para que la fila vaya cambiando en el instrucción Cells(fila, columna) hemos creado una variable que precisamente se llama fila y que dentro del bucle, y al final de éste, incrementa uno.

fila=fila+1

De esta forma, la filas se van incrementando de uno en uno a medida que el bucle va haciendo sus ciclos. Esto es lo que en informática se llama CONTADOR.

La condición que hace que se repita el bucle es s<1000, lo que provoca que el bucle se repita MIENTRAS se cumpla que s, que es el acumulado de la variable i, sea inferior a 1000.


El resultado es que disponemos de dos columnas con números aleatorios. En la columna B los números aleatorios son enteros entre 1 y 100, y en la columna C se encuentran sus acumulados. El último número de la columna C será un número entre 1000 y 1099, que al ser mayor o igual a 1000, hará que la macro se detenga.

Necesitamos borrar el rango que hemos escrito en las columnas B y C, para que al generar una nueva serie ve valores se haga sobre una zona limpia. Esto se hace con la macro Borra.



Do ... Loop While

Do
....
....
Loop While condición


Esta estructura es similar a la anterior pero la condición se evalúa al final. La consecuencia inmediata de esto es que el flujo del programa entra en el bucle directamente la primera ver que se ejecuta. Al final se evalúa la condición y se decide si se repite el bucle, pero al menos se ha ejecutado una vez.





Do ... Loop Until

Hacer hasta que se cumpla la condición

Do
....
....
Loop Until condición


La condición se evalúa y el bucle se repite hasta que se cumpla la condición.

Hemos tenido que cambiar la condición para obtener resultados similares. Ahora la condición es s>=1000 ya que el bucle se repite hasta que se cumpla la condición.

También podríamos haber puesto el comando NOT, sin necesidad de tocar la condición. Quedaría así:

Loop Until Not (s < 1000)


Una variante poco ortodoxa

La siguiente macro (Bucles4) es una variante de la anterior. Decimos que es poco ortodoxa debido a que el Loop no lleva condición que haga que finalice, por lo que en teoría los ciclos del bucle seguirían indefinidamente. Para detener estos infinitos ciclos del bucle lo que hacemos es incluir dentro del bucle un condicional (IF) que haga que cuando se cumple cierta condición la macro finalize (END).


Sub Bucles4()
Dim i As Byte
Dim s As Integer
Dim fila As Byte
Borra
s = 0
fila = 1
Do
   i = Int(Rnd * 100) + 1
   s = s + i
   Cells(fila, 2) = i
   Cells(fila, 3) = s
   fila = fila + 1
   If s > 1000 Then End
Loop
End Sub


Hoja 2

En la Hoja2 disponemos de una tabla y deseamos desplazarnos por ella hasta que encontremos una celda vacía.

Sub Desplaza()
Do While Not IsEmpty(ActiveCell)
   ActiveCell.Offset(1, 0).Activate
Loop
End Sub

Nos situamos en una celda que contiene datos, por ejemplo, la celda B4 y ejecutamos la macro. al finalizar la ejecución el cursor aparecerá en la primera celda vacía que encuentre en la columna B.

La línea

ActiveCell.Offset(1, 0).Activate

lo que hace es desplaze el cursor una celda hacia abajo respecto a su posición actual. Como esta línea esta dentro de un bucle se ejecutará repetidamente hasta que el flujo del programa se salga de bucle.

El bucle se repite mientras la celda activa no sea una celda vacía. Esto supone, que el cursor se vaya desplazando por la columna donde se dejara inicialmente y que no pare de bajar hasta que se encuentre con una celda vacía.


Este bucle es muy útil para encontrar en una base de datos el final de la tabla. Para ello, debemos situar el cursor en la columna donde se encuentre el campo llave o campo clave. Esto ha de ser así ya que sabemos que al tratarse de una variable sin espacios vacíos el cursor bajará hasta el final.

Práctica (Hoja 3)

Le invitamos a crear un código que se desplace hacia arriba y que se sitúe en una tabla en la cabecera de la columna donde se entrontrara inicialmente el cursor.


En la Hoja3, sitúe el cursor en la celda B24. El objetivo es que la macro desplace el cursor de forma ascendente hasta la celda que hace el papel de cabecera de esta columna, en nuestro caso, la celda B3.

Hoja 4

Convertir en mayúsculas los valores de un rango. Esto se hace con UCase y queremos pasar a minúsculas se usaría LCase. Veamos el código.


Sub Ciudades()
Dim R As Range
Set R = ActiveCell.CurrentRegion
Dim Inicial As Long
Dim Final As Long
Inicial = 1
Final = R.Count
Dim i As Long                      'Índice
Dim Ciudad As String               'Texto de la celda
i = Inicial
Do
  Ciudad = R.Cells(i).Value        'Toma la ciudad
  R.Cells(i).Value = UCase(Ciudad) 'Escribe la ciudad en mayúsculas
  i = i + 1                        'Contador
Loop While i <= Final
End Sub

46 comentarios:

  1. Una posible solución a la práctica propuesta sería la siguiente:

    Sub Desplaza2()
    Do While Not IsEmpty(ActiveCell)
    ActiveCell.Offset(-1, 0).Activate
    Loop
    ActiveCell.Offset(1, 0).Activate
    End Sub

    ResponderEliminar
    Respuestas
    1. Para cuando la cabecera de datos se encuentra en la fila 1
      Sub Desplaza3()
      Do While Not IsEmpty(ActiveCell)
      If ActiveCell.Row = 1 Then End
      ActiveCell.Offset(-1, 0).Activate
      Loop
      ActiveCell.Offset(1, 0).Activate
      End Sub

      Eliminar
  2. Caramba, magnífico blog. Te felicito.
    Un saludo.

    ResponderEliminar
  3. Genial Adolfo!!! Como siempre!!! Saludos!!!

    ResponderEliminar
  4. DIculpe me podria ayudar para crear con do while una piramide con asteriscos .el programa es el siguiente realizar una piramide con asterisco y pedir al usuario cuantos asteriscos quiere ver.
    algo mas o menos asi:
    *
    * * *

    ResponderEliminar
  5. Hola Belén.

    Con la idea de los asteriscos he creado una macro que luego tu podrás adaptar ya que está resuelta con FOR...NEXT.

    Árbol de Navidad

    ResponderEliminar
  6. Hola, lo primero me gustaría felicitarte por la web, estoy empezando con las VBA en Excel y me ayuda muchísimo.

    Estoy creando una macro que descarga datos de un formulario web en formato csv y los ordena para después poder valorar uno a uno.

    Los Libros que relaciono son “Prueba” con la hoja “DescargaDatos” y “Prueba2” con las hojas “Formulario” y “Resumen”.
    Las páginas que se relacionan son las siguientes:
    - Página de descarga de datos (en csv) en “Prueba”.
    - Página de Formulario en “Prueba2” (Hoja estándar) donde están los campos a rellenar para cada Persona registrada.
    - Página del Formulario en “Prueba2” (Nombre) que es una copia de la Hoja Estándar con los datos de cada Persona registrada.
    - “Página Resumen” en “Prueba2”, donde incluyo los datos de todas las hojas personalizadas (Nombre).

    La forma de ordenarlos (ya tengo escrita la macro que los clasifica si meto los datos uno a uno en las celdas de la “Hoja Estándar”) es la siguiente:
    - Se rellena el Formulario (“Hoja Estándar”) con campos como Nombre, Dirección, Teléfono, etc…
    - Se crea una copia de la hoja (“copia hoja estándar") y al mismo tiempo se copian en otra “hoja resumen” donde posteriormente poder compararlos. Renombro la “copia hoja estándar” con el valor de una celda (“Nombre”) y borro el contenido de las celdas de “hoja estándar” para comenzar de nuevo.
    - Imprimo esa nueva hoja (“Nombre”) en pdf y se guarda en una carpeta en C:
    - Paso a la siguiente id.
    Como son bastantes formularios los que tengo que tratar, me gustaría no tener que estar pasando los datos a la “hoja estándar” uno a uno. Ahora viene mi pregunta, me gustaría hacer este paso con un Do While…

    El trabajo completo sería:
    1 - Formatear los datos en CSV y pasarlos a columnas (Se descargan en Col A y los inserto en “B1”).
    2 - Contar los valores descargados (están guardados y numerados por orden de entrada, Formulario Web) y situar el valor en una celda (DescargaDatos“A1”) para comparar con los datos ya tratados anteriormente (DescargaDatos“A2”).
    3 - Aplicar un macro Do While (aquí es donde necesito ayuda) que realice las funciones de guardado a partir de la última id guardada. Si por ejemplo tengo guardados 10 datos (10 en la celda “A2”) y tras la última descarga de formularios hay 30 en total (celda “A1”), me gustaría hacer un Do While Loop del proceso de guardado mientras “Valores Totales” (“A1”) > “Valores Guardados” (“A2”) comenzando por el valor de esta celda.
    4 - Pasar a la siguiente id.

    Si pudieras ayudarme con el código te lo agradecería mucho ya que me ahorraría mucho tiempo.

    Muchas gracias!

    ResponderEliminar
  7. Te incluyo la macro completa que tengo desarrollada por si puedes ayudarme, muchas gracias!

    Sub Formatear_Datos()
    '
    ' Formatea Datos CSV Macro
    '
    Columns("A:A").Select
    Selection.TextToColumns Destination:=Range("B1"), DataType:=xlDelimited, _
    TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=False, _
    Semicolon:=False, Comma:=True, Space:=False, Other:=False, FieldInfo _
    :=Array(Array(1, 1), Array(2, 1), Array(3, 1)), TrailingMinusNumbers:=True

    ' Borra Columna A
    Columns("A:A").Select
    Selection.ClearContents

    ' Contar Valores
    Range("A1").Select
    ActiveCell.FormulaR1C1 = "=COUNTA(C[1])-1"

    ' Copia el número de compañias registradas
    Windows("Prueba2.xlsm").Activate
    Sheets("Resumen").Select
    Range("A1").Select
    Selection.Copy
    Windows("Prueba.xlsm").Activate
    Sheets("DescargaDatos").Select
    Range("A2").Select
    ActiveSheet.Paste Link:=True

    Dim Resta As Integer
    Resta = Range ("A1") - Range("A2")
    Do
    ' Calcular diferencias
    Windows("Prueba.xlsm").Activate
    Sheets("DescargaDatos").Select
    Range("A3").Select
    ActiveCell.FormulaR1C1 = "=R[-2]C-R[-1]C"

    ResponderEliminar
  8. ' Copiar Id number en Formulario
    Windows("Prueba.xlsm").Activate
    Sheets("DescargaDatos").Select
    Range("A2").Select
    Selection.Copy
    Windows("Prueba2.xlsm").Activate
    Sheets("Formulario").Select
    Range("C9").Select
    ActiveSheet.Paste
    ' Copiar Nombre en Formulario
    Windows("Prueba.xlsm").Activate
    Sheets("DescargaDatos").Select
    Range("A3").Select
    Selection.Copy
    Windows("Prueba2.xlsm").Activate
    Sheets("Formulario").Select
    Range("C6").Select
    ActiveSheet.Paste
    ' Copiar Direccion en Formulario
    Windows("Prueba.xlsm").Activate
    Sheets("DescargaDatos").Select
    Range("A4").Select
    Selection.Copy
    Windows("Prueba2.xlsm").Activate
    Sheets("Formulario").Select
    Range("C7").Select
    ActiveSheet.Paste

    ' Añade nuevo Dato a Check List Macro
    Sheets("Resumen").Select
    Range("c1:c6").Select
    Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove

    ' creo copia en blanco de Formulario
    Sheets("Formulario").Select
    Sheets("Formulario").Copy Before:=Sheets(2)

    ' Copia el link a Nombre
    Sheets("Formulario (2)").Select
    Range("c6").Select
    Application.CutCopyMode = False
    Selection.Copy
    Sheets("Resumen").Select
    Range("c2").Select
    ActiveSheet.Paste Link:=True

    ' Copia el link a Direccion
    Sheets("Formulario (2)").Select
    Range("c7").Select
    Application.CutCopyMode = False
    Selection.Copy
    Sheets("Resumen").Select
    Range("c3").Select
    ActiveSheet.Paste Link:=True

    ' imprimo en pdf hoja de la empresa
    Windows("Prueba2.xlsm").Activate
    Sheets("Formulario (2)").Select
    Dim RutaArchivo As String
    RutaArchivo = "C:\Prueba\" & Range("c6").Value & ".PDF"
    Range("a1:h50").Select
    Range("a1").Activate
    Selection.ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
    RutaArchivo, _
    Quality:=xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas _
    :=False, OpenAfterPublish:=False

    ' renombro la nueva hoja
    Windows("Prueba2.xlsm").Activate
    Sheets("Formulario (2)").Select
    ActiveSheet.Name = Range("c6").Value

    ' borro Formulario
    Windows("Prueba2.xlsm").Activate
    Sheets("Formulario").Select
    Range("c6:c9").Select
    Range("c6").Activate
    Selection.ClearContents

    Loop Until Resta = 0

    End Sub

    ResponderEliminar
  9. Primero mis felicitaciones excelente informacion, necesito por favor su apoyo como podria obligar o forzar la itereacion del bucle en un caso determinado me explico dentrol del bucle ejecuto varias acciones necesito que de cumplice una condicion este pase al siguiente registro (Fila) omitiendo las acciones.. Gracias de antemano

    ResponderEliminar
  10. Hola Jose T.

    Puedes probar incluyendo dentro del bucle una estructura condicional IF de forma que si se cumple la condición realice lo que quieres y en caso contrario (ELSE) realice otra cosa.

    ResponderEliminar
    Respuestas
    1. Hola Como estás, por favor ayúdame con algo. Mira necesito una macro para que en un rango determinado de datos me ordene de mayor a menor por fila. Así por ejemplo:

      ABC | 10 | 20 |(vacío) | 50 | 1 ..... ordenando: 50|20|10|1
      CBA | 20 | 50 |40 | 30 | 2 ..... ordenando: 50|40|30|20|2

      Con la opción "ORDENAR" (IZQUIERDA A DERECHA) se lo puede hacer pero tengo que hacerlo línea por línea manualmente =(, y la intención es que lo pueda hacer por medio de una macro para que lo haga linea por linea hasta el ultimo registro que encuentre. Mil Gracias por tu apoyo

      Eliminar
  11. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  12. Saludos!!!

    tengo la siguiente inquietud, estoy haciendo un sorteo en excel (nombre y cédula), ya tengo la formula que me da esta información por medio de una formula de aleatorio, lo que quisiera es insertar dos botones uno que funcione como el F9 sostenido y otro que me detenga esa función, para seleccionar el ganador de manera aleatoria... Quedo altamente agradecida con su ayuda.

    ResponderEliminar
  13. hola buenas noches,
    Disculpa tengo un proble con una macro que es un sumador y acumula pero solo lo hace un una celda celda en especifico y quisiera hacerlo para varias celdas aplicar la misma operacion este es el codigo:

    Private Sub Worksheet_Change(ByVal Target As Excel.Range)
    If Target.Address = "$A$1" Then [B1] = [B1] + Target
    End Sub

    ResponderEliminar
  14. alguien me puede ayudar como hacer una inserción de columnas, haciendo un salto por columna, y dejándolo de hacer cuando encuentre una columna vacía?

    ResponderEliminar
  15. excelente que buen trabajo, queria pedirle una ayuda buscar un dato de abajo hacia arriba seleccionando el ultimo dato de la columna y al tener la coincidencia restar la cantidad de filas que los separa
    muchas gracias y que Dios lo bendiga por esa entrega de conocimiento

    ResponderEliminar
  16. excelente que buen trabajo, queria pedirle una ayuda buscar un dato de abajo hacia arriba seleccionando el ultimo dato de la columna y al tener la coincidencia restar la cantidad de filas que los separa
    muchas gracias y que Dios lo bendiga por esa entrega de conocimiento

    ResponderEliminar
  17. Buenas tardes, disculpe la molestia no se si me pudiera ayudar por favor, es q tengo esta sentencia pero lo único que logro es repetir el primer registro, no me muestra los otros 9 registros; de antemano muchas gracias.
    Set RsFa = New ADODB.Recordset
    Rem sqlstr = "Select PAR_FACTF01.Cve_Doc, CVE_CLPV, FECHA_DOC, "FACTF01.CVE_VEND, CVE_PEDI, CVE_ART", CANT, PREC, PAR_FACTF01.TOTIMP4, FACTF01.CVE_OBS, PAR_FACTF01.CVE_OBS, DESC1, DESC2, DESC3, NOMBRE, CLASIFIC FROM FACTF01, PAR_FACTF01, CLIE01 WHERE CLAVE=CVE_CLPV AND FACTF01.CVE_DOC=PAR_FACTF01.CVE_DOC AND FACTF01.STATUS<>'C' AND (datevalue(FECHA_DOC) >= '" & FechaI & "' and datevalue(FECHA_DOC) <= '" & FechaF & "')"
    sqlstr = "Select INVE01.CVE_ART, DESCR, EXIST, COSTO_PROM, CLASIFIC FROM INVE01, CLIE01 ORDER BY CVE_ART"
    ', WHERE CLAVE=CVE_ART AND INVE01.CVE_ART >= value('" & FechaI & "') AND CVE_ART <= value ('" & FechaF & "')"
    'MsgBox sqlstr
    RsFa.Open sqlstr, Cnn, adOpenForwardOnly, adLockReadOnly
    Rc = 3: Tot = 0: IMPORTE = 0
    Do While Rc < 10
    Rc = Rc + 1
    Hja.Cells(R, 1).Value = Trim(RsFa!CVE_ART)
    Hja.Cells(R, 2).Value = Trim(RsFa!DESCR)
    Hja.Cells(R, 3).Value = Trim(RsFa!EXIST)
    Hja.Cells(R, 4).Value = Trim(RsFa!COSTO_PROM)
    RsFa.MoveNext

    Loop
    'R = R + 1
    'RsFa.NextRecordset
    'RsFa.MoveNext
    'Wend
    RsFa.Close
    Cnn.Close

    ResponderEliminar
  18. Buenas tardes! Necesito ayuda, tengo un userform para registrar datos a una hoja de excel que posteriormente sera impresa, todo funciona muy bien, pero necesito que la macro de registrar los datos desde el userform hasta la hoja de excel permita hacerlo un máximo de 5 veces y posterior al 5 registro muestre un mensaje y obligue a imprimir para poder continuar

    ResponderEliminar
  19. Hola. Genial tu exposición de este tema.
    Tengo una consulta haber si puedes ayudarme.
    Yo poseo una macro que me suma valores hasta que el resultado en la columna A sea =0, con otra condicion en la columna B.
    Sucede que solo me selecciona las celdas que suman cero si son dos celdas si el valor que compone 0 son 3 celdas no me lo toma en cuenta y los ignora.

    Como logro que tome todas las celdas que componen el valor 0 para kla segunda condicion de la Columna B?

    ResponderEliminar
  20. Hola,
    Tengo un problema, me gustaria crear una macro que:
    1. Que de formato a una tabla.
    2. Otra macro que le de el mismo formato a todas la tablas del documento.
    Es en Word, no en excel. Gracias.

    ResponderEliminar
  21. Buenos dias

    Buenos dias

    me podrías ayudar incluyendo esta formula en un do while ActiveCell.FormulaR1C1 = "=CONCATENATE(RC[1],RC[6])"
    Range("A3").Select

    ResponderEliminar
  22. Hola buenas noches, primero felicitarle por tan buena informacion y segundo pedir ayuda para mi siguiente problematica, sucede que recibo semanalmente una base de datos de aprox 50,000 clientes que mediante formulas he logrado depurar, hasta obtener mi “universo” que oscila entre 9,000 y 13,000; de ese universo, según su tamaño, debo de obtener aleatoriamente entre un 15 y 25% y asignarlo a que lo revisen algunos compañeros de forma aleatoria.
    Lo que pasa es que necesito una macro que me extraiga aleatoriamente el tamaño determinado de mi muestra, y que además obligatoriamente me asigne a mis compañeros los casos equitativamente para revisar.
    Ahora la cosa se complica por que me piden que obligatoriamente revise los casos de clientes que realizan operaciones por arriba de cierto monto y que además se revise por lo menos un caso de cada vendedor, y en ocasiones tenemos a 500 o 600 vendedores, ayuda por favor, ya intente con formulas y nada mas no puedo.
    Aclaro que la base original ya esta depurada, de esta base depurada debo obtener:
    a) al menos un cliente de cada vendedor,
    b) obligatoriamente los clientes que realizan operaciones importantes (los clasifique como estatus 1 y 2, los estatus 2 son los que realizan operaciones importantes)
    c) que el tamaño de la muestra sea al menos del 20%,
    d) y además asignar equitativamente entre mis compañeros que somos 8 para revisión, gracias

    ResponderEliminar
    Respuestas
    1. Hola Angela.
      El caso que comentas se podría resolver aplicando el método de simulación de Monte Carlo y metiendo en el programa las condiciones y restricciones que necesitas.
      Envíame a: financieras @ gmail.com un fichero de Excel con la base de datos y explicando con más detalle las columnas que necesitas tratar.
      Un saludo.

      Eliminar
  23. Hola Adolfo, primeramente quisiera dar gracias por el trabajo que haces al ayudar a la gente con este pagina. Me ha servido de mucho. Y bueno el otro tema de mi comentario es si puedes ayudarme con una macro que tengo que hacer. Si tienes algún ejemplo o alguna recomendación de comando para utilizar. Te explico, soy novato en esto y empecé con macros hace unas atrás. La macro consiste en que te entregan una tabla con datos con algunos criterios como nombres, edades, sexo y algo particular de ellos pero que dentro del grupo es repetitivo esta ultima característica Todo esto estará en una tabla que puede ir disminuyendo de datos o aumentando. Mi trabajo consiste en buscar y contar todas las personas que cumplan uno o mas criterios.
    Agrego también que trabaje con la función Count ifs pero esta trabaja con un rangos determinados y no se me ocurre como poder hacerla. Agradecería tus consejos. Muchas gracias nuevamente.

    ResponderEliminar
    Respuestas
    1. Hola Felipe.
      Creo que lo que necesitas se podría conseguir sin macros con Datos, Filtro. El simbolo del icono es un embudo. Aplicado a una base de datos te permite filtrar y obtener resúmenes de la información que manejas.
      Un saludo.

      Eliminar
    2. Otra posibilidad que puedes utilizar se encuentra en el siguiente enlace.

      BUSCARV para valores repetidos

      Eliminar
  24. Una pregunta, yo quiero poner que la restricción del Loop While sea que cada vez que se intruduzca un valor que no sea una letra admitida por la variable vuelva a pedir que se ingrese el valor.

    Sub Resta()
    '
    ' Resta Macro
    Dim Debe As String
    Dim Haber As String


    Debe = InputBox("Colocar la Columna (Ejem:A, B, C, ETC")
    Do While Debe = ""
    MsgBox "No has seleccionado ninguna Columna"
    Debe = InputBox("Colocar la Columna (Ejem:A, B, C, ETC")
    Loop

    Haber = InputBox("Colocar la Columna (Ejem:A, B, C, ETC")
    Do While Haber = ""
    MsgBox "No has seleccionado ninguna Columna"
    Haber = InputBox("Colocar la Columna (Ejem:A, B, C, ETC")
    Loop
    End Sub

    Es decir en vez de While = "", colocar While <> String

    ResponderEliminar
  25. Esta puede ser otra solucion con bulcle for
    Sub Recorrer_Celda()

    Dim Fila As Integer, Fila2 As Integer

    Fila = Application.WorksheetFunction.CountA(Sheets("Hoja2").Range("b3:b500"))


    For i = Fila To 1 Step -1
    Range("b" & i + 2).Activate
    Next i


    End Sub

    ResponderEliminar
  26. BUENAS TARDES ADOLFO QUISIERA SABER COMO ME PUEDES COLABORAR CON ESTA MACRO, ESA ES LA CONDICION PERO LA DEBO REPETIR POR POR 100 FILAS HE IMPRIMIRLAS... TE AGRADEZCO DE ANTE MANO LA ATENCION A LA PRESENTE

    EDWARD BECERRA

    Range("R3").Select
    Selection.Copy
    Range("G4:H4").Select
    ActiveSheet.Paste
    Range("S3").Select
    Application.CutCopyMode = False
    Selection.Copy
    Range("H5:I5").Select
    ActiveSheet.Paste
    Range("T3").Select
    Application.CutCopyMode = False
    Selection.Copy
    Range("J7").Select
    ActiveSheet.Paste
    Application.CutCopyMode = False
    ActiveWindow.SelectedSheets.PrintOut Copies:=1, Collate:=True, _
    IgnorePrintAreas:=False
    End Sub

    ResponderEliminar
  27. Hola Como estás, por favor ayúdame con algo. Mira necesito una macro para que en un rango determinado de datos me ordene de mayor a menor por fila. Así por ejemplo:

    ABC | 10 | 20 |(vacío) | 50 | 1 ..... ordenando: 50|20|10|1
    CBA | 20 | 50 |40 | 30 | 2 ..... ordenando: 50|40|30|20|2

    Con la opción "ORDENAR" (IZQUIERDA A DERECHA) se lo puede hacer pero tengo que hacerlo línea por línea manualmente =(, y la intención es que lo pueda hacer por medio de una macro para que lo haga linea por linea hasta el ultimo registro que encuentre. Mil Gracias por tu apoyo

    ResponderEliminar
  28. Hola buenos días. Me surge una duda, y es la siguiente:
    Necesito que se haga una operación concreta, tantas veces a la derecha como aparezca en una celda de su izquierda. es decir, hay una columna en la que hay valores (columna E) y necesito realizar esta operación (1 - ALEATORIO()*30 ) a la derecha de cada celda de la columna tantas veces como indique la celda.

    ResponderEliminar
  29. HOLA BUENOS DIAS.
    COMO PUEDO UN REGISTRO DE VENTAS DE 2000 ITEMS SE CONTABILIZA AUTOLATICAMENTE O SE

    121-------X
    401-----------X
    701-----------X

    ResponderEliminar
  30. BUEN DIA
    QUISIERA NUMERAR EN LA COLUMNA B TODOS LOS DATOS QUE TENGO EN LA COLUMNA A, ES DECIR QUE SI TENGO UN DATO POR EJEMPLO 'AAAA' LE ASIGNE EL NUMERO 1 Y CUANDO EL DATO DE LA COLUMNA A CAMBIE POR EJEMPLO 'BBBB' LE ASIGNE EL NUMERO 2 Y ASI SUCESIVAMENTE, QUE INCREMENTE EL VALOR HASTA QUE CAMBIE EL DATO DE LA COLUMNA A, ESPERO ME HAYA DADO A ENTENDER, GRACIAS

    ResponderEliminar
  31. Buen dia, saludos... tengo un archivo donde registro el inventario mensual..quisiera enlazar las filas y columnas del resultado final ..eje enero existencia final, con las columnas iniciales del mes de febrero, pero con las finales de enero sin inventario en cero.. me explico, que para el mes de febrero me depure y elimine los articulos en cero.. quisiera que verificara los datos finales en enero, si el artc es cero saltar a la siguiente fila, sino copiarla en las columnas iniciales de la siguiente hoja, pero en la celda de febrero que ejecuta el o los condicional(es)

    ResponderEliminar
  32. Saludos, primero felicitarle por tan buena informacion y segundo pedir ayuda al siguiente problema, luego de generar una tabla con filtro avanzado en una macro, ¿cómo puedo totalizar al final de algunas columnas? en la misma macro.

    ResponderEliminar
  33. Me podrian ayudar.....necesito un bucle que cuente las filas entre dato y dato (en la columna A) e incerte las necesarias entre datos (ahi mismo en columna A) segun lo necesite para una separacion de 6 filas entre cada uno.
    ejemplo
    1
    (esp1)
    (esp2)
    2
    (esp1)
    (esp2)
    (esp3)
    3
    (esp1)
    (esp2)
    4
    (esp1)
    (esp2)
    (esp3)
    (esp4)
    5
    (esp1)
    (esp2)
    (esp3)

    etc....

    para que quede asi
    1
    (esp1)
    (esp2)
    (esp3)
    (esp4)
    (esp5)
    (esp6)
    2
    (esp1)
    (esp2)
    (esp3)
    (esp4)
    (esp5)
    (esp6)
    3
    (esp1)
    (esp2)
    (esp3)
    (esp4)
    (esp5)
    (esp6)
    4
    (esp1)
    (esp2)
    (esp3)
    (esp4)
    (esp5)
    (esp6)
    5
    (esp1)
    (esp2)
    (esp3)
    (esp4)
    (esp5)
    (esp6)

    etc.... hasta donde se encuentre el ultimo dato

    ResponderEliminar
  34. Buenos días Adolfo. Gracias por la ayuda que nos prestas a todos.

    Me gustaría saber si existe algún modo, en referencia al bucle DO WHILE, de volver al principio del bucle sin necesidad de llegar al final de este en el LOOP. Es decir en función del resultado de un IF poder saltar al principio del bucle, al igual que se hace con otros lenguajes como clipper.
    Muchas gracias.

    ResponderEliminar
  35. Buen Dia, ud me puede ayudar a hacer un ciclo For-Next o Do-While esoty haciendo una formato de oreden de compra mas o menos el codigo va asi, soy principiante en VBA de excel, Gracias

    Sub Venta1()
    ActiveSheet.Unprotect "XXXXX"
    If Hoja1.Range("I11").Value <> "" Then
    If Hoja1.Range("E11") = 0 Then
    Hoja1.Range("J11").Formula = Range("K11") / Range("I11")
    If Range("J11") < 0.059 Then
    MsgBox "Porcentaje por debajo de lo autorizado PRECIO DE VENTA NO PUEDE ESTAR VACIO, Corregir", vbSystemModal, "ATENCION CORREGIR DATOS!!!"
    Exit Sub
    End If
    End If


    If Range("E11") <> 0 Then
    Hoja1.Range("J11").Formula = Range("K11") / Range("I11")
    If Range("J11") < 0.099 Then
    MsgBox "Porcentaje por debajo de lo autorizado PRECIO DE VENTA NO PUEDE ESTAR VACIO, Corregir", vbSystemModal, "ATENCION CORREGIR DATOS!!!"
    Exit Sub
    End If
    End If
    End If


    If Hoja1.Range("I12").Value <> "" Then
    If Hoja1.Range("E12") = 0 Then
    Hoja1.Range("J12").Formula = Range("K12") / Range("I12")
    If Range("J12") < 0.059 Then
    MsgBox "Porcentaje por debajo de lo autorizado PRECIO DE VENTA NO PUEDE ESTAR VACIO, Corregir", vbSystemModal, "ATENCION CORREGIR DATOS!!!"
    Exit Sub
    End If
    End If
    End If


    If Range("E12") <> 0 Then
    Hoja1.Range("J12").Formula = Range("K12") / Range("I12")
    If Range("J12") < 0.099 Then
    MsgBox "Porcentaje por debajo de lo autorizado PRECIO DE VENTA NO PUEDE ESTAR VACIO, Corregir", vbSystemModal, "ATENCION CORREGIR DATOS!!!"
    Exit Sub
    End If
    End If


    Dim Resp As Byte
    Dim Si As Integer
    Dim No As Integer
    If Hoja1.Range("E11") = 0 And Hoja1.Range("J11") > 0.099 Then
    Else
    End If
    If Hoja1.Range("E11") <> 0 And Hoja1.Range("J11") > 0.059 Then
    Else
    End If
    Resp = MsgBox("Agregar otro cliente?", vbYesNo + vbExclamation, "AVISO")

    If Resp = vbYes Then
    Hoja1.Range("B12").Select
    Else
    End If

    If Resp = vbNo Then
    If Hoja1.Range("E11") = 0 And Hoja1.Range("J11") > 0.099 Then
    Else
    If Hoja1.Range("E11") <> 0 And Hoja1.Range("J11:J20") > 0.059 Then
    Else
    End If
    End If
    End If



    ActiveSheet.Protect "XXXXX"

    End Su

    ResponderEliminar
    Respuestas
    1. Lo que busco es que el proceso de arriba el de
      If Hoja1.Range("I11").Value <> "" Then
      If Hoja1.Range("E11") = 0 Then
      Hoja1.Range("J11").Formula = Range("K11") / Range("I11")
      If Range("J11") < 0.059 Then
      MsgBox "Porcentaje por debajo de lo autorizado PRECIO DE VENTA NO PUEDE ESTAR VACIO, Corregir", vbSystemModal, "ATENCION CORREGIR DATOS!!!"
      Exit Sub
      End If
      End If


      If Range("E11") <> 0 Then
      Hoja1.Range("J11").Formula = Range("K11") / Range("I11")
      If Range("J11") < 0.099 Then
      MsgBox "Porcentaje por debajo de lo autorizado PRECIO DE VENTA NO PUEDE ESTAR VACIO, Corregir", vbSystemModal, "ATENCION CORREGIR DATOS!!!"
      Exit Sub
      End If
      End If
      End If

      Se repita y lo haga desde la fila 11 hasta la 20.

      Eliminar
  36. Lo que busco es que el proceso de arriba el de
    If Hoja1.Range("I11").Value <> "" Then
    If Hoja1.Range("E11") = 0 Then
    Hoja1.Range("J11").Formula = Range("K11") / Range("I11")
    If Range("J11") < 0.059 Then
    MsgBox "Porcentaje por debajo de lo autorizado PRECIO DE VENTA NO PUEDE ESTAR VACIO, Corregir", vbSystemModal, "ATENCION CORREGIR DATOS!!!"
    Exit Sub
    End If
    End If


    If Range("E11") <> 0 Then
    Hoja1.Range("J11").Formula = Range("K11") / Range("I11")
    If Range("J11") < 0.099 Then
    MsgBox "Porcentaje por debajo de lo autorizado PRECIO DE VENTA NO PUEDE ESTAR VACIO, Corregir", vbSystemModal, "ATENCION CORREGIR DATOS!!!"
    Exit Sub
    End If
    End If
    End If

    Se repita y lo haga desde la fila 11 hasta la 20

    ResponderEliminar
  37. Buenos Días, apenas llego y espero me colaboren para aprender bastante
    de VBA

    ResponderEliminar
  38. Hola! tengo esto y necesito que se repita hacia abajo, peor nos se como sumarle 1 a cada celda...

    cuando el valor de la celda B17 sea correcto, debe traer datos desde otras dos celdas a I16 y H16 y debe recorrer la fila B buscando el valor correcto y repetir la acción 100 veces.

    Sub Macro20()

    Dim file As Integer

    For file = 2 To 100
    If Hoja1.Range("B17").Value = "Office" Then
    Hoja1.Range("I16").Value = Hoja1.Range("B18")
    Hoja1.Range("H16").Value = Hoja1.Range("A17")

    End If

    Next file

    End Sub

    Gracias!

    ResponderEliminar
  39. Hola buenas, muy didáctico tu blog,


    ¿Me podrías ayudar en la generación de una macro en excel que evalúe un rango de celdas y le cambie el formato de la celda a los 63 números mayores del rango de celdas? se debería realizar un bucle que permita evaluar varios conjuntos de celdas. Mil gracias y ojala me puedas ayudar

    ResponderEliminar