Cómo copiar datos de TextBox, ComboBox, y Lables de formulario según valor de Checkbox a columnas en forma vertical consecutiva?

Necesito de su valiosa ayuda, tengo un problema para copiar datos de un formulario a las columnas de una hoja de excel en forma vertical cuando el checkbox del formulario está con check (marcado), es decir que cuando se ingresa un documento que tiene más de un detalle, se tiene que marcar el checkbox para que habilite los demás textbox, combobox y labels, al querer guardar los datos ingresados no guarda nada. El código lo programé en dos partes, la primera parte, cuando el checkbox no está marcado, esta parte del código sí guarda los datos correctamente, pero la segunda parte, cuando el checkbox está marcado, no funciona.

De antemano les agradezo la ayuda que me puedan brindar. Gracias.

He tratado de enviar por este medio el código para que lo puedan revisar pero no me permite enviarlo, ¿será por qué el código es extenso?, si es así.

2 Respuestas

Respuesta
1

Cuando un código se extiende tanto que te lleva a hacer esas escaleras con End IF... hay algo que está mal. Se supone que la programación nos tiene que aliviar el trabajo no aumentarlo.

Te dejo un par de notas de instrucciones que no están mal, no dan error. Solo para que nadie intente copiarlo y usarlo así como está ;)

Siendo tan extensa tu codificación te vendrá bien hacer un poco de 'claridad':

1- Si estás trabajando en un solo UF no hace falta agregar la expresión ME...

Me.LblNumero01.Caption = Sheets("REGISTROS").Range("D" & F1).Value

Eso solo va en ocasiones especiales. Alguien una vez lo usó y ahora nadie se anima a quitarlo ;)

2- Todas tus instrucciones mencionan a la hoja REGISTROS. Aquí podrías aligerarlo utilizando un bucle del tipo: With.... End With. Fijate que solo se deja el punto ... el nombre de la hoja se coloca al inicio del bucle.

With Sheets("REGISTROS")
    LblDocSerieNum.Caption = .Range("A" & F).Value
    CmbDocumento.Value = .Range("B" & F).Value
    TxtSerie.Value = .Range("C" & F).Value
    TxtNumero.Value = .Range("D" & F).Value
    TxtFecha.Value = .Range("E" & F).Value
    'sigue......
End With

3- No necesitas declarar n variables para ir teniendo el valor de F1 +  n

Para estas 2 instrucciones sería:

Me.LblDocSerieNum01.Caption = Sheets("REGISTROS").Range("A" & F1).Value
Me.LblDocSerieNum02.Caption = Sheets("REGISTROS").Range("A" & F1 + 1).Value
Me.LblDocSerieNum03.Caption = Sheets("REGISTROS").Range("A" & F1 + 2).Value

4- Aquí nuevamente se podría utilizar un bucle del tipo For x = 1 to 10 .... Next . Pero en tu caso lo voy a dejar pasar porque el número de los Label requiere de un algoritmo que será difícil de explicarte.

5- Al registrar coloca la 1ra condición y al finalizar agrega EXIT SUB para cerrarlo y no confundirte con la 2da condición:

'1ra Parte: Cuando el documento no tiene más detalle, (ChkDetalleDoc no está seleccionado)
'=========================================================================================
If ChkDetalleDoc.Value = False Then
    'Se verifica que los campos obligatorios no estén vacíos
    If Trim(CmbDocumento.Text) = "" Then
    MsgBox "Ingrese el tipo de documento", vbInformation, "Atención"
'sigue hasta estas últimas
       Sheets("INGRESO").Select
       Me.CmbDocumento.SetFocus
       Exit Sub     'Else   aquí se termina la 1er condición y se sale
End If
'2da Parte: Cuando el documento tiene más detalle, (ChkDetalleDoc está seleccionado)
'===================================================================================
If ChkDetalleDoc.Value = True Then
'todas las instrucciones
End IF

6- Al hacer control (en 1ra y 2da parte) debes finalizar con los End IF allí ... luego empezarás a realizar los pases.

'2da Parte: Cuando el documento tiene más detalle, (ChkDetalleDoc está seleccionado)
'===================================================================================
If ChkDetalleDoc.Value = True Then
    'Se verifica que los campos obligatorios no estén vacíos
    If Trim(CmbDocumento.Text) = "" Then
         MsgBox "Ingrese el tipo de documento", vbInformation, "Atención"
         Exit sub
    ElseIf Trim(TxtNumero.Text) = "" Then
       MsgBox "Ingrese el número del documento", vbInformation, "Atención"
    ElseIf Trim(TxtFecha.Text) = "" Then
       MsgBox "Ingrese la fecha de emisión", vbInformation, "Atención"
       Exit Sub
     'siguen los ElseIF .... Exit Sub
     End If
    'Se concatena el contenido del combobox (Documento) con los 2 textbox (Serie - Número) y el NºRUC
    'CABECERA

7- Para evitar la escalerita de End IF podrías dejar las consultas de este modo, donde al estar en 1 sola instrucción queda cerrado (no necesitas End If).

    'DETALLE
    If TxtFecha01 <> "" Then LblDocSerieNum01 = LblDocSerieNum & "/" & "A"
    If TxtFecha02 <> "" Then LblDocSerieNum02 = LblDocSerieNum & "/" & "B"
    If TxtFecha03 <> "" Then LblDocSerieNum03 = LblDocSerieNum & "/" & "C"

8 - Y ahora viene el problema puntual. En DETALLE estás enviando a la misma celda ("A" & libre) diferentes campos por lo que solo te quedará el último.

 'DETALLE
       Range("A" & libre) = LblDocSerieNum01
       Range("A" & libre) = LblDocSerieNum02
       Range("A" & libre) = LblDocSerieNum03

Seguramente querrás enviarlo a la col A pero uno debajo del otro, por lo que el arreglo sería:

 'DETALLE
       Range("A" & libre) = LblDocSerieNum01
       Range("A" & libre + 1) = LblDocSerieNum02
       Range("A" & libre + 2) = LblDocSerieNum03

Espero que este mini-curso VBa te sea de utilidad. Desde la sección Macros de mi sitio podrás descargar más ejemplos.

Cuando tengas todo rearmado podrás dejar nuevas consultas puntuales. No olvides valorar éstas antes.

Muchas gracias Elsa por tu ayuda, haré las correcciones que me indicaste.

Buen día estimados Elsa y Abraham, hice las correcciones según sus indicaciones, pero en el código de la 2da parte que copia el detalle del documento (cuando el ChkDetalleDoc está seleccionado), éste copia los datos del formulario, pero en la hoja Registros, desplaza las filas hacia abajo la suma de las cantidades del detalle que haya ingresado al documento, es decir, como en el código se le suma +1, +2, +3....+10 a la variable libre:

Range("A" & libre + 1) = LblDocSerieNum01

Range("A" & libre + 2) = LblDocSerieNum02

Range("A" & libre + 3) = LblDocSerieNum03

Entonces, si yo ingreso 3 detalles, la suma de filas que me desplaza según el código serían 6 (1+2+3) y si a eso se le suma 1 más de la cabecera, serían 7 filas en total. En el link del archivo adjunto, he hecho una copia de la hoja Registros, con el nombre Registros (2) para que vean cómo estaban los datos (Antes), y en la hoja Registros cómo quedaron los datos desplazados (Después).

O es que algo no he hecho bien?, por favor les agradecería mucho me continúen ayudando.

https://drive.google.com/file/d/1P4yN16FBrQD4Z-x4Pb0Z30LZu-Zp86H4/view?usp=sharing

En esa sección de código lo primero que hay que hacer es saber cuántos de los 10 controles tienen datos, para no pasar los 10 (con o sin valor) tal como lo estás haciendo ahora.

Para ello solo miraré los de Fecha (puede ser cualquier concepto que tenga obligatoriedad) . A continuación de la Cabecera y justo por encima del texto DETALLE irán las siguientes instrucciones:

       'calcular la cant de detalles a registrar
       canti = 0
       For Each ct In Frame5.Controls
            If Left(ct.Name, 8) = "TxtFecha" Then
                If ct.Value <> "" Then canti = canti + 1
            End If
        Next ct
       'DETALLE

A continuación, en cada grupo de columnas (desde A hasta Y) solo necesitas incrementar la variable 'libre' desde 1 hasta el total acumulado en la variable 'canti'.

Y para esto utilizaremos otro bucle, considerando que podemos tomar parte del nombre de los controles e ir incrementando también de 1 hasta la cantidad deseada (***)

En lugar de todo lo que aparece como

        'DETALLE
        Range("A" & libre + 1) = LblDocSerieNum01
        Range("A" & libre + 2) = LblDocSerieNum02

hasta la línea que dice:  Range("Y" & libre + 10) = TxtObservacion10

debes dejar solo esto:

For i = 1 To canti
            Range("A" & libre + i) = Controls("LblDocSerieNum0" & i).Caption
            Range("B" & libre + i) = Controls("LblDocumento0" & i).Caption
            Range("D" & libre + i) = Controls("LblNumero0" & i).Caption
            Range("E" & libre + i) = Controls("TxtFecha0" & i).Value
            Range("F" & libre + i) = Controls("LblProveedor0" & i).Caption
            'completar con el resto hasta la col Y
        Next i

(***) Como podrás observar puedo utilizar la variable 1 desde 1 hasta 10 si todos los controles tienen por nombre, por ejemplo, TxtFecha0 & i

Es decir que debes cambiarle el nombre a los últimos controles para que sigan esta regla y se llamen para el grupo fecha: TxtFecha010

Nota: me pareció que queda una fila vacía entre el último registro y el primer pase de la cabecera ... pero este tema por favor comentaselo a Abraham si no lo pode´s resolver... ya he hecho bastante hasta aquí.

PD) Tu formulario está muy bonito visualemente pero adolece de muchísimos errores de programación. Seguramente faltarán más detalles aún... por favor inicia nuevas consultas por cada tema .

Gracias nuevamente por tu ayuda estimada Elsa, también te agradezco por ser sincera con tu opinión con respecto a mi proyecto, que te haya gustado la interfaz gráfica y que hayas detectado los errores en su programación, espero me sepas comprender ya que yo no soy programador y no tengo amplios conocimientos de VBA, por el contrario son muy limitados, y si lo he podido "armar" hasta este punto, gracias a DIOS, ha sido por los códigos que encontré en internet y los fui adaptando para lo que necesitaba, y ahora lo estoy mejorando con la ayuda de ustedes, por lo cual les estoy muy agradecido, pero tampoco quisiera causarles molestia solicitándoles me sigan ayudando, no quiero caerles molestoso o pesado. Que tengas un excelente día.

No nos molestan las consultas, para eso estamos aquí colaborando dentro de nuestras posibilidades.

Es muy meritorio lo que has hecho por eso me explayé en marcarte los principales puntos a modificar.

Solo quería aclarar que a partir de ahora con el código bastante pulido, vayas realizando una consulta por vez, en nuevas entradas donde en el título dejes idea de lo que necesitas para que luego con el buscador sea posible que otros usuarios también encuentren solución a iguales problemas.

Sdos!

Estimada Elsa, te agradezco por tu ayuda, el último código que me proporcionaste, estuvo excelente, por fin se pudo guardar los datos de manera correcta, ahora tengo otro inconveniente con el código de los botones de Eliminar, Actualiza, Anterior y Siguiente, como te habrás dado cuenta, en mi formulario, todos esos botones están programados y cumplen bien sus funciones pero solo con la cabecera de los documentos, más no con los detalles de los mismos.

En todos esos botones intervienen el Do While Loop, que verifican una sola condición (la del código principal, es decir, de la cabecera del documento), y no sé como hacer que el Do While Loop me evalué las otras condiciones (la de los códigos secundarios, es decir, del detalle del documento). 

Siguiendo tu recomendación, hice otra pregunta con referencia a lo que te comenté: "Usar Do While Loop con varias condiciones para eliminar filas y actualizar datos desde un formulario vba Excel"

No sé si me podrías volver ayudar, si no es mucha molestia, disculpa?.

Gracias, que tengas un buen día.

Respuesta
1

Coloca tu archivo en "Google Drive" o "OneDrive" o "Dropbox" o similar, así lo podremos ver y entenderte mejor para ayudarte más rápido.

Salu2

Abraham Valencia

Estimado Abraham, no sé si te llegó el link que me solicitaste, el mensaje lo envié anteriormente a través del botón que dice "ENVIAR GRACIAS", ahora lo estoy enviando nuevamente, por si acaso, a través del botón "PEDIR MÁS INFORMACIÓN". Si no recibiste el mensaje, te escribí que los otros botones del formulario (Actualizar, Eliminar, Anterior y Siguiente) solo funcionan cuando el documento que se ingresó no tiene detalle, y los labels (LblDocSerieNum01...10, LblDocumento01...10, LblNumero01...10, LblProveedor01...10) se encuentran debajo del frame "DETALLE DEL DOCUMENTO".

Este es el link para que descargues el archivo: https://drive.google.com/file/d/15FtpH9KH5Nz8TtWWP6dN9yO_mheU2F9p/view

He visto el código de tu botón "Registrar" y cuando tu "CheckBox" está activado se va (casi) directamente al final (o sea, termina el proceso - lo he podido detectar agregando MsgBox en la rutina) ¿Por qué? Has abusado de los "If-Else" y es muy difícil detectar en que momento se pierde el proceso, hay que reordenar, aunque suene medio fuerte, (casi) todo para que puedan coincidir los "If" con los "Else" y los "End If".

El proceso general debería quedar algo así:

'Primera verificación (¿y quizá única?) de objetos llenos/vacíos

If ChkDetalleDoc.Value = True Then

'Aquí el proceso correspondiente

'Exit sub

Else

'Si ya hay un "If" con el checkbox en False, no es necesario un "If" más, basta el "Else"

End If

End Sub

Otra cosa más, cuando lo (re)ordenes, en la parte de llenar varios campos, si a todos les colocas:

Range("A" & libre) = LblDocSerieNum01
Range("A" & libre) = LblDocSerieNum02
Range("A" & libre) = LblDocSerieNum03

Simplemente se colocarán uno encima de otros, lo correcto es:

Range("A" & libre + 1) = LblDocSerieNum01
Range("A" & libre + 2) = LblDocSerieNum02
Range("A" & libre + 3) = LblDocSerieNum03

Etc.

Y ojo, para todos los casos.

Abraham Valencia

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas