Comunidad Gambas-es
Gridview. Ordenar por columnas. - Versión para impresión

+- Comunidad Gambas-es (https://gambas-es.org)
+-- Foro: Gambas (https://gambas-es.org/forum-3.html)
+--- Foro: General (https://gambas-es.org/forum-4.html)
+--- Tema: Gridview. Ordenar por columnas. (/thread-1632.html)

Páginas: 1 2 3


RE: GridView Evento Data - Shell - 18-03-2024

He encontrado un problema con la ordenación de indices.

Pongamos el caso de los autores. Los valores almacenado en el array de indices no se repiten, las fechas son distintas.

[Imagen: aPAttU9.png]

Pero en otro ejemplo que estoy haciendo de mostrar stat sobre archivos..
La cosa cambia y hay dos valores en el array de indices que almacenan 0. 
Sus fechas han resultado ser iguales.

Como si hubiera que decirle, busca desde este lugar y no el primero que encuentres.

[Imagen: xrAMiiP.png]

Si hago clic en la columna de Última modificación no hay problema, pero si lo hago en las otras se genera
el error fuera de limites.


RE: GridView Evento Data - Shordi - 18-03-2024

El ejemplo extGrid5 que hice para el vídeo de youtube, no incluía, por no liarla más, el tema de las fechas. Como digo, una fecha es un número, por tanto con muy pocas variaciones, el ejemplo ordena número tan bonitos como fechas.

1.- He añadido una columna de fechas al fichero de ciudades.csv para ampliar la demo.

2.- He modificado el código en las dos líneas donde pregunta si el valor es un número para que pregunte también por si es fecha.

3.- He pasado la variable de la función Antinumber de integer a Float por problemas de desbordamiento.

y ya está. Queda así

Código:
            Select Case v
                Case gb.Ascent
                    If IsNumber(sword) Or If IsDate(sword) Then  ''añadimos la pregunta de la fecha
                        'Pueden tener o no decimales así que les ponemos a todos
                        skey &= String.PadLeft(Val(sWord) + Frac(0.001), 16, "0") ''Si es fecha, Val devuelve un valor de fecha, o sea, un número
                    Else
                        skey &= sWord
                    Endif
                Case gb.Descent
                    If IsNumber(sWord) Or If IsDate(sword)   ''añadimos la pregunta de la fecha
                        skey &= Antinumber(Val(sWord))  ''si es fecha, Val devuelve un valor de fecha, o sea, un número
                    Else
                        skey &= Antiword(sWord)
                    Endif
            End Select
        Next
        asKeys.Add(skey & "^" & Str(n)) 'la clave de ordenación+ "^" + número de fila actual
    Next
    asKeys.Sort(gb.Ascent + gb.Language) 'ordenamos las claves
    avSorted = New Variant[$avSource.Count] 'Creamos un array bidimensional con las mismas filas que el $avSource
    For n = 0 To $avSource.Max
        'grabamos las filas del $avSource en el nuevo array siguiendo el nuevo orden
        avSorted[n] = $avSource[Val(Mid(asKeys[n], InStr(asKeys[n], "^") + 1))]
    Next
    $avSource.Clear   'limpiamos el $avSource
    $avSource = avSorted   'y lo igualamos al nuevo
    $isShift = False
    Dec Application.Busy

Catch
    Print Error.Text;; Error.Where;; sword


End

Private Sub Antinumber(nNumber As Float) As String

    Dim nAntiNumber As Float
    Dim nMax As Float = 9999999999999999  ''He cambiado nMax de integer a Float por problemas de desbordamiento

y ahora ordena tanto números como fechas igualmente.

Lo he probado con más de 1.000.000 líneas y mi ordenador tarda al rededor de 10 segundos en ordenarlas.

He intentado hacer una comparativa de tiempos con tu función... pero ese bug con las claves repetidas que indicas más arriba no me lo ha permitido.

Adjunto el extGrid5 corregido y con el 1.000.000 líneas. Para usar sólo las 300 que tiene el fichero basta con comentar el bucle:

Código:
   Private Sub CsvLoad(sFile As String)

    Dim vRet As New Variant[]
    Dim aLines, aCells, aTits As String[]
    Dim sLine As String
    Dim aWidths As New Integer[]
    Dim n As Integer

    aLines = Split(File.Load(sfile), gb.NewLine, "", True)
    aCells = Split(alines[0], ";")
    aTits = aCells
    aLines.Extract(0) 'quitamos la línea de títulos.

    '  For n = 0 To 3333 ''usamos un millón de registros. Comentar este bucle para trabajar con los 300 del fichero
    For Each sLine In alines
        aCells = Split(sLine, ";") 'convertimos la líne en un array de valores
        vRet.Add(aCells) 'añadimos al array bidimensional
    Next
    ' Next
    miGrid.Source = vRet
    For n = 0 To aCells.Max 'ponemos todas las celdas expandibles
        aWidths.Add(-2)     ''TODO: Añadir este comportamiento como una propiedad boolean al control como hicimos con WordWrap y no usar la propiedad .widths sí no hay columnas de ancho fijo
    Next
    miGrid.Titles = aTits 'le pasamos los títulos a miGrid
    migrid.Widths = aWidths 'le pasamos los anchos

End

No me resisto a copiar y pegar aquí el archivo "Notas" que adjunté al proyecto y que no recordaba haber escrito. Mola:


 Cómo ordenar un array bidimensional por una de sus columnas

 ["1","Tokio","Japón","1616,792","436,64","Asia"]
 ["2","Los Ángeles","Estados Unidos","860452","65082","América"]
 ["3","Nueva York","Estados Unidos","1403463","69915","América"]

A) Creamos array de una dimension uniendo la columna y número de fila

 ["Tokio^1"]
 ["Los Ángeles^2"]
 ["Nueva York^3"]

B) Lo ordenamos de arriba a abajo

 ["Los Ángeles^2"]
 ["Nueva York^3"]
 ["Tokio^1"]

C) Luego copiamos el array original a uno ordenado según los índices del array monodimensional

 ["2","Los Ángeles","Estados Unidos","860452","65082","América"]
 ["3","Nueva York","Estados Unidos","1403463","69915","América"]
 ["1","Tokio","Japón","1616,792","436,64","Asia"]
 --------------------------------------------------------

 Cómo ordenar por varias columnas en este ejemplo Continente + país

 A.1) Orden Ascendente:


 Hacemos lo mismo del punto A pero uniendo las columnas a ordenar poniendo primero las cadenas que abarcan a las demás (primero Continente, por ejemplo, y luego Ciudad) en una sola cadena y número de fila

 ["AsiaTokio^1"]
 ["AméricaNueva York^2"]
 ["AméricaLos Ángeles^3"]

Luego hacemos los puntos B y C

A.2) Si hay alguna en Orden Descendente en lugar de añadirla sin más, buscamos una cadena que sea su "Antípoda" y añadimos ésta a las claves a ordenar. Ejemplo:

       La Antípoda de "aba" es "zyz". La Antípoda de "111"es "999"

Luego hacemos los puntos B y C igual que antes.


Espero que te sea útil.

Saludos


RE: GridView Evento Data - Shell - 18-03-2024

Estuve viendo un poco la función IsDate.

Tenemos que estar seguros de que lo que se le pase como argumento es una cadena similar a una fecha local
Y es que hay fechas que pueden parecer que están en formato local, pero pueden no estarlo.

Ejemplo. Creemos que se encuentra formato local.

03/05/2024

Cuando en realidad puede no serlo. Y ya no estamos hablando de mayo (formato local).
Estaríamos hablando de Marzo.

¿ Y cómo deberíamos controlar eso ?

Supongo que:

- Primero saber como es el formato de las fechas de origen. El origen de la información.
- ¿ Necesita una conversión ?.

No siempre es algo tan sencillo de controlar a la primera.

Saludos


RE: GridView Evento Data - Shordi - 18-03-2024

Cita:Cuando en realidad puede no serlo. Y ya no estamos hablando de mayo (formato local).
Estaríamos hablando de Marzo.

¿ Y cómo deberíamos controlar eso ?
 
Si controlamos la fuente de los datos, almacenando las fechas en su formato nativo, o sea, en números. Si no lo controlamos (digamos csv o textos ya tratados por otros)... pues no te queda otra que hacer una comprobación/conversión, antes.
Con las bases de datos no debiera haber problema...

Saludos.


RE: GridView Evento Data - Harpo - 18-03-2024

Saludos,
Yo llevo un tiempo trabajando en un GridView personalizado, necesitaba poder ordenar y filtrar datos.
Por si les sirve de ayuda les cuento mis descubrimientos, seguramente no les cuente nada nuevo.

GridView se puede cargar de dos maneras distintas, con el evento Data y con la asignación de valores a las celdas. Por otro lado los valores de las celdas se almacenan en una clase Collection siendo la clave el valor de fila-columna.

Cuando GridView necesita pintar una celda busca si tiene almacenado un valor y en ese caso lo utiliza. Si no tiene almacenado nada para esa celda lanza el evento Data, recoge la información y la pinta.

Un ejemplo sería:
Código:
Public Sub gvw_Data(Row As Integer, Column As Integer)      ''Solo pinta en pantalla.

   gvw.Data.Text = "Cell-" & CStr(Row) & "-" & CStr(Column)

End

Private Sub LoadGrid()     ''Carga Collection interna

   For iRow As Integer = 0 To gvw.Rows.Max
      For iCol As Integer = 0 To gvw.Columns.Max
         gvw[iRow, iCol].Text = "Cell-" & CStr(iRow) & "-" & CStr(iColumn)
      Next
   Next

End

Si se usa el evento Data el control no almacena nada internamente, supongo que por eso el GridView estándar no tiene un algoritmo de ordenación interno.
Por otro lado si se carga la información de las celdas y se quiere ordenar por una columna, hay que mover de sitio todas las celdas de una fila, no solamente las celdas de la columna ordenada. Además hay que tener en cuenta las propiedades de la fila. Si la fila 15 pasa a ser la fila 3 hay que mover todas las celdas de la fila 15 y las propiedades de la fila 15 (Text - Border ).

Les dejo una imagen de como funciona mi GridView, tengo pensado subirlo al foro, pero antes quería solucionar un problema con los filtros que no acabo de encontrar.
Un saludo, Harpo.

[Imagen: dDxrgxm.gif]


RE: GridView Evento Data - Shordi - 18-03-2024

Si te sirve de algo, aquí está la serie de videos sobre la extensión de Gridview que subí hace tiempo. Hace exactamente eso, ordenaciones, filtros y listado de distintas fuentes de datos( result, variant[], texto, etc.)
https://youtube.com/playlist?list=PLM9b_coNmB5TtMhl9zN3lTr29EmoE63CY&si=wJZql-ZbIEJYeovO

Por cierto, si yo no he monetizado nada, ni quiero hacerlo, ni nada de eso ¿Por qué demonios ponen anuncios en mis videos?

Me viacagar en to lo que se menea... Oiga.

Saludos


RE: GridView Evento Data - Shell - 19-03-2024

(18-03-2024, 18:41)Shordi escribió: Con las bases de datos no debiera haber problema...

Ya, pero para cosas sencillas no vamos a usar una base de datos. Es más entender como hacer funcionar algo en Gambas y
hecho solo con Gambas. Un control, una función, etc.

Ejemplo: Tenemos la función Dir de Gambas, podemos usar Dir del Shell Bash. Y nos ordenaría la salida.
Nosotros intentamos más comprender el problema, más que buscar una solución rápida. A menos que sea para trabajo
y con "tiempo" puedas implementar una solución hecha en Gambas. ( Si es que eso se hace, cuando trabajas para otros..  Rolleyes ).

( Hecha solo en Gambas ) ¿ Purista ?. Smile
 
(18-03-2024, 21:32)Shordi escribió: Por cierto, si yo no he monetizado nada, ni quiero hacerlo, ni nada de eso ¿Por qué demonios ponen anuncios en mis videos?

Para mi que lo hacen con todos. Ten en cuenta que hay otra opción en Youtube que es pagando y no ves publicidad.
Si la publicidad es selectiva ( puede no molestar, si veo vídeos de programación, pueden ponerte anuncios sobre eso ).
Aunque algunos son malos pero malos.
 

Por cierto Shordi, ¿ sabes que estás usando gb.gui  en el proyecto y no gb.gui.qt ?.

Te digo esto por que usando Qt, (como sabes) vas a tener menores problemas ( recochineo Big Grin  ).

Ademas de la broma. ¿ Sabes que si usas el componente QT vas a poder desplazar la barra de arriba abajo
con solo un clic de ratón sobre el lugar donde se desplaza la barra ?  ( Usa el botón derecho sobre esta..pero con Qt ).

[Imagen: XLaX0Uh.png]

Saludos


RE: GridView Evento Data - Shordi - 19-03-2024

Cita:Por cierto Shordi, ¿ sabes que estás usando gb.gui  en el proyecto y no gb.gui.qt ?.
A ser sincero... no me acuerdo. Hice los vídeos en su momento, pero mi pobre cerebro está medio jubilado anticipadamente y según los hago los olvido. Ayer me encontré en el proyecto ExtGrid5 esa nota explicativa que copié más arriba y me dije "¡Qué chula! ¡Qué cosas hacemos los programadores!" así que por la noche, aprovechando que mi santa trabaja estos días en turno de noche, me puse en la tele los vídeos de la secuencia de "Extendiendo Gridview"... y me dormí al cabo de un rato.

Soy un desastre como youtubero... pero viendo al plasta ese que has puesto de Gnome... tampoco estoy tan mal ¿no?

Big Grin Big Grin Big Grin


RE: GridView Evento Data - Shell - 19-03-2024

(19-03-2024, 10:45)Shordi escribió: ... y me dormí al cabo de un rato.

Es que tenías que haber empezado por el primero.
El youtuber decía "...repasar los vídeos anteriores. No voy a tener piedad con los nuevos". Hay que aplicarse el cuento.  Tongue
 
(19-03-2024, 10:45)Shordi escribió: Soy un desastre como youtubero... pero viendo al plasta ese que has puesto de Gnome... tampoco estoy tan mal ¿no?

Big Grin Big Grin

Que controles todo, resulta complicado.
Había que entender los métodos de enseñanza del youtuber y acostumbrarse a ese método.

- Escribir mientras ves el vídeo ( cosa que puede no ser fácil, tanto para el que enseña como el que aprende ).
- Descargar la fuente y entenderlo a medida que vas viendo el vídeo.

Y en cuanto al plasta. Big Grin
Pues no tenía ni idea del nivel al que están recortando las aplicaciones de Gnome.
Cosas que pueden ser importantes para los usuarios.  Siempre se puede buscar una aplicación optativa,
pero si haces eso, estas obligando al usuario a que se busque la vida y no le estas dando otra opción.

Como dijo alguien: "Si no puedes hacer que funcione bien, hazlo bonito."


RE: GridView Evento Data - Shell - 19-03-2024

Shordi:

¿ Qué diferencia existe entre el archivo ciudadesold.csv y ciudades.csv ?.

Ademas de que las fechas puedan variar. ( Que eso no es importante ).
ciudades.csv tiene un problema mal formado en la cabecera.

ciudades.csv:
Cita:1;Tokio;Japón;Fecha;1616,792;436,64;Asia
2;Nueva York;Estados Unidos;10/9/2020;1403463;69915;América
3;Los Ángeles;Estados Unidos;20/1/2020;860452;65082;América
....

ciudadesold.csv:
 
Cita: 
ID;Ciudad;Pais;Fecha;PIB;PIB_PC;Continente
1;Tokio;Japón;12/01/25;1616,792;436,64;Asia
2;Nueva York;Estados Unidos;01/04/29;1403463;69915;América
...

Parece más coherente, el old, ¿ no ?. Lo digo solo por la cabecera.
Actualmente estoy usando old. No creo que sea un problema.

Ah, un pequeño cambio que hice al código de extGrid5 en FMain, cuando eliges si ciudades o países.
Fue crear un array de controles de los botones. Cosas de la estética. Eso fue antes de que hicieras
los cambios oportunos para el tema de las fechas.

Código:
Public Sub botones_Click()

  Dim vRet As New String[][]
  Dim lineas, campos, titulos As String[]
  Dim linea As String
  Dim sPathCsv As String
  'Dim n As Integer

  miGrid.Clear()

  Select Case Last.tag
    Case 0
      sPathCsv = "ciudades.csv"
    Case 1
      sPathCsv = "paises.csv"
  End Select

  lineas = Split(File.Load(sPathCsv), gb.NewLine, "", True)
  titulos = Split(lineas[0], ";")
  lineas.Remove(0) 'Eliminamos la línea de titulos antes de añadir al array de valores

  'Si queremos añadir más registros. Vamos a cargar 1000 veces el total de registros del csv

  ' For n = 0 To 1000
  For Each linea In lineas
    campos = Split(linea, ";")
    vRet.Add(campos)
  Next
  'Next

  miGrid.Source = vRet
  miGrid.Titles = titulos
  miGrid.Widths = [-2, -2, -2, -2] 'Ancho de los títulos

End


Saludos