modificar list1

Iniciado por corlo, 4 Marzo 2020, 23:20 PM

0 Miembros y 1 Visitante están viendo este tema.

corlo

Hola soy corlo
modificar datos de text1,text2 a list1 del formulario 2 al formulario 1
leer datos de list1 a text1, text2 del formulario 1 al formulario 2

aqui dejo el codigo que tengo hasta ahora

en el formulario1




Private Sub Form_Load()
List1.AddItem "jorge" & "               " & "Ramirez"
List1.AddItem "luis" & "                " & "Rodriguez"
List1.AddItem "pedro" & "               " & "Gonzalez"

End Sub



Private Sub List1_DblClick()

'Form2.Text1.Text = List1.List(List1.ListIndex)

Dim i As Integer

Form2.Text1.Text = Mid(List1.Text, 1, InStr(1, List1.Text, " ") - 1)
Form2.Text2.Text = Mid(List1.Text, InStr(List1.Text, " ") + 16)
i = List1.ListIndex
   

Form2.Show
End Sub










y en el formulario 2  esto





Private Sub Command1_Click()
Form1.List1.List(Form1.List1.ListIndex) = Form2.Text1.Text
Form1.List1.List(Form1.List1.ListIndex) = Form2.Text2.Text
Unload Me
End Sub








no logro hacer la modificacion del formulario 2 al formulario 1
gracias


Serapis

#1
La verdad es que resulta confusa tu explicación...
Podías haber empezado por decir algo como:
en el formulario 1 hay una listbox,  un boton y ... lo que sea más...
y en el formulario 2 hay .... lo que sea,
....preferiblemente con nombres MUY distintos, para no generar confusión inecesariamente (tu luego llámalos como te dé la gana).
A veces incluso mejor un par de capturas, si son demasiados elementos termina por dejar claro el asunto.

...pués aclararía bastante cual es tu intención. Ahora mismo es un galimatías que uno tiene que interpretar y esperar a haberlo hecho correctamente. Lo que la mayor parte de las veces supone perder tiempo y es una de las razones por la que muchos decidimos pasar de contestar (mensajes ininteligibles)...

Tampoco dejas claro cual es el objetivo, solo tras 'recrear' la interfaz y el código, lo que observo es que modificas el contenido del listbox, pero ahora no contiene lo previo. De lo que deduzco que lo que intentas es 'editar un ítem' del listbox, donde cada ítem se compone de dos partes, nombre y apellido...

Si es así, tu problema es que sobrescribes una y luego otra vez, el ítem olvidando que se cada ítem se compone de '2 campos', como se aprecia en la imagen, así queda  una vez editado con el código que tienes:




Hay que decir algunas cosas, vayamos primero por la más simple:

Cada item en la lista es un string, cuando se intenta que 'contenga' varios campos de texto, resulta adecuado darle un formato, lo mínimo un separador.
Así por ejemplo, un simple espacio hubiera sido algo muy sencillo y fácil de manejar:
Código (vb) [Seleccionar]

Private Sub Form_Load()
   With List1
       .AddItem "Jorge Ramirez Díaz"
       .AddItem "Luis Rodriguez Moreno"
       .AddItem "Pedro Gonzalez Granado"
   End With
End Sub


Luego la transferencia sus sendos textbox en el form2, es muy sencilla:
Código (vb) [Seleccionar]

Private Sub List1_DblClick()
   Dim i As Integer
   dim txt() as string
   
   txt = split(list1.list(lits1.listindex), " ")
   ' NOTA: al caso acomoda que los 3 textboxes del form 2 formen un array.
   for i= 0 to 2    
        form1.textbox1(i).text = txt(i)
   next  
   
   call Form2.Show (vbmodal)  ' esto impide que sepueda acceder al form1 hasta que se cierre el 2.  
End Sub


(nota que en el form2 ahora tenemos 3 textbox, llamados con el mismo nombre y con índices 0, 1 y 2).
Así cuando ahora pulsemos, en el botón del form2:
Código (vb) [Seleccionar]

Private Sub Command1_Click()
   dim item as string
 
   item = text1(0).text & " " & text1(1).text & " " & text1(2).text
   Form1.List1.List(Form1.List1.ListIndex) = Item
   
   Unload Me
End Sub


Con eso obtienes lo que parece que quieres.


Ahora bien, podría ser que te interese mantener algo más que un espacio de separación, entre el nombre y los apellidos o algún otro elemento añadido en cada ítem.
Se trataría entonces de prefijar un formato, por ejemplo supongamos que el apellido más grande tuviere 20 caracteres... entonces precisamos crear una función que garantice esos 20 caracteres:

Añadir un módulo y pegar esta función allí. El módulo contendrá funcionalidad que puede ser común a ambos forms y a todo el proyecto.
Código (vb) [Seleccionar]

' Funcion: Rellena con un (solo 1) carácter hasta completar el tamaño solicitado, si excede puede forzarse a cortar el sobrante.
'  Parámetros:
'    Valor: El dato a ser modelado.
'    Size: Tamaño solicitado para la cadena devuelta.
'    Delante: Señala a que lado se coloca el relleno (o en caso de sobrar, por donde se retiran).
'    Relleno: Carácter que se utiliza para completar el tamaño (por defecto espacio).
'    Force: Determina que si la cadena de entrada es más larga que los digitos pedidos, (por defecto) cortará el sobrante o lo devolverá tal cual llegó.
'  Devuelve: una cadena con la cantidad de caracteres indicado por 'size', salvo que en origen a la entrada sea mayor y explicitamente no se haya forzado a cortar.
Public Function FormatSizeString(ByRef Valor As String, ByVal Size As Byte, Optional Delante As Boolean, Optional ByVal Relleno As Byte = 32, Optional ByVal Force As Boolean = True) As String
   Dim k As Integer
   
   k = (Size - Len(Valor))
   If (k < 0) Then
       If (Force = True) Then
           If (Delante = True) Then
               FormatSizeString = Right$(Valor, Size)
           Else
               FormatSizeString = Left$(Valor, Size)
           End If
       Else
           FormatSizeString = Valor
       End If
   ElseIf (k > 0) Then
       If (Delante = True) Then
           FormatSizeString = (String$(k, Chr$(Relleno)) & Valor)
       Else
           FormatSizeString = (Valor & String$(k, Chr$(Relleno)))
       End If
   Else
       FormatSizeString = Valor
   End If
End Function



Ahora es más fácil hacer que tu listbox aparezca como si estuviera compuesto por columnas... aunque falta alguna función rutinaria más (la pongo luego):
Código (VB) [Seleccionar]

' esta línea ponerla arriba del todo en el módulo 'module1', que has añadido al proyecto...
private const SIZE_CAMPO as integer = 20

' la función también va en el módulo.
' nota el 'byval en los parámetros de string...
Public Function ComponerItem(ByVal Nombre As String, ByVal Apellido1 As String, ByVal Apellido2 As String) As String
   Nombre = FormatSizeString(Nombre, SIZE_CAMPO)
   Apellido1 = FormatSizeString(Apellido1, SIZE_CAMPO)
   Apellido2 = FormatSizeString(Apellido2, SIZE_CAMPO)
   
   ComponerItem = Nombre & Apellido1 & Apellido2
End Function


Esta función debe llevar aparejado otra equivalente, que hace la operación contraria... deserializa el ítem en sus componentes simples:
Código (VB) [Seleccionar]

' Se da por supuesto que cada item contiene exactamente la cantidad de caracteres precisos,
'  lo cual será cierto si se usó la función 'ComponerItem'.
Public Sub DescomponerItem(ByRef Item As String, ByRef Nombre As String, ByRef Apellido1 As String, ByRef Apellido2 As String)
   Nombre = RTrim$(Left$(Item, SIZE_CAMPO))
   Apellido1 = RTrim$(Mid$(Item, SIZE_CAMPO + 1, SIZE_CAMPO))
   Apellido2 = RTrim$(Right$(Item, SIZE_CAMPO))
End Sub


Veamos como quedaría ahora la carga dle formulario 1:
Código (vb) [Seleccionar]


' ...ahora modificamos la rutina de carga:
Private Sub Form_Load()
   With List1
       call .AddItem( ComponerItem("Jorge", "Ramirez",  "Díaz"))
       call .AddItem(ComponerItem("Luis", "Rodriguez", "Moreno"))
       call .AddItem(ComponerItem("Pedro", "Gonzalez", "Granado"))
       .FontName = "Courier new"   ' si no se pone una fuente monoespaciada, la verticalidad de las columnas, fracasará
      ' y habría que considerar el espacio ocupado por cada carácter, para añadir más o menos espacios,
      ' lo cual es más complejo, lento e inexacto, pués tampoco podemos 'dibujar' en el punto exacto...
      'NOTA: Haz el listbox, lo suficientemente ancho, para que sea vean todos los 'campos'.
   End With
End Sub


Ahora solo falta la reformular la función que toma un ítem para editarlo y la que luego devuelve el ítem editado.
Nota que seguimos delegando funcionalidad en el módulo, simpificando el código dentro de ambos forms, es mas claro y fácil de modificar a futuro, si decides un largo mayor por ejemplo para los nombres basta cambiar el valor de la constante, no hay que tocar nada más en ninguna parte.

Código (vb) [Seleccionar]

Private Sub List1_DblClick()
   Dim n As String, ap1 As String, ap2 As String
   
   Call Module1.DescomponerItem(List1.List(List1.ListIndex), n, ap1, ap2)
   
   With Form2
       .Text1(0).Text = n
       .Text1(1).Text = ap1
       .Text1(2).Text = ap2
       .Show vbModal
   End With
End Sub


Y finalmente el código del botón del form2, que transfiere el ítem editado de vuelta al listbox.
Código (vb) [Seleccionar]

Private Sub Command1_Click()
   Dim item As String
   
   item = Module1.ComponerItem(Text1(0).Text, Text1(1).Text, Text1(2).Text)
   Form1.List1.List(Form1.List1.ListIndex) = item
   
   Unload Me
End Sub


Y así queda y se ve cuando se ejecuta:



Hay una parte fea aún en el código ...la insistencia en list1.listindex...
Sería mejor declarar una variable pública en el module1:
Código (vb) [Seleccionar]

public IndexItem as integer

Al entrar al proyecto IndexItem = -1, y luego con cada click en el listbox, actualizas dicho valor, ahora no hay que referenciar cada vez al listindex del list en el form1...

Finalmente este sería el código de cada fichero con los cambios aplicados en cada uno de ellos:

Para el form1:
Código (vb) [Seleccionar]

Private Sub Form_Load()
   IndexItem = -1
    With List1
       Call .AddItem(ComponerItem("Jorge", "Ramirez", "Díaz"))
       Call .AddItem(ComponerItem("Luis", "Rodriguez", "Moreno"))
       Call .AddItem(ComponerItem("Pedro", "Gonzalez", "Granado"))
       .FontName = "Courier new"   ' si no se pone una fuente monoespaciada, la verticalidad de las columnas, fracasará
      ' y habría que considerar el espacio ocupado por cada carácter, para añadir más o menos espacios,
      ' lo cual es más complejo, lento e inexacto, pués tampoco podemos 'dibujar' en el punto exacto...
   End With
End Sub

Private Sub List1_Click()
   IndexItem = List1.ListIndex
End Sub

Private Sub List1_DblClick()
   Dim n As String, ap1 As String, ap2 As String
   
   If (IndexItem <> -1) Then
       Call Module1.DescomponerItem(List1.List(IndexItem), n, ap1, ap2)
   
       With Form2
           .Text1(0).Text = n
           .Text1(1).Text = ap1
           .Text1(2).Text = ap2
           .Show vbModal
       End With
   Else
       Beep ' no hay ningún ítem seleccionado
   End If
End Sub


Para el form2:
Código (vb) [Seleccionar]

Private Sub Command1_Click()
   Dim item As String
   
   item = Module1.ComponerItem(Text1(0).Text, Text1(1).Text, Text1(2).Text)
   Form1.List1.List(IndexItem) = item
   
   Unload Me
End Sub


y para el módule1:
Código (vb) [Seleccionar]

Public IndexItem                As Integer
Private Const SIZE_CAMPO        As Integer = 20


' nota el 'byval en los parámetros de string...
Public Function ComponerItem(ByVal Nombre As String, ByVal Apellido1 As String, ByVal Apellido2 As String) As String
   Nombre = FormatSizeString(Nombre, SIZE_CAMPO)
   Apellido1 = FormatSizeString(Apellido1, SIZE_CAMPO)
   Apellido2 = FormatSizeString(Apellido2, SIZE_CAMPO)
   
   ComponerItem = Nombre & Apellido1 & Apellido2
End Function

' Se da por supuesto que cada item contiene exactamente la cantidad de caracteres precisos,
'  lo cual será cierto si se usó la función 'ComponerItem'.
Public Sub DescomponerItem(ByRef item As String, ByRef Nombre As String, ByRef Apellido1 As String, ByRef Apellido2 As String)
   Nombre = RTrim$(Left$(item, SIZE_CAMPO))
   Apellido1 = RTrim$(Mid$(item, SIZE_CAMPO + 1, SIZE_CAMPO))
   Apellido2 = RTrim$(Right$(item, SIZE_CAMPO))
End Sub


' Funcion: Rellena con un (solo 1) carácter hasta completar el tamaño solicitado, si excede puede forzarse a cortar el sobrante.
'  Parámetros:
'    Valor: El dato a ser modelado.
'    Size: Tamaño solicitado para la cadena devuelta.
'    Delante: Señala a que lado se coloca el relleno (o en caso de sobrar, por donde se retiran).
'    Relleno: Carácter que se utiliza para completar el tamaño (por defecto espacio).
'    Force: Determina que si la cadena de entrada es más larga que los digitos pedidos, (por defecto) cortará el sobrante o lo devolverá tal cual llegó.
'  Devuelve: una cadena con la cantidad de caracteres indicado por 'size', salvo que en origen a la entrada sea mayor y explicitamente no se haya forzado a cortar.
Public Function FormatSizeString(ByRef Valor As String, ByVal Size As Byte, Optional Delante As Boolean, Optional ByVal Relleno As Byte = 32, Optional ByVal Force As Boolean = True) As String
   Dim k As Integer
   
   k = (Size - Len(Valor))
   If (k < 0) Then
       If (Force = True) Then
           If (Delante = True) Then
               FormatSizeString = Right$(Valor, Size)
           Else
               FormatSizeString = Left$(Valor, Size)
           End If
       Else
           FormatSizeString = Valor
       End If
   ElseIf (k > 0) Then
       If (Delante = True) Then
           FormatSizeString = (String$(k, Chr$(Relleno)) & Valor)
       Else
           FormatSizeString = (Valor & String$(k, Chr$(Relleno)))
       End If
   Else
       FormatSizeString = Valor
   End If
End Function


La siguiente imagen (compuesta) corresponde a este código en ejecución:




Puedes añadir más campos al listbox... pero si el 'ítem' del listbox se vuelve más complejo, conviene al caso mejor usar una estructura para definir cada campo, así como el tamaño de cada campo, que podría ser diferente.
NOTA: que la función que formatea el string, te lo he dejado en previsión de que formatee también textos que son números, indicando el lado donde añadir a la izquierda y el carácter '0' y luego si se quiere añadir espacios a su derecha (una segnda llamada).

Y si además la edición de cada campo es muy diferente, podría entonces usarse una clase en vez de un módulo.
La clase representaría un ítem del listbox, donde al pulsar en el listbox, transfiere dicho ítem a una clase, (no solo sus datos, también el índice que ocupa) y abre el form 2 que recibe una referencia a la clase, y durante su evento 'load', transfiere los datos d ela clase a la interfaz de edició que proporciona el form2, el botón deberían ser 2 botones uno aceptar y otro cancelar, ambos cierran  el form2 cuando se pulsen, la diferencia es que el 'aceptar' coloca de regreso los datos actuales en la clases, y en retorno, el form1 detecta si hubo cambios (una variable llamada así 'Changed = TRUE cuando se pulsa el botón 'Ok' y que se pone a Changed = FALSE cuando se carga el form2, detecta si hubo cambios y e n tal caso actaliza el ítem del listbox.
Más aún, dicha clase podría contener la posibilidad de 'añadir un ítem nuevo inexistente, abriendo el form con valores por defecto (en el caso de nombre y apellidos vacíos, pero si hay números, alguno podría tener cierto valor de entrada prefijado... por ejemplo si hubiere días de la semana, proveer un combobox, donde por defecto el día seleccionado fuere el Lunes (u otro según el caso).

corlo

Hola soy corlo

Gracias nebire por la informacion

tema resuelto