Sorting speed

Thanks to your support, examples, info and code that you suggested, I was able to sort my listboxes using RowComparision. However, I noticed that in lists where there are several hundred rows the sorting is slow, it takes even several seconds to sort. Can the code be improved or some trick used to speed up the execution?

I also tried with this, but the substance does not change.

Select Case column
Case 3  'colonne con il tipo DATA
  Var n1 As DateTime
  Var n2 As DateTime
  Var olds As String
  Var lc As New locale("it-IT")
  if Me.CellTextAt(row1,column)<>"" then
    olds = Me.CellTextAt(row1,column)
    n1 = datetime.FromString(olds, lc)
    if Me.CellTextAt(row2,column)<>"" then
      olds = Me.CellTextAt(row2,column)
      n2= datetime.FromString(olds, lc)
      If N1 < N2 Then
        result = -1
      ElseIf N1 > N2 Then
        result = 1
      Else
        result = 0
      End If
    end if
  end if
  Return True
Else 'nulla, esco
  Return False
End select

I also tried with this, but the substance does not change.

Var  olds, news, bits() as String
olds = Me.CellTextAt(row1,column)
bits = olds.split (“/”)
news = bits(2) + “-” + bits(1) + “-” + bits(0)
n1 = DateTime.FromString(news)

Save the actual DateTime in CellTagAt(row, column) so you don’t have to call FromString all the time.

7 Likes

Should I eliminate the Olds variable and have the date be stored in CellTagAt(row, column) , like this?

me.cellTagAt(row1,column)= Me.CellTextAt(row1,column)

and the date format conversion, how do I do it?

if you add a row to a list you should get the row index. (all cells are currently strings, unfortunately)
if you fill the list (without datasource) put a datetime object in the celltag.
you already used the string to datetime convert.
for empty string use nil.

you mean if the list have few thousand of rows?
there is a blog “Lazy Loading Data with ListBox”

More like: DesktopListbox.CellTagAt(row, column) = DateTime Object taken from Source Data

Not at my Dev.Desk currently. But the comparison will then look something like this:

If Me.CellTagAt(row1,column) <> Nil Then
  
  If Me.CellTagAt(row1,column).DateTimeValue < Me.CellTagAt(row2,column).DateTimeValue Then
    result = -1
  ElseIf Me.CellTagAt(row1,column).DateTimeValue > Me.CellTagAt(row2,column).DateTimeValue Then
    result = 1
  Else
    result = 0
  End If
  
  
  Return True
  
Else
  
  Return False
  
End Select
1 Like

I would go so far as to store just the secondsFrom1970 double value in the tag. Then your code just needs to compare the two numbers.

1 Like

The first question is: How do you get the data into the listbox?

Asked ages back in the original post.
Comes from a database.
Attempts to get the data sorted at the query stage (which should surely be the fastest route?) floundered and the OP elected to continue down the RowComparison route.

Yet another solution could be to put the SQLDate formatted text into the cell, but to paint the text in the celltextpaint event using localised formatting, for that column.

Simply clicking the list header would then sort the list happily without using either RowComparison or a database requery.

2 Likes

Yes I know, but it is not like that, the data is entered, stored and displayed in the European format.

Does not alter what @Jeff_Tullin said.

  • Pull the Data from the Database in a Format that can be sorted by the Listbox without further handling in RowComparison.
  • Put the sortable Text into the ListBox.CellTexts but handle the drawing of the CellText by your Code in the PaintCellText.Event.

PaintCellText:

Select Case column
Case 0
  
  g.DrawingColor = &c000000
  g.DrawText(DateTime.FromString(Me.CellTextAt(row,column)).ToString(DateTime.FormatStyles.Long, DateTime.FormatStyles.None), x, y, g.Width, True)
  
  Return True
End Select

But once you have the date string you can use it to create a datetime object and thus get the SecondsFrom1970 property, and store that instead in the tag. This may take more time in loading but the sorting then becomes quick.

To me, @Jeff_Tullin Solution looks like the fastest way. No more RowComparison needed. Or?

Here’s an example of what @Jeff_Tullin described:
untitled2.zip (5.1 KB)

At start the App adds 10.001 random dates and writes them into the Listbox (so, in random roder).
Then a Message Box appears just before the Listbox will be sorted, just to se how long sorting 10.0000 Lines will take with a standard Listbox.

(Disable VerticalScrollbar before adding this much lines to a Listbox on Screen, in Xojo before 2024.4.) - Look here why.

I would like to try sorting, formatting the date in PaintCellTEXt, but I get an error, again due to formatting.: date needs to be in the format of YYYY-MM-DD HH:MM or YYYY-MM-DD

You should really give us more information:

  • code used
  • in what line of your code you get the error
  • or even a small sample project

My guess, is that you added some code and tried to use FromString and the string is not SQLDate formatted.

1 Like

sure, I write the code I use…

I have the upload part of my listbox where I enter the data like this:

Dim DataFormattata as date
While Not Rows.AfterLastRow
  ......  
    ListBoxRicerca.AddRow(....rows2.Column("Data").DateTimeValue.SQLDate)
    rows.MoveToNextRow
..............
Wend
rows.Close

And already here I don’t understand why the date is formatted as 2024-05-21 for me while in Sascha S’s example it comes out formatted as “21 May 2024”.

then in PaintCellText I write:

g.DrawingColor = &c000000
g.DrawText(DateTime.FromString(Me.CellTextAt(row,column)).ToString(DateTime.FormatStyles.Long, DateTime.FormatStyles.None), x, y, g.Width, True)
DateTime.Now.SubtractInterval(0,0,System.Random.InRange(0, 150)).SQLDate

I tried to copy the code as per Sasha’s example but it gives me the error:

I noticed that, by deleting the line from the original project, everything still works. So, I also delete it from mine and it gives me the error on the line before … in g.DrawText… telling me: Parse error: date needs to be in the format of YYYY-MM-DD HH:MM or YYYY-MM-DD

May it be possible that your querry delivers data points with NIL values? That may cause the Parse errors, maybe.

My example writes YYYY-MM-DD values into the CellText properties. But in the PaintCellText event it replaces the drawing of the CellTexts as they are and replaces them with a drawing formatted as “21 May 2024”. And because the CellText is formatted as YYYY-MM-DD but just displayed formatted as “21 May 2024”, the ListBox can use the normal alphanumeric sorting algorithm.

In fact your example is fantastic and I think it can solve my problem in display speed… but unfortunately I have this problem and I can’t understand why, I try to see if there are NIL date values

What happens if you replace it with:

Try
  
  g.DrawText(DateTime.FromString(Me.CellTextAt(row,column)).ToString(DateTime.FormatStyles.Long, DateTime.FormatStyles.None), x, y, g.Width, True)
  
Catch err As RuntimeException
  
  g.DrawText("", x, y, g.Width, True)
  
End Try

(Catching all RuntimeException’s is not recommended and should be handled in the UnhandledException Event of the App Object, but here it’s ok…)