In general, sequential numeric identifiers (i.e., serial numbers) are risky in AppSheet: if two users happen to add rows at the same time, both rows could be assigned the same serial number, which could lead to confusion (at the least) or data loss (at the worst). For this reason, serial numbers are strongly discouraged!
One way to implement serial numbers is with a normal (not virtual) column named (e.g.) Serial of type Number and an Initial value expression of (MAX(MyTable[Serial]) + 1)
. Each new row will get a serial number one greater than the highest serial number already in use. The very first serial number will be 1.
If a row with a serial number is deleted, a gap in the numeric sequence will occur. To fill-in sequence gaps and reuse deleted serial numbers for new rows:
Create an additional virtual column named (e.g.) Next Serial of type Number and with the App formula expression:
([Serial] + 1)
Replace the Initial value expression of the original Serial column with:
MIN(
LIST(1)
+ MyTable[Next Serial]
- MyTable[Serial]
)
Then, each time a serial number is assigned, it will be the lowest unused number in the sequence. The very first serial number will be 1.
I do have calculation Steve introduces as basic one. The danger to use this is not to place the serial number when app users go to offline mode. Just as additional cautions when someone use this in production apps.
Hi @Steve , this is super useful. Can I ask you for a modification of this that would help me to assign sequential numbers to a set of rows in a table? What I mean by that is, letโs say I have 2 tables on my app, the first is โPatient Bankโ that records basic patient details like the name, age, gender etc. The next table called โFollow Upโ records follow up details of each patient. So the โFollow Upโ table is a โchildโ table referenced to the โPatient Bankโ, which means the โFollow Upโ table has a [Key] column with a UNIQUEID() expression for each entry, and a [Patient Bank Ref Key] column that fetches the relevant [Key] from the โPatient Bankโ table pertaining to the patient.
This โFollow Upโ table has a number type column called [Admission number], and I would like this column to record a sequentially incrementing number (like 1, 2, 3 etc.) when a new โFollow upโ record of a patient is made, but that also means if a โFollow upโ record is made on another patient, that patientโs [Admission number] should start afresh with 1, and then go up as 2, 3 etc. when newer โFollow upโ records are made for that new patient.
Is this doable?
I wrote something like this, but it didnโt bring out what I wanted.
IF(AND(([_THISROW].[Key] <> [Key]),([_THISROW].[Patient Bank Ref Key] = [Patient Bank Ref Key])),
(MAX(SELECT(Follow Up[Admission number], AND(([_THISROW].[Key] <> [Key]),([_THISROW].[Patient Bank Ref Key] = [Patient Bank Ref Key])))))+1
,1)
Your advice would be much appreciated.
Thanks.
Ah, Iโve made a mistake in the expression I wrote. I removed the IF and it works fine now.
(MAX(SELECT(Follow Up[Admission number], AND(([_THISROW].[Key] <> [Key]),([_THISROW].[Patient Bank Ref Key] = [Patient Bank Ref Key])))))+1
Thanks for the inspiration @Steve .
Also combine letters with sequential numbers without having to utilize multiple columns.
This depends on max [_RowNumber] being the same record as the max serial number.
Below expression also assumes it is the key column that is holding the letters plus serials numbers, which are like: abc0001 abc0002 abc0003, etc. If the serial number is in a different column, youโd have to wrap MAXROW() inside a LOOKUP().
"abc"
&
RIGHT(
"000" & ( NUMBER( RIGHT( MAXROW( table , "_RowNumber" ) , 4 ) ) + 1 ) ,
4
)
A little less cumbersomeโฆ
"abc"
&
RIGHT(
"000" & ( MAX(table[_RowNumber]) + 1 ) ,
4
)
No I wouldnโt do that, as that introduces another possible error case.
Imagine you have 3 records:
rowNumbers: 2,3,4
serials: abc02 , abc03 , abc04
First, abc01 doesnโt even exist, because your column header are on row 1.
Second. Imagine you delete record abc03, and not just from the app, you actually delete the row from the sheet (or you have an auto-delete clean-up script that runs regularly). Max row number is now 3+1 again, but serial abc04 is already in use.
Either way, the user must pick where they need to draw the line of acceptable errors if theyโre using sequential numbers.
Oh, yeah, I see what youโre doing now. My bad!
Thanks a lot @Marc_Dillon You saved my day!
I tried this, and the result I get is like this
abc0001
abc0003
abc0004
abc0005
where is abc0002 ?
Looks like it ainโt there.
Yes, right
every 2nd row,
Super helpful.
I do not want to offer a number smaller than 10000
That the (first) lowest number will be
10001
10002
10003
10004 โฆ
I use it โฆ
โโ
MIN(
LIST(1)
โโ
Are you asking a question, or offering another solution? If the latter, you should clean up your posted expression.
IM asking
Is it possible?
Sure.
Something like this should work (Iโm sure there are other solutions as well).
MAX( LIST( 10000 ) + MyTable[Serial] ) + 1
In general, sequential numeric identifiers (i.e., serial numbers) are risky in AppSheet: if two users happen to add rows at the same time, both rows could be assigned the same serial number, which could lead to confusion (at the least) or data loss (at the worst). For this reason, serial numbers are strongly discouraged!
PLEASE DONT LEGITIMATE WEAKNESS WITH STUPID/UNACCEPTABLE REASON. IF APPSHEET IS THE FIRST IN THE EARTH, THEN YOU MIGHT TELL THIS.
Wow, โlegitimateโ (verb) is a real word. Who knew?
Shah please calm down. It is just a formula. Breathe Look, this works for me: just count to 1000 until the anger has passed.
If you donโt get it, just remember: they are serial numbers too
please[Breathe] + 1
I have no idea what this means.
Sorry Steve.
Would like to add to this post something I came across today.
Please keep in mind that if you were to edit a row with a sequential number (via App Formula), the sequential number would get updated.
In my app, I require the given serial number to stay the same.
So, I use this (MAX(salesdata[serial_id]) + 1) as an initial value instead.
Thereโs a high probability that a mistake will be made but this is the only way I know to work around it so far.
If anyone knows a much safer solution, please share.
Thank you.
Yes, definitely use Initial Value and NOT App Formula. You may also consider setting the Editable_If to FALSE
to prevent any user-modification.
Or Editable_If to ISBLANK([COLUMN_TO_PREVENT_THE_USER_INTERACTION])
if you need your users to see it but not touch it
Yeah. Sequential is not intended for AppFormulas
Thatโs pretty neat. Updated instantly.
Thank you very much!
Hi Steve,
With the serial numbers issue, and recycling old numbers, how do you make it so it is counting rows that share the same reference unique ID.
Right now this formula works perfectly for the whole data set..
MIN( LIST(1) + MyTable[Next Serial] - MyTable[Serial] )
but I need it to count rows that share the same reference. Can you help?
@Dan_Oliphant wrote:With the serial numbers issue
Which one?
I am trying to use the recycling old numbers solution. But that works for the entire spreadsheet. I need it work work that same way, but within the database with each set of rows that share a unique reference.
i believe this works. Been testing it and seems like it does.
MIN(
LIST(1)
+ (SELECT(bol_addcharges[Next_Serial], [_THISROW].[job_uid] = [job_uid]))
- (SELECT(bol_addcharges[misc_title], [_THISROW].[job_uid] = [job_uid]))
)
Brilliant!! Thank you so much!! ๐๐๐๐
Very Helpful!! Thank You!! ๐๐