LIST BOX - He doesn't order

No.

Look at the real order in red:

Nope. That’s not a proper code. You should try to understand the sample I’ve made.

You should not be using Val() at all for your text use case in your locale.

Better to convert the number in each row to a double, and store that in the RowTag.

Then, for sorting, create your own method for sorting by the RowTag. Sorting by doubles is then fast, especially with long lists (10s of thousands).

You can implement this either as a method on the Listbox, though the way I do it is by subclassing the Listbox and creating an iterator for it.

i’m write this, is ok ?

Var n1 as double=CDbl(Me.CellTextAt(row1, column ).ToText)
Var n2 as double=CDbl(Me.CellTextAt(row2, column ).ToText)


Select Case column
  
Case 4  
  If n1 < n2 Then
    result = -1
  ElseIf n1 > n2 Then
    result = 1
  Else
    result = 0
  End If
  Return True
  
  
Case 6 
  If n1 < n2 Then
    result = -1
  ElseIf n1 > n2 Then
    result = 1
  Else
    result = 0
  End If
  Return True
  
  
Else 'NOT WORKing
  Return False
End Select

1 Like

Check out what Nicholas (and it was mentioned earlier in this thread too, I think but am too lazy to find) wrote:

I would think that you get the original values as double and then attach them as a localised string to the listbox, right? You avoid a lot of unnecessary conversions (and processing time) if you don’t compare the strings by converting them to doubles again, but simply save them in the cell tag of their column as doubles. Then you do the sorting comparison based on the celltag values, not on the cells, so you fully skip the time-consuming conversions.

The easiest way to do so is in the code that fills your listbox. So after (as an example, your code will look different)
listbox1.addrow datafattura.tostring(formatters), nettof.tostring(locale.current), iva.tostring( …
add a line like
listbox1.celltagat(listbox1.lastRowIndex, 4) = lordoAsDouble

Your sorter should be changed to

Case 4
If Me.CellTagtAt(row1, column ).DoubleValue < Me.CellTagAt(row2, column).DoubleValue Then
    result = -1
  ElseIf Me.CellTagAt …

If you’d later find your listbox can get quite full and setting it up takes a long time, cell tags with native values also offer a great way to reduce the addRow times and such make your app become snappier. But I don’t want to confuse you. Just ask again if you feel a little speed bump could improve user experience.

This should work now for your proposal (ordering from known numbers expressed as string using locale settings). But learn more tips from users about separation of data and presentation (aka storing the real values in “Xojo Tags”). That may be an advanced topic now for a starter (guessing you are a starter), but take a look later.

Yes, I consider myself a beginner :slight_smile:

Yes, I already load the formatted data in the listbox, and I used this code:
ListBox.addrow … replaceall(format(rows.Column(“TotaleScadenza”).Value,“-##.00”),“.”,“,”)

Can it go?

My version as a typing strip
sorting is very easy with RowComparison
adding-numbers-sort.xojo_binary_project.zip (14.9 KB)

You mean adding the tags? Yes, the way you format the cells does not influence the tag handling.
You could simplify your formatting if you’d use the doublevalue of the row and its toString method, but that’s a different topic.

thanks.

I lightened the code like this:
From:
Var n1 as double=CDbl(Me.CellTextAt(row1, column ).ToText)
Var n2 as double=CDbl(Me.CellTextAt(row2, column ).ToText)

TO:
Var n1 as double=Me.CellTextAt(row1,column).ToDouble
Var n2 as double=Me.CellTextAt(row2,column).ToDouble

To avoid this kind of errors, there is an entry in the documentation named Variables and Constants that explain why trying to set a Text to Double variable will not work.
There are also some useful links in that page.

“Variables are like dishes: you do not put spoon with fork or knife, but in the spoon box.”

So ? What would be the right way to read the values ​​in € and sort them?

What would be the right way to read the values

Where is the data coming from, before it gets into the listbox?

If it is in a database, surely it is better to select and order in the query.
I notice that the date column is DD/MM/YYYY and that won’t sort by date if you click the header either.
There is a big difference between the way data is stored, and the way it is displayed.
If your app can be used in several countries, you need to be aware of how the user will enter data too.

In Europe, 2,50 is between 2 and 3
If you use Val(), you will get 2 because Xojo stops reading at the comma

In Europe, 3/5/2025 is the 3rd of May
In USA 3/5/2025 is the 5th of March

STORING these values, you should be storing as a Double, or using the format “2.50”
Dates… if you store as a string, best use SQLDATE format of YYYYMMDD

And you can later display these in any way that the user prefers.

I always see SQLDate as YYYY-MM-DD and I think that’s the string that we can use for regular DateTime.FromString (with locale nil). I haven’t tested using Xojo’s DateTime.FromString with YYYYMMDD, not sure if that will cause an error.
Can you confirm it works?

1 Like

Yes that would work

1 Like

Yes, my data comes from an access database, and is saved as a decimal number, I read it and insert it into the listbox reading it from a query … replaceall(format(rows.Column(“TotaleScadenza”).Value,“- ##.00”)“,”,“,”,") , then I sort it, if needed by the user, with RowComparision:


Var n1 as double=Me.CellTextAt(row1,column).ToDouble
Var n2 as double=Me.CellTextAt(row2,column).ToDouble
Select Case column
  Case 5 
  If n1 < n2 Then
    result = -1
  ElseIf n1 > n2 Then
    result = 1
  Else
    result = 0
  End If
  Return True
  Else
  Return False
End Select

Mine is software for me, at most for a few friends who do the same job as me. nothing more, I don’t have big expectations :slight_smile:

Now I have a lot of confusion in my head, I just want to understand if how I sort the data is ok.

You already have many sortng options.

All I am saying is, if it were me, I would get the data from Access already sorted, and display it in a manner that you like to see

Select * from mytable order by NettoF

for example.

If another header is pressed, you could get a new data set, in ascending or descending order

Select * from mytable order by DateFattura desc

Yes, yes, I do this when I extrapolate the data from the query. The whole problem arose because, when I read the data from the listbox it was fine, but if I sorted it by pressing on the indicated column, the data was sorted incorrectly because I used the .val of the data. Then they explained to me that I had to read the data carefully with .double in order to also count the decimals. I think I solved the problem like this.

I think @Jeff_Tullin means that instead of sorting with the RowComparison event, when the user clicks a header just reload the ListBox. You do have to modify the SELECT statement to have the appropriate ORDER BY. I use this approach and have no RowComparison event handler. I’m using an SQLite database which I figure can sort as fast as Xojo. Seems to work very well.

1 Like