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