Question
Please advise on how to correctly number the rows in the #number
field depending on the date in the #date
field.
Example
There is a table with rows consisting of two columns date
and number
:
01.03.24 1 07.03.24 2 20.03.24 3
How to make the values in the Serial Number column recalculate according to the dates, where the earliest date is assigned the smallest serial number, and the latest date the largest?
Continuing the example to better explain the question
I add a row to this table with the date field value 10.03.24, it should look like this:
01.03.24 1 07.03.24 2 10.03.24 3 20.03.24 4
And one more nuance, if I add a row with a date already existing in the table, for example, 07.03.24, it should look like this (the numbers in the table should change according to the new order):
01.03.24 1 07.03.24 2 07.03.24 3 10.03.24 4 20.03.24 5
How can this be implemented?
Answer
Tasks involving complex sorting in tables, such as when we need a continuous sort by the date field plus id, are solved through an additional technical field of type String, where we compile a string Y-m-d-id
that can be set as the default sorting field for the table.
The id must be padded with leading zeros since the comparison will be done in string mode: 10
should be used as 00010
.
The number of leading zeros is determined by the maximum possible id in the table.
Code in the technical field creating a continuous sorting identifier (field with name teh_order_field
):
=: str`#date + "-" + $zero_prefix + #id`
zero_prefix: strRepeat(str: 0; num: $id_length)
id_length: 10 - strLength(str: #id)
Now we need to calculate the number in the number field. The number is calculated as the number in the previous row sorted by the teh_order_field plus 1.
Code in the number field:
=: $prev_num + 1
prev_num: select(table: $#ntn; field: $#nf; where: 'teh_order_field' < #teh_order_field; order: 'teh_order_field' desc)
It should be noted that this code will work correctly only in simple tables and cycle tables. In calculated tables and temporary tables, a different approach is needed since the rows in them are virtual and do not correspond to rows in the database.
Next, it is necessary to add action code in the teh_order_field with triggers for addition, modification, and deletion, which will recalculate the rows following the modified row:
Action code in the teh_order_field:
ad1=: reCalculate(table: $#ntn; where: 'teh_order_field' > $#nfv)
dl1=: reCalculate(table: $#ntn; where: 'teh_order_field' > $#onfv)
ch1=: reCalculate(table: $#ntn; where: 'teh_order_field' > $min)
min: listMin(list: json`[$#nfv,$#onfv]`)
When changing, we determine which sorting marker was smaller (before or after the change) and recalculate from it, as the date change can go both ways.
It is important to enable the "Column-by-column recalculation" parameter for the table. This means that the column with teh_order_field should be calculated to the end when the number is being calculated.
Also, in the calculated table, no action codes are needed for this task since it is always calculated in full.
Code in the number field:
= : $key[0] + 1
key: listSearch(list: $list; key: "value" = #teh_order_field)
list: selectList(table: $#ntn; field: 'teh_order_field'; order: 'teh_order_field' asc)
For optimization, it is better to create a field in the footer of the teh_order_field column where selectList
is done, and in listSearch
, take it through #list_in_column_futer
.
Code in the f_precalc field in the footer of the teh_order_field column:
=: selectList(table: $#ntn; field: 'teh_order_field'; order: 'teh_order_field' asc)
Code in the number field:
= : $key[0] + 1
key: listSearch(list: #f_precalc; key: "value" = #teh_order_field)
When we have the teh_order_field selected as the Sorting Field in the table settings, it only triggers at the moment the table is loaded.
If all the table rows are transferred to the browser without pagination, we can update their order immediately through the table formatting code:
Table formatting code:
f1=: setRowsOrder(ids: $ids)
ids: selectList(table: $#ntn; field: 'id'; order: 'number' asc)