** NORMAS DEL FORO **
Inicio del foro Inicio del foro > Otros de Microsoft: Windows y Office > Excel
  Mensajes nuevos Mensajes nuevos RSS - Ciclo For Each ... Next
  Preguntas frecuentes Preguntas frecuentes  Buscar en el foro   Eventos   Registro Registro  Iniciar sesion Iniciar sesion

Tema cerradoCiclo For Each ... Next

 Responder Responder
Autor
Mensaje
noesystem Ver desplegable
Habitual
Habitual
Avatar

Unido: 24/Septiembre/2008
Localización: Mexico
Estado: Sin conexión
Puntos: 106
Enlace directo a este mensaje Tema: Ciclo For Each ... Next
    Enviado: 21/Agosto/2009 a las 23:37
Buenas Tardes:
Amigos del foro, estoy desarrollando un formulario
para guardar información en una hoja de Excel.
Dicho formulario lo generé en Automático con el UserForm
de VB de Excel.
Una de las columnas de Excel, le he nombrado Contrato
la cual pretendo controlar como registro irrepetible.
Para esto pretendo utilizar un Bucle For Each
Solamente que no comprendo la sintaxis para estructurar
la instrucción.
Pido por favor que algún experto del Foro tomé mi código
y me aconseje como desarrollar el procedimiento.

Private Sub CommandButton1_Click()
Dim RegActual As Integer ' Contador Final para Bucle
Dim rw&&&&&&&&&&&&&&&&&&&&' Contador inicial del Bucle
Dim Repite&&&&&&&&&&&&&& ' Valor lógico para condicionar el IF
Repite = False

' Guardar Registro
Worksheets("CHEQUES_EVENTOS").Select
Range("A12000").Select
Selection.End(xlUp).Select
RegActual = (ActiveCell.Row)
' Validar Folio Cheque repetido
If RegActual > 3 Then
rw = 4
For Each rw In Range(Cells(rw, 1), Cells(RegActual, 1))
If Cells(rw, 1) = TextBox1.Value Then
MsgBox ("Se Repite en el Renglon " & rw)
Repite = True
Exit For
End If
Next
End If

' Se escribe sòlo si Repite es Falso
If Repite = False Then
RegActual = (ActiveCell.Row) + 1
Rows(RegActual).Select
Cells(RegActual, 1) = TextBox1.Value
Cells(RegActual, 3) = TextBox16.Value
Cells(RegActual, 6) = Label39.Caption
End If
End Sub

Aunque el procemiento no me funciona, mi intención es que
el experto que me ayude, comprenda la lógica que estoy
suponiendo que hará el proc.

"Toma del primero al último renglón de la hoja y
valida la primera columna, comparandola con el valor
que trae mi formulario en el Cuadro de Texto: TextBox1
si resulta verdadero, entonces termina el bucle y sólo
avisa con un Mensaje, de lo contrario, escribe en el
último renglón + 1".

Agradezco de antemano la atención al presente. Atte: Noé Avila.

DIOS es DIOS desde que comenzó a ser Matemático!
Arriba
sdgm Ver desplegable
Colaborador
Colaborador
Avatar

Unido: 21/Abril/2005
Localización: Guatemala
Estado: Sin conexión
Puntos: 906
Enlace directo a este mensaje Enviado: 22/Agosto/2009 a las 17:00

Hola, Noé.

Veamos primero cómo hacer funcionar tu código.

He hecho algunas correcciones y comentarios. Revísalos, pruébalos, y luego trataremos de optimizarlo.

Private Sub CommandButton1_Click()
    Dim RegActual As Long  'No uses Integer, tiene un límite muy pequeño: 32767.  Long tiene como limite 2147483648
    Dim rw As Range        'Para recorrer con FOR EACH un rango, necesitas una variable del mismo tipo
    Dim Repite As Boolean  'Para valores lógicos
    Repite = False         'No necesario. Al definir una variable Boolean, ésta recibe el valor inicial FALSE.
   
    ' Guardar Registro
    Worksheets("CHEQUES_EVENTOS").Select
    Range("A12000").Select
    Selection.End(xlUp).Select
    RegActual = (ActiveCell.Row)
    ' Validar Folio Cheque repetido
    If RegActual > 3 Then
        'rw = 4   'No puedes asignar un valor entero a una variable RANGE.
        For Each rw In Range(Cells(3, 1), Cells(RegActual, 1))  'Aquí te faltó una letra "r"
            If CStr(rw.Value) = TextBox1.Value Then
                MsgBox ("Se Repite en el Renglon " & rw.Row)
                Repite = True
                Exit For
            End If
        Next
    End If
   
    ' Se escribe sòlo si Repite es Falso
    If Repite = False Then
        'RegActual = (ActiveCell.Row) + 1   'No necesario
        'Rows(RegActual).Select             'No necesario
        Cells(RegActual + 1, 1) = TextBox1.Value
        'Cells(RegActual, 3) = TextBox16.Value  'Comentado sólo para fines de prueba
        'Cells(RegActual, 6) = Label39.Caption  'Comentado sólo para fines de prueba
    End If
End Sub

 
Ahora veamos algunas ideas para ayudarte a optimizar este código y los próximos que desarrolles.

Primero:

En VBA para Excel, no siempre es necesario que selecciones celdas. Si estás utilizando variables para controlar el número de fila y columna, puedes ejecutar acciones directamente en las celdas. Por eso te comenté las úlitmas líneas de tu código, y modifiqué para que el valor de tu textbox se actualice directamente en la celda, sin necesidad de seleccionarla.

Esto te dará la ventaja adicional que evitarás la "actualización de la pantalla", lo que hace bastante lento el código...

 

Segundo:

En ocasiones, es conveniente que intentes unir instrucciones. Por ejemplo, las líneas:

    ' Guardar Registro
    Worksheets("CHEQUES_EVENTOS").Select
    Range("A12000").Select
    Selection.End(xlUp).Select
    RegActual = (ActiveCell.Row)
 
 
trabajan bien, pero requieren que selecciones celdas varias veces. Eso hace lento tu código, y no es muy elegante. Prueba lo siguiente:
 
    ' Guardar Registro
    RegActual = Worksheets("CHEQUES_EVENTOS").Range("A12000").End(xlUp).Row

y verás que el resultado es el mismo.

 

Tercero:

Trata de establecer límites en función del SW, no de cantidades tentativas. En tu caso, el límite de tus cheques será la celda A12000, pero ¿qué pasaría si alguna vez se sobrepasa? Tu código principiaría a ejecutar acciones indebidas. Prueba reducirlo, por ejemplo, a A10, y verás...

Ahora bien, la instrucción:

    activesheet.rows.count

te devuelve la última fila de la hoja activa, aún cuando migres a la versión 2007 de Excel. Entonces, podrías usar la siguiente instrucción:

    ' Guardar Registro
    RegActual = Worksheets("CHEQUES_EVENTOS").cells(activesheet.rows.count,1).End(xlUp).Row
 

 
 
Cuarto:

Trata de prever lo imprevisto. ¿Qué pasaría si alguna vez (remoto, pero posible) se llenara la hoja completa? Puedes testearlo antes de ejecutar la acción con algo como lo siguiente:

    ' Guardar Registro
    if len( )>0 then
        msgbox "Hoja llena"
        exit sub
    else
        RegActual = Worksheets("CHEQUES_EVENTOS").cells(activesheet.rows.count,1).End(xlUp).Row
        '... y todo lo demás .... 

Bueno, con estas ideas ya tienes para entretenerte por un tiempo. Pruébalas para ver cómo te va.

Saludos!

Cordialmente, David
Arriba
AnSanVal Ver desplegable
Administrador
Administrador
Avatar

Unido: 16/Marzo/2005
Localización: España
Estado: Sin conexión
Puntos: 5375
Enlace directo a este mensaje Enviado: 22/Agosto/2009 a las 20:05
 

Despues de los consejos de David, poco queda por decir, pero aún así; te expongo lo que te habia preparado.

 
Suponiendo que la columna A contiene textos , tu código podría quedar como...

 
Private Sub CommandButton1_Click()

  Dim fila As long  ' Contador Final para Bucle

  Dim celda As Range ' Cada celda del Bucle

  ' Validar Folio Cheque repetido

  fila = Worksheets("CHEQUES_EVENTOS").Range("A12000").End(xlUp).Row

  If fila > 3 Then

    For Each celda In Range("A4:A" & fila)

      If celda.Value = TextBox1.Value Then

        MsgBox """" & TextBox1.Value & """ se Repite en la fila " & _

            celda.Row, vbCritical, "NoeSystem"

        Exit Sub

      End If

    Next

  ' Se escribe sòlo si no existe.

    fila = fila + 1

    Cells(fila, 1) = TextBox1.Value

    Cells(fila, 3) = TextBox16.Value

    Cells(fila, 6) = Label39.Caption

  End If

End Sub

 
 
... un código alternativo (sin bucle) sería...

 
Private Sub CommandButton1_Click()

  Dim fila As Integer ' fila de valor encontrado o próxima fila libre.

  ' Validar Folio Cheque repetido

  If Application.WorksheetFunction.CountIf(Range("$A:$A"), _

      UserForm1.TextBox1.Value) > 0 Then

    fila = Worksheets("CHEQUES_EVENTOS").Range("$A:$A"). _

        Find(UserForm1.TextBox1.Value).Row

    MsgBox "Ya existe """ & UserForm1.TextBox1.Value & """ en la fila " & fila & "."

  Else

    fila = Worksheets("CHEQUES_EVENTOS").Range("A12000").End(xlUp).Offset(1).Row

    Cells(fila, 1) = TextBox1.Value

    Cells(fila, 3) = TextBox16.Value

    Cells(fila, 6) = Label39.Caption

  End If

End Sub

 
 
Aprendemos viendo respuestas de otros, también intentando resolver dudas (intenta ayudar cuando puedas/sepas).

Mi sitio_web con ejemplos Excel.
Arriba
noesystem Ver desplegable
Habitual
Habitual
Avatar

Unido: 24/Septiembre/2008
Localización: Mexico
Estado: Sin conexión
Puntos: 106
Enlace directo a este mensaje Enviado: 25/Agosto/2009 a las 23:27
Buenas tardes,
Gracias a los miembros del foro que han dedicado su
tiempo a atender mi consulta.
Hice una recopilación de las sugerencias que me han
hecho y finalmente quedó así:



Private Sub CommandButton1_Click()
Dim RegActual As Long
Dim Rw As Range
Dim Repite As Boolean
Repite = True

' Guardar Registro
RegActual = Worksheets("CHEQUES_EVENTOS").Cells(ActiveSheet.Rows.Count, 1).End(xlUp).Row
Range("A" & RegActual).Select
' Validar Folio Cheque repetido
If RegActual >= 3 And Val(TextBox1.Value) > 0 Then
For Each Rw In Range(Cells(4, 1), Cells(RegActual, 1))
If CStr(Rw.Value) = TextBox1.Value Then
MsgBox "Ya Existe el Cheque """ & UserForm1.TextBox1.Value & """ en la fila " & _
Rw.Row & ".", vbCritical, "NoeSystem"
Repite = True
Exit For
End If

Repite = False
Next
End If
' Se escribe sòlo si Repite es Falso
If Repite = False Then
Cells(RegActual + 1, 1) = TextBox1.Value
Cells(RegActual + 1, 3) = TextBox16.Value
Cells(RegActual + 1, 6) = Label39.Caption
End If
End Sub

(Pude haberlo hecho mas técnico, con sus consejos;
pero conforme vaya aprendiendo a aplicar las funciones
y los métodos, sabré apreciar las instrucciones compuestas).
Atte: Noé Avila.
Un agradecimiento al Colaborador David, quien aparte de
su sugerencia, incluye algunos consejos para los iniciados.
DIOS es DIOS desde que comenzó a ser Matemático!
Arriba
 Responder Responder
  Compartir tema   

Ir al foro Permisos de foro Ver desplegable