# retorno de datos desde un formulario



## Samuel Cano (Sep 27, 2010)

Saludos,

Si fueran tan amables de ayudarme en lo siguiente que necesito hacer (llevo dos días en esto y no doy con la solución):

Mi problema involucra dos formularios: Form1 y Form2

En Form1 utilizo combobox para seleccionar opciones que arman un registro.

Pero si algun combo no tiene el dato necesario, quiero poder invocar a Form2 mediante botón de comando
- capturar ahí los datos faltantes 
- cerrar Form2 y 
- que me regrese a Form1 con los datos capturados para 
- grabarlos y la hoja correspondiente,
- refrescar el combobox y
- ya sea reiniciar la captura o continuarla.

Lo siento, por más que he buscado, no doy como pasar los datos entre formularios.

Cualquier ayuda se agradece.

Su amigo, Samuel.


----------



## Marcelo Branco (Sep 28, 2010)

Samuel,

Algunas perguntas:
Los dos Forms son iguales? 
Tienem los mismos campos?
Hay un boton de comando en Form1 qui llama el Form2, es esto?

M.


----------



## Samuel Cano (Sep 28, 2010)

*20100928 seguimiento Re: retorno de datos desde un formulario*

Marcelo,

Antes que todo, gracias por tu atención.

A lo que preguntas:

1. Los dos Forms son iguales? 
R= Bueno, no son identicos por el tipo de información que se pretende que contengan y tampoco estan "lado a lado" para interactuar con ellos al mismo tiempo (simultáneo).  Por lo demás, si estan diseñados iguales.

Tienem los mismos campos?
R= No.  Form1 está intencionado para capturar unos datos (algunos de ellos en controles combobox). Form2 es mas sencillo y para captura otros datos.

La idea es que si algun dato no esta presente en Form1, al dar clic en un botón en ese mismo formulario se llame a un Form2 (auxiliar) donde se capture el dato requerido y mediante código esa captura se almacene en la hoja de cálculo correspondiente, asi como se agregue al combobox donde se le necesita, quedando enseguida disponible para reiniciar la captura.

3.Hay un boton de comando en Form1 qui llama el Form2, es esto?
R= Si, es correcto.  
El userForm1 es llamado desde un botón en la hoja de cálculo, luego llegado el momento, se llama al userForm2 desde un botón en la primera forma, por lo que queda encima de la primera.

Ayer de madrugada encontré una referencia en internet que habla del paso de parámetros entre formularios declarando variables publicas para que sean visibles por las dos formas, pero claro, como no hay felicidad completa, no había ejemplo; solo la idea, asi que hay que desarrollarla, sin embargo senti que puede ser lo que me sirva.

En resumen: 
Forma1 llama a Forma2
en Forma2 se capturan datos.   Cuando se cierre.
Forma1 manipulará esos datos capturados en Forma2.

Ahora bien: cómo hacer?

Gracias mil.


----------



## Marcelo Branco (Sep 28, 2010)

Samuel,

Si yo lo compreendi corretamente try it

En codigo del boton de Form1 que llama Form2

```
Private Sub CommandButton1_Click()    
    UserForm1.Hide
    UserForm2.Show        
End Sub
```
 
Supondo que Form2 pega datos del rango B2 (ajuste esto para tus necessidade) y pone los datos en TextBox1, ponga en el codigo del boton de Form2

```
Private Sub CommandButton1_Click()
    TextBox1.Value = ActiveSheet.Range("B2")
    UserForm2.Hide
    UserForm1.TextBox1.Value = UserForm2.TextBox1.Value
    UserForm1.Show    
End Sub
```
 
Usando UserForm1.Hide y UserForm2.Hide usted siempe tiene los dos Forms disponibles.

Espero que te ayude

Sorry por los errores en Espanhol 

Saludos

M.


----------



## Marcelo Branco (Sep 29, 2010)

Samuel,

El metodo de la mensage anterior iria borrar todos los datos ya obtenidos en Form1 quando fosse passar os valores de Form2.

El mejor a hacer és passar por el valor de una variable global da seguinte forma:

Crie un modulo standard onde pones

```
Option Explicit
'Declaración de la variable global
Public Valor As String
 
Public Sub IniciaForm()
    'Este procedure llama el Form1
    Valor = ""
    UserForm1.Show    
End Sub
```
 
En el modulo UserForm1

```
Private Sub CommandButton1_Click() 
    'Botón que llama el Form2   
    Me.Hide
    UserForm2.Show    
End Sub
 
Private Sub UserForm_Initialize()
   'Inicializasón del Form1
   'Ponga lo que necessitas     
End Sub
 
Private Sub UserForm_Activate()
   'Passa el valor de la variable global para el campo apropriado de Form1    
    UserForm1.TextBox1.Value = Valor    
End Sub
```
 
En el modulo UserForm2 deve haver un Botón (CommandButton2) para pegar los datos complementares y passar para Form1

```
Private Sub CommandButton2_Click()
    'Passa el valor do rango B3 para Form1 usando una variable global
    'Elija otro(s) rango(s) que quiera
    Valor = ActiveSheet.Range("B3")    
 
    Me.Hide
 
    ' O comando abajo ativa o evento UserForm_Activate() do Form1
    ' que passa el valor da variable global para Form1 TextBox1    
    UserForm1.Show
End Sub
```
 
Espero que esto ayude.

saludos

Marcelo


----------



## Samuel Cano (Sep 29, 2010)

*seguimiento 20100929 Re: retorno de datos desde un formulario*

Muito obrigado Marcelo,

En un módulo de código puse


```
'++ variables para la alta de nuevo remitente en formulario ufAltas 
   '++ capturados en formulario ufAgregaRemite
   Public remiteTituloTexto As String
   Public remiteNombreTexto As String
   Public remiteCargoTexto As String
```

En una hoja de cálculo puse la llamada al userForm1 así


```
Sub cargaFormularioAltas()

   '++ >> FRAGMENTO DE CODIGO <<

    ''muestra formulario para Captura
    ufAltas.Show
End Sub
```

Debo aclarar que userForm1 activa una hoja de cálculo en particular para trabajo

El siguiente codigo esta en un boton del userForm1 y lo que hace es llamar a userForm2


```
Private Sub cmdMas_Click()

   '++ >> FRAGMENTO DE CODIGO <<

   '++ Muestra formulario auxiliar y le pasa el control
   ufAgregaRemite.Show
End Sub
```


Despues userForm2 pasa valores de los cuadros de texto a las variables globales asi


```
cmdAgregarNombre_Click()

   '++ >> FRAGMENTO DE CODIGO <<

   '++  paso de valores a las variables
   remiteTituloTexto = ufAgregaRemite.txtTitulo                 ' (A) TITULO
   remiteNombreTexto = ufAgregaRemite.txtNombre            ' (B) NOMBRE
   remiteCargoTexto = ufAgregaRemite.txtCargo                 ' (C) CARGO

   '++
   Unload Me
End Sub
```

Al descargar de la memoria userForm2 deja visible nuevamente userForm1, por lo que puedo proceder a
-cambiar de worksheet para grabar valores almacenados en variables globales
-regresar a worksheet de trabajo del userForm1 
-actualizar combobox y reiniciar la captura

Es decir: justo lo que necesitaba.


```
Private Sub cmdMas_Click()

   '++ >> FRAGMENTO DE CODIGO <<

   '++ hoja de registro
   Sheets("dbRemiteTurnado").Activate

   '++ determina siguiente fila vacía
   sigFila = Application.WorksheetFunction.CountA(Range("A:A")) + 10

   '++ transfiere los datos a la hoja
   Cells(sigFila, "C") = remiteTituloTexto                        ' (C) TITULO
   Cells(sigFila, "A") = remiteNombreTexto                     ' (A) NOMBRE
   Cells(sigFila, "B") = remiteCargoTexto                        ' (B) CARGO

   '++ limpia variables
   remiteTituloTexto = ""
   remiteNombreTexto = ""
   remiteCargoTexto = ""

   '++
   MsgBox "Remitente agregado.", vbInformation + vbOKOnly, "Aviso"

End sub
```

Marcelo, a mis posibilidades y con tu generosa ayuda he podido resolver este punto del desarrollo, obrigado.

Seguro estoy que hay formas más elegantes de hacer lo mismo y estoy abierto a más ideas.

Un abrazo desde México, Distrito Federal.


----------



## Marcelo Branco (Sep 29, 2010)

*Re: seguimiento 20100929 Re: retorno de datos desde un formulario*



Samuel Cano said:


> Marcelo, a mis posibilidades y con tu generosa ayuda he podido resolver este punto del desarrollo, obrigado.


 
Samuel,

Estoy feliz por tener podido ayudar.

Marcelo


----------



## Greg Truby (Oct 12, 2010)

Hola Samuel y Marcelo,
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-comfficeffice" /><o></o>
Me doy cuenta que ustedes sí llegaron a una solución que funcionó para Samuel. Pero por favor permítame hacer una explicación más amplia porque con el transcurso de los meses y años habrá otra gente leyendo esta hilera y la información hasta el momento está un poco incompleta.
<o></o>
Bien, la pregunta es - ¿cómo hacer que información de un formulario pasa a otro? Uno tiene que tomar en cuenta el alcance o dominio (scope en inglés) de los variables. Uno no necesita ninguna variable global, sino uno puede hacer referencia directo a los controles en el UserForm o si uno va a usar una estructura más avanzada, se puede definir un _Interface_ para el UserForm y definir propiedades de GET para tal interface. Pero eso de interface lo dejamos para otro día.
<o></o>
En el ejemplo abajo el módulo normal tiene la rutina Main que contiene una variable de objeto de tipo ufxl_Padre. Y dentro del módulo de código de ufxl_Padre, la rutina de Click de un botón tiene definido una variable de tipo ufxl_Hijo. El alcance (scope) de ninguna variable es global, ni siquiera hay una de alcance nivel módulo (no module-level variables).<o></o>

Bueno – tenemos dos UserForms: <o></o>
· ufxl_Padre <o></o>
· ufxl_Hijo<o></o>

(Se puede cambiar los nombres de formularios en la misma manera de cambiar nombres de controles, con la ventanilla de propiedades.) Cada UserForm tiene dos cajas de texto. Ufxl_Padre tiene dos botones, uno para mostrar el segundo formulario y otro para terminar.<o></o>

*Código en un módulo normal:*
<o>
	
	
	
	
	
	



```
<o:p>Sub Main()</o:p>
<o:p>  Dim ufP As ufxl_Padre, strMsg As String
 
    Set ufP = New ufxl_Padre
 
    With ufP
        .Show
        Let strMsg = .tbxPadre1 & vbCr & .tbxPadre2
    End With
 
    Set ufP = Nothing
 
    MsgBox strMsg, vbInformation</o:p>
<o:p>End Sub</o:p>
```
</o>
*El código en ufxl_Padre:*
<o>
	
	
	
	
	
	



```
Private Sub btnPadre_OK_Click()
    Me.Hide
End Sub</o:p>
<o:p>Private Sub btnShowForm2_Click()</o:p>
<o:p>  Dim ufH As ufxl_Hijo
 
    Set ufH = New ufxl_Hijo
 
    With ufH
        .Show
        Me.tbxPadre2.Text = .tbxHijo1 & ", " & .tbxHijo2
    End With
 
    Set ufH = Nothing</o:p>
<o:p>End Sub</o:p><o:p>
```
</o>
*El código en ufxl_Hijo:<o></o>*

```
Private Sub btnHijo_OK_Click()
    Me.Hide
End Sub
```


----------



## Marcelo Branco (Oct 13, 2010)

Olá Greg,

Bueno saber que hay soluciones mejores o más sencillas.

Una duda:

```
Dim ufP As ufxl_Padre
```
 
Significa que hás criado una classe ufxl_Padre? 
Lo mismo para ufxl_Hijo?
Se si, como hacerlo?

Tks in advance

M.


----------



## Greg Truby (Oct 13, 2010)

Marcelo Branco said:


> Significa que hás criado una classe ufxl_Padre?


 
Bueno, sí y no. La única cosa que hice fue cambiar los nombre de los Userforms, utilizando el sistema Simonyi para nombrarlos. Pero uno debe de darse cuenta que los Userforms son una especie de *class module* igual a los módulos para hojas y cuadernos. 
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-comfficeffice" /><o></o> 
Eso de hacer el DIM y después el SET ____ = NEW ufxl______ es para evitar un caso de _auto-instantiation_ y controlar la _instantiation_. Usar un nombre específico en vez de llamar el formulario con referencia genérica ayuda a uno estar seguro que uno esté refiriendo al objeto deseado y no una instancia errónea.


----------



## Samuel Cano (Sep 27, 2010)

Saludos,

Si fueran tan amables de ayudarme en lo siguiente que necesito hacer (llevo dos días en esto y no doy con la solución):

Mi problema involucra dos formularios: Form1 y Form2

En Form1 utilizo combobox para seleccionar opciones que arman un registro.

Pero si algun combo no tiene el dato necesario, quiero poder invocar a Form2 mediante botón de comando
- capturar ahí los datos faltantes 
- cerrar Form2 y 
- que me regrese a Form1 con los datos capturados para 
- grabarlos y la hoja correspondiente,
- refrescar el combobox y
- ya sea reiniciar la captura o continuarla.

Lo siento, por más que he buscado, no doy como pasar los datos entre formularios.

Cualquier ayuda se agradece.

Su amigo, Samuel.


----------



## Samuel Cano (Oct 28, 2010)

*Hola Greg..*

Hola Greg,

Agradezco tus notas también, tengo ya el post entero en .pdf en mi biblioteca de consulta para re-leerlo con mas detenimiento.

Me llamó la atención eso de asignar nombres que nos den certeza de a qué se está refiriendo el código.

Desde México:
- Samuel


----------



## galileogali (Oct 30, 2010)

Greg: Simply Masterly !!!

No te olvides de la solucion que denominaste vía "Interface", cuando tengas tiempo, explicala o si andas con poco tiempo agrega algun/os links que refierena el tema....


----------



## Samuel Cano (Sep 29, 2012)

Gracias Greg por la informacion complementaria, te saludo y a Marcelo.


----------

