Last month, I had an article about a script to auto-increment field values (instead of using the field rule). I pointed out that one disadvantage was that you would lose a number if you cancelled the records; i.e., if the next number available was 1002, and you cancel the record, the next new record would be 1003, and 1002 would no longer be available.
Ray DiFazio wrote to me about this disadvantage, and came up with a very elegant way to avoid it (I'm sure all you accountants out there will be happy). Here's his idea:
Put PENDING in the field rules as the default value for the field (make sure you check the first box, Set value at start of data entry).
Put .T. in the Skip field rule for this field, to prevent the user from changing the value.
Create an auto-increment script for the OnSave event of the form.1
If there is an embedded one-many child browse, create a second auto-increment script for the CanArrive event of the browse.
Instead of assigning the next number when the record is first created, Ray put PENDING in the field to be incremented. Then, when the field is saved, the auto-increment script assigns the number. This way, if the record is cancelled before the save, the number will not be used, and therefore not lost.
To accomplish this, we have to do four things:
1.
2.
3.
4.
The first auto-increment script is:dim global newjob as c
t = table.current()
pendjob = t.job
IF pendjob <> "PENDING"
end
END IF
tm = table.open("menu")
job = tm.job
newjob = padl(ltrim(str(val(job)+1)),5,"0")
tm.change_begin(.t.)
tm.job = newjob
tm.change_end(.t.)
t.change_begin()
t.job = newjob
t.change_end(.t.)
parentform.resynch()
In this script, job is the character field to be incremented, menu is the table where the job number is stored. Note that the calculation for newjob uses the padl() function to put leading zeros in front of the number (in this case, it will put enough zeros to make the value 5 characters long). This will assure that the numbers sort properly.2
The second script is needed for a one-many child browse. This is because if you click in the browse directly from the form, the first script will not fire (even though the record is saved when you go from the form to the browse). This script takes care of that:
dim global newjob as c
t = table.current()
pendjob = t.job
IF pendjob <> "PENDING"
end
END IF
tm = table.open("menu")
job = tm.job
newjob = padl(ltrim(str(val(job)+1)),5,"0")
tm.change_begin(.t.)
tm.job = newjob
tm.change_end(.t.)
t.job = newjob
parentform.commit()
parentform.resynch()
This script is nearly identical, except that the change_begin and change_end from the first script are not there (since the table is currently in ENTER mode), and parentform.commit() is used to save the parent.