Páginas (3): 1 2 3   
Shell   14-03-2024, 13:51
#1
Buenos días!

Estoy realizando un ejemplo con un GridView que tengo "algunos" nombres de escritores, poetas con su fecha de nacimiento y la de fallecimiento.

Actualmente solo estoy ordenado la columna de las fechas donde hago click.
Pero me encuentro con el problema de que cuando uso el evento Data no me muestra los cambios si "uso" el array que contiene todo los datos.
Solo lo hace la primera vez.

El gridview si lo hace si lo hago directamente, cambiando su contenido en el evento Sort. ( En este caso ).
'Comentar una opción u otra, para ver las diferencias. Ahora mismo usa la modificación del contenido directamente del gridview.

Código fuente:

Código:
' Gambas class file

'Fecha MM/DD/YYYY

Private nombres As String[][] = [
  ["Federico García Lorca", "06/05/1898", "08/18/1936"],
  ["Miguel de Unamuno", "09/29/1863", "12/31/1936"],
  ["Rosalía de Castro", "02/23/1837", "07/15/1885"],
  ["José Martínez Ruiz", "06/08/1873", "03/02/1967"],
  ["Pío Baroja y Nessi", "12/28/1872", "10/30/1956"]]

Private titulos As String[] = ["Nombre del autor", "Fecha de nacimiento", "Fecha de fallecimiento"]

Public Sub Form_Open()

  With Me
    .Arrangement = Arrange.Vertical
    .Spacing = True
    .Margin = True
    .Title = "Ordenar por fechas"
  End With

  With grd
    .Expand = True
    .Mode = Select.Single
    .Sorted = True
  End With

  ConfigurarGrid()

End

Public Sub ConfigurarGrid()

  With grd
    .Font = Font["Noto Sans,False,10"]
    .Columns.Count = 3
    .Columns[0].Title = titulos[0]
    .Columns[0].Expand = True
    .Columns[1].Title = titulos[1]
    .Columns[1].Expand = True
    .Columns[1].Alignment = Align.Center
    .Columns[2].Title = titulos[2]
    .Columns[2].Expand = True
    .Columns[2].Alignment = Align.Center
    .Header = grd.Both
    .Rows.Count = nombres.Count
  End With

End

Public Sub btnSalir_Click()

  Me.Close

End

Public Sub grd_Data(Row As Integer, Column As Integer)

  'El array nombres se muestra en el grid

  grd[Row, Column].Text = nombres[Row][Column]

End

Public Sub grd_Sort()

  Dim afechas As New Date[]
  Dim asortfechas As New Date[]
  Dim avalores As New String[][] 'Contendrá todos los valores del gridview (más adelante)

  If grd.Columns.Sort > 0 Then
    'Si el contenido de la columna se parece a una fecha
    For nx As Integer = 0 To grd.Rows.Max
      afechas.Add(CDate(grd[nx, grd.Columns.Sort].Text))
    Next

    asortfechas = afechas.Copy()
    asortfechas.Sort(IIf(grd.Columns.Ascending, gb.Ascent, gb.Descent))

    For n As Integer = 0 To asortfechas.Max

      '¿ No se supone que estoy actualizando el array ?
      'Entonces,¿ por qué no cambia los valores en el gridview en el evento data ?.

      'grd.columns.sort, es por la columna que se ordena

      '1ª Opción
      'Modificar el array nombres.
      'nombres[n][grd.Columns.sort] = asortfechas[n]

      '2ª Opción. Mostrar directamente en el gridview el contenido del array asortfechas
      grd[n, grd.Columns.Sort].Text = asortfechas[n]

    Next

  Else
    'Si el contenido de la columna no se parece a una fecha lo mostramos en la consola por ahora
    For n As Integer = 0 To grd.Rows.Max
      Print grd[n, grd.Columns.Sort].Text
    Next
    Print
  Endif

  'Intento de refrescar el gridview para refrescar su contenido, en caso de usar la 1ª opción
  'grd.Refresh()

End

Y el código. Todavía tengo que mostrarlo todo junto, pero por ahora prefiero entender el motivo de que no funciona
si cambio el array de array nombres, que no se actualice luego en el evento data del gridview.

Algo que he visto raro, es que cuando muestro los nombres de los escritores en la consola, se añade dos saltos de línea al principio,
cuando lo hace por primera vez. Huh


Saludos
Última modificación: 20-03-2024, 17:09 por Shell.

"El conocimiento es la mejor inversión que se puede hacer" - Abraham Lincoln
Shordi   14-03-2024, 14:07
#2
El evento data sólo trabaja con celdas, no con columnas y el column[x].sort sólo cambia la flechita de la cabecera.
Te remito a este video tutorial donde se explica cómo ordenar un array multidimensional y plasmarlo en un Gridview:


saludos

No podemos regresar
Shell   14-03-2024, 15:00
#3
Jeje, llevo días si y días no viendo todo los tutoriales en los que expandiste la clase GridView.
Lo dejé en su día y estos días los volvía retomar. Ese vídeo en concreto es que el estoy repasando.
 
(14-03-2024, 14:07)Shordi escribió: El evento data sólo trabaja con celdas, no con columnas y el column[x].sort sólo cambia la flechita de la cabecera.

Debo ser muy burro.
Se esta asignando a "cada celda" el contenido del array nombres, ya que se ha variado.
Si se varía este, el cambio debería reflejarse en las celdas , ¿ no ?. Confused

El column.sort da como resultado un número. Prueba. Angel
 
Cita: 
Te remito a este video tutorial donde se explica cómo ordenar un array multidimensional y plasmarlo en un Gridview:

También usas un método para ordenarlo. Pero puede que ese método no funcione con fechas.
Intenta ordenar una columna de fechas, usando Sort y sus formas de ordenar, creo que no funcionaba correctamente.

Por eso decidí usar directamente un array de Dates y luego su método sort.

Y unos de los principales problemas que hay que entender es:

En Gridview solo se muestran "datos" (probablemente cadenas).
Todo el "meollo" con lo que se trabaja, los cambios, ordenaciones se hacen en otro lugar, un procedimiento, una función.

Hay que entender también que cada proyecto es un mundo, claro.

 

Vale. Lo hice funcionar con la ayuda de tu videotutorial y cambiando cosas.
Ahora tengo que modificar cosas para que todo se quede ordenado.

( Ahora las fechas no son correctas , es solo un ejemplo de ordenación ). Smile

[Imagen: UgmE2KS.png]

He tenido que cambiar el contenido de Colum_Click y el Sort.
(No es una clase ).

Código:
Public Sub grd_ColumnClick(Col As Integer)

  Dim n As Integer
  Dim sDown As String
  Dim sUp As String

  sDown = String.Chr(Int(&2B07)) 'Flecha hacia abajo. Ordenada de arriba a abajo
  sUp = String.Chr(Int(&2B06)) 'Flecha hacia arriba. Ordenada de abajo a arriba

  If InStr(grd.Columns[col].Title, sDown) Then 'Ya estaba ordenada
    For n = 0 To grd.Columns.Max
      grd.Columns[n].Title = titulos[n] 'Limpiamos todos los titulos
    Next
    grd.Columns[col].Title = titulos[col] & " " & sUp 'añadimos la flecha
    aSort(col, gb.Descent)
  Else
    For n = 0 To grd.Columns.Max
      grd.Columns[n].Title = titulos[n] 'Limpiamos todos los titulos
    Next
    grd.Columns[col].Title = titulos[col] & " " & sDown 'añadimos la flecha
    aSort(col, gb.Ascent)
  Endif
  grd.Clear()
  grd.Rows.Count = nombres.Count

End

Public Sub aSort(nColum As Integer, nMode As Boolean)

  Dim afechas As New Date[]
  Dim asortfechas As New Date[]
  Dim avalores As New String[][] 'Contendrá todos los valores del gridview (más adelante)

  If nColum > 0 Then
    'Si el contenido de la columna se parece a una fecha
    For nx As Integer = 0 To grd.Rows.Max
      afechas.Add(CDate(grd[nx, nColum].Text))
    Next

    asortfechas = afechas.Copy()

    asortfechas.Sort(nMode)

    For n As Integer = 0 To asortfechas.Max
      nombres[n][nColum] = asortfechas[n]
    Next

  Else
    'Si el contenido de la columna no se parece a una fecha lo mostramos en la consola por ahora
    For n As Integer = 0 To grd.Rows.Max
      Print grd[n, nColum].Text
    Next
    Print
  Endif

End

Ahora tengo que comprobar los indices.
Adjunto el código con cambios hasta ahora.

Saludos
Última modificación: 16-03-2024, 11:55 por Shell.

"El conocimiento es la mejor inversión que se puede hacer" - Abraham Lincoln
Shell   14-03-2024, 18:26
#4
Encontré otra posibilidad usando el sorted de Gambas ( Mientras se pueda aprovechar ).
Añadí la conversión de formato de fecha en el Data del GridView.
Y solucioné el problema que al cambiar el array se mostrase correctamente en el GridView.

Código:
Public Sub grd_Data(Row As Integer, Column As Integer)

  'El array nombres se muestra en el grid

  If Column >= 1 Then
    'Para mostrarlo en una fecha local
    grd[Row, Column].Text = Format(Date(nombres[Row][Column]), "dd/mm/yyyy")
  Else
    grd[Row, Column].Text = nombres[Row][Column]
  Endif

End

Public Sub grd_Sort()

  Dim afechas As New Date[]
  Dim asortfechas As New Date[]
  Dim avalores As New String[][] 'Contendrá todos los valores del gridview (más adelante)

  If grd.Columns.Sort > 0 Then
    'Si el contenido de la columna se parece a una fecha

    For nx As Integer = 0 To grd.Rows.Max
      afechas.Add(CDate(nombres[nx][grd.Columns.sort]))
    Next

    asortfechas = afechas.Copy()
    asortfechas.Sort(IIf(grd.Columns.Ascending, gb.Ascent, gb.Descent))

    For n As Integer = 0 To asortfechas.Max
      nombres[n][grd.Columns.sort] = asortfechas[n]
    Next

  Else
    'Si el contenido de la columna no se parece a una fecha lo mostramos en la consola por ahora
    ' For n As Integer = 0 To grd.Rows.Max
    '   Print grd[n, grd.Columns.Sort].Text
    ' Next
    ' Print
  Endif

  'Esto es necesario
  grd.Clear()
  grd.Rows.Count = nombres.Count

End

Todas las ideas son buenas, naturalmente cada uno lo intenta hacer a su manera.

"El conocimiento es la mejor inversión que se puede hacer" - Abraham Lincoln
Shordi   14-03-2024, 18:59
#5
No entiendo qué quieres hacer. Si haces click en la fecha de nacimiento, por ejemplo, y se ordena sólo esa columna, toda la información del GridView queda inservible porque las celdas no coinciden dentro de la misma fila. Hay que reordenar todo el grid, no solo la columna

Cita:Encontré otra posibilidad usando el sorted de Gambas ( Mientras se pueda aprovechar ).
Añadí la conversión de formato de fecha en el Data del GridView.
Y solucioné el problema que al cambiar el array se mostrase correctamente en el GridView
Conejudo. Yo no utilizo el sorted del GridView porque es excluyente, es decir sólo se puede ordenar por una columna. En este vídeo tienes el siguiente paso de ordenación por múltiples columnas.

Este es el aspecto del ejemplo del vídeo, se ordena por País Ascendente y luego dentro de cada país por ciudad también Ascendente.

[Imagen: xsqiiob.png]


No quise juntarlo todo en un sólo video por el tiempo que llevaba y la complejidad (a destacar el sistema que inventé para ordenaciones inversas que me resultó muy divertido con las funciones AntiWord y AntiNumber)...

Saludos
Última modificación: 14-03-2024, 19:56 por Shordi.

No podemos regresar
Shell   16-03-2024, 11:54
#6
Al final lo he resuelto.

En este ejemplo ya funciona todo. Lo he dividido en dos formularios.

En el primero tiene cadenas ( los nombres de los autores ) y fechas. En el segundo formulario, ordena solo cadenas

Entre la propia naturaleza del control, los métodos de ordenación ( que es la madre del cordero ) y según lo que quieras ordenar,
se complica.
 
(14-03-2024, 18:59)Shordi escribió:
Cita: 
Conejudo. Yo no utilizo el sorted del GridView porque es excluyente, es decir sólo se puede ordenar por una columna

Al final lo hice sin sorted. Es que no acabo de entender, "cuando" y "donde" puedo poner a True, su propiedad Sorted.
Me gusta más tu forma de ordenar por que haces más cosas, ordenas por distintos conceptos.

Para una ordenación simple (que no lo es), si se podría utilizar el método que uso o usar sorted.
 
(14-03-2024, 18:59)Shordi escribió: tienes el siguiente paso de ordenación por múltiples columnas.

Eso es lo interesante. Aunque me he liado un poco con tu código. ( Excuse me ).
A medida que vas haciendo el vídeo voy añadiendo el código, modificaciones propias.

Tu código es más extenso (es una clase), hace más cosas. Hay cosas que me funcionaban y otras no.
La ordenación. Tengo que repasar los ejemplos que estoy haciendo con tus videotutoriales
y encontrar el motivo de que no funcione algo.

Cuando de 300 registros creas 9000, ostras. Era mejor dejarlo solo con los 300 que es lo que trae
el csv y no complicarte, en ese caso no se puede usar el reloj, claro. Tira de procesador , un momento.

Tal como he acabado los dos ejemplos, funcionan ambos. Puede que no este optimizado del todo.
Me he valido de un array para indices, que se guarda en el, los cambios de orden de los registros.

Por otra parte no es lo mismo ordenar cadenas que fechas. ( Te tienes que valer de algo más para ordenar fechas)

En los ejemplos que yo he visto de tus videotutoriales, trabajas con cadenas y números que son cadenas.
( Puede que no hayas visto el problema de lo que es trabajar con fechas ).

Te muestro dos códigos fuentes.

En el ordeno solo columnas con cadenas.

Código:
Public Sub OrdenarValores(Columna As Integer, modo As Boolean)

  Dim i As Integer
  Dim tcadenas As New String[]
  Dim scadenas As New String[]
  Dim testvalores As New String[][]

  Dim aotro As String[][]

  Dim fila As Integer
  Dim aindices As New Integer[]

  testvalores = nombres.Copy()

  For i = 0 To testvalores.Max
    tcadenas.Add(testvalores[columna])
  Next

  scadenas = tcadenas.Copy()

  'Descendente es True y ascendente es False
  If modo Then
    scadenas.Sort(modo + gb.Natural).Reverse()
  Else
    scadenas.Sort(modo + gb.Natural)
  Endif

  For i = 0 To tcadenas.Max
    aindices.Add(scadenas.Find(tcadenas))
  Next

  'Se han ordenado las cadenas y creado indices para ver los cambios de lugar

  aotro = testvalores.Copy()

  For fila = 0 To testvalores.Max
    Swap testvalores[fila], aotro[aindices.Find(fila)]
  Next

  nombres.Clear
  nombres = testvalores
  grd.Clear()

End

Ahora el más complicado. Como existen fechas y sé que la columna 1 y la 2 son fechas uso una forma para
ordenar las fechas y otro para las cadenas o nombres de los autores.

Lo importante de todo es saber cuál es el orden que se ha cambiado en los registros, cosa que queda
registrada en el array aindices. ( Eso en ambos ejemplos ).

Aquí se añade más código claro.

Código:
Public Sub OrdenarValores(Columna As Integer, modo As Boolean)

  Dim i As Integer
  Dim tfechas As New Date[]
  Dim sfechas As New Date[]
  Dim tcadenas As New String[]
  Dim scadenas As New String[]
  Dim testvalores As New String[][]
  Dim fila As Integer
  Dim aindices As New Integer[]
  Dim aotro As New String[][]

  testvalores = nombres.Copy()

  If Columna = 1 Or Columna = 2 Then
    'Se parecen a fechas. lSon las columnas donde hay fechas

    For i = 0 To testvalores.Max
      tfechas.Add(Date(testvalores[Columna]))
    Next

    sfechas = tfechas.Copy()
    'Descendente es True y ascendente es False
    If modo Then
      sfechas.Sort(modo).Reverse()
    Else
      sfechas.Sort(modo)
    Endif

    For i = 0 To tfechas.Max
      'En el array aindices se almacena los cambios de los lugares que ocupan ahora en el array sfecha ordenado
      aindices.Add(sfechas.Find(tfechas))
    Next

    'Se han ordenado las fechas y creado indices para ver los cambios de lugar

  Else If columna = 0 Then
    'Es un texto
    For i = 0 To testvalores.Max
      tcadenas.Add(testvalores[columna])
    Next

    scadenas = tcadenas.Copy()
    'Descendente es True y ascendente es False
    If modo Then
      scadenas.Sort(modo + gb.Natural).Reverse()
    Else
      scadenas.Sort(modo + gb.Natural)
    Endif

    For i = 0 To tcadenas.Max
      aindices.Add(scadenas.Find(tcadenas))
    Next
  Endif

  'Se han ordenado las cadenas y creado indices para ver los cambios de lugar

  aotro = testvalores.Copy()

  For fila = 0 To testvalores.Max
    Swap testvalores[fila], aotro[aindices.Find(fila)]
  Next

  nombres.Clear()
  nombres = testvalores
  grd.Clear()

End

En parte el código es muy similar en este último. Casi repetido. Pero una cosa son las cadenas y otras las fechas.
Me he tenido que apoyar en otro array aotro.

A ver si se puede optimizar un poco más.
Ah, como ves para la creación del array aindices me he valido de búsquedas dentro del array con su método Find.

Me he llevado dos días liado con esto.  Es increíble lo que absorbe estas cosas. Sad
 

En el código que uso solo cadenas, "puede" llevarse a otros ejemplos, pero ya en el que uso cadenas y fechas
es muy exclusivo de la aplicación. Los números de las columnas ( sabiendo siempre donde están las fechas ).

Lo que quiero decir de esta última frase, es que cuando hacemos algo en programación , eso puede estar muy
ligado a la aplicación en concreto que estamos diseñando. (Hay que entender como funciona para poder trasladarlo a otro código ).

Entonces puede que eso no valga en otro ejemplo.

Y en realidad, estos son ejemplo para entender un poco la ordenación en un GridView y comprender el componente.
Desde los métodos Sort de los arrays, sus variaciones, incluidos si añadimos un idioma ( que tenga tildes ) y ademas
entender como funciona el Evento Data del GridView.

Coordinar para que todo funcione no siempre es fácil. Y naturalmente no hemos hablado de SQL, que seria lo ideal,
pero no vas a crear una base de dato para un pequeño ejemplo. Smile

P.d Cacho texto he escrito.

Saludos
Archivos adjuntos
.gz
OrdenarFechas-0.0.3.tar.gz (Tamaño: 8.58 KB Descargas: 1)
Última modificación: 16-03-2024, 12:10 por Shell.

"El conocimiento es la mejor inversión que se puede hacer" - Abraham Lincoln
Shordi   16-03-2024, 14:36
#7
Hasta el lunes no puedo ver tu código, pero una aclaración: en gambas un valor de fecha es un número entero. Se verá de una forma u otra según el formato que se le defina o el de el país que se use, pero si es una fecha es un número.
Me da la sensación (ten en cuenta que no he visto tú código) que estás confundiendo fechas con "cadenas con formato de fecha". Si es así hablamos de cosas distintas. El lunes te lo digo, que hoy y mañana estoy en Benidorm donde vive mi hijo.

Slaudos

No podemos regresar
Shell   16-03-2024, 14:47
#8
(16-03-2024, 14:36)Shordi escribió: Hasta el lunes no puedo ver tu código, pero una aclaración: en gambas un valor de fecha es un número entero

Creo que un número float.
(16-03-2024, 14:36)Shordi escribió: El lunes te lo digo, que hoy y mañana estoy en Benidorm donde vive mi hijo.

Que lo disfrutes.

Ya me aconsejarás cuando veas el código y que es lo mejor. Wink

Saludos

"El conocimiento es la mejor inversión que se puede hacer" - Abraham Lincoln
Shell   16-03-2024, 17:49
#9
(16-03-2024, 14:47)Shell escribió: Creo que un número float.

Pues no, es un entero de 32 bit, que pena que la documentación que explica las fecha no este en español.
Con el tiempo que lleva esto. Tampoco es difícil de entender.

Date & time management

"El conocimiento es la mejor inversión que se puede hacer" - Abraham Lincoln
Shell   17-03-2024, 23:50
#10
He cambiado el método de ordenación.
En este caso no es necesario conocer si la columna 1 o 2, contienen cadenas similares a una fecha.

Código:
Public Function OrdenarValores(Columna As Integer, modo As Boolean) As String[][]

  Dim j As Integer
  Dim tfechas As New Date[]
  Dim sfechas As New Date[]
  Dim tcadenas As New String[]
  Dim scadenas As New String[]
  Dim testvalores As String[][]
  Dim fila As Integer
  Dim aindices As New Integer[]
  Dim aotro As New String[][]

  testvalores = nombres.Copy()

  For j = 0 To testvalores.Max
    'Intenta convertir la cadena a una fecha
    Try Date(testvalores[j][columna])
    If Error Then
      'Si no se parece a una fecha, añadimos el valor a cadenas temporales
      tcadenas.Add(testvalores[j][columna])
    Else
      'En caso positivo, añadimos el valor a fechas temporales
      tfechas.Add(testvalores[j][columna])
    Endif
  Next

  If tfechas.Count > 0 Then
    sfechas = tfechas.Copy()
    'Descendente es True y ascendente es False
    If modo Then
      sfechas.Sort(modo).Reverse()
    Else
      sfechas.Sort(modo)
    Endif
    For j = 0 To tfechas.Max
      aindices.Add(sfechas.Find(tfechas[j]))
    Next
  Else If tcadenas.Count > 0 Then
    scadenas = tcadenas.Copy()
    If modo Then
      scadenas.Sort(modo + gb.Natural).Reverse()
    Else
      scadenas.Sort(modo + gb.Natural)
    Endif
    For j = 0 To tcadenas.Max
      aindices.Add(scadenas.Find(tcadenas[j]))
    Next
  Else
    Message.Error("Ha ocurrido un error: " & Error.Where & gb.NewLine & Error.Text)
  Endif

  aotro = testvalores.Copy()

  For fila = 0 To testvalores.Max
    Swap testvalores[fila], aotro[aindices.Find(fila)]
  Next

  nombres.Clear()
  nombres = testvalores
  grd.Clear()

End

He cambiado la variable local i por j en el código, para que no queje el editor de la comunidad, la "i" la entiende como itálica.


Saludos
Última modificación: 18-03-2024, 00:00 por Shell.

"El conocimiento es la mejor inversión que se puede hacer" - Abraham Lincoln
Páginas (3): 1 2 3   
  
Usuarios navegando en este tema: 14 invitado(s)
Powered By MyBB, © 2002-2024 MyBB Group.
Made with by Curves UI.