custom number format

ksgirl

Registered User.
Local time
Today, 17:42
Joined
Jul 1, 2002
Messages
53
OK. Here is my problem. I need a number/text (I'm pretty sure I need a text) format that does the following: 02-00000. The first two digits are the last two digits of the year and the last five digits are incremented by one each time a new one is needed. This is what I've worked on so far:
=Format(Now(),"yy") & "-" & Format(.....this is where I need help!)
and have placed it in the default value of the field's properties in the table design view. So far I get the "02-" to show up!!! But I'm not sure if I need to use Dmax or what for the rest of the number format! I'm really clueless, so if anyone has any information to steer me in the right direction I would aprreciate it.
:confused:
~Nicole
 
You can't use functions (except for Date() and Now()) in table design so you would have to generate your id in the beforeUpdate event of a form.

Much better to use an autonumber. Search the archives for lots on this topic. When you generate your own id in a multi-user environment, don't forget to handle the potential for duplicates.
 
If I generate this in a BeforeUpdate event how do you suggest I do this? I've searched through the forums and can't find much help. I've been given advice on this same topic and another Access Programer suggested to do what I stated in the first post....so now I'm confused! I ultimately want the table to generate these numbers like an autonumber format....just with the "02-" for the year!!! I know I can just go in and type that as a prefix to the autonumber, but I don't want to have to change that when the year turns over. There has to be a way to do this. Does anyone else have any suggestions????
 
ksGirl,
It is possible to do what you want, but as Pat suggested you should explore alternatives first, like using an internal autonumber and only displaying your built key on will (not storing it, much less even using it as a primary key)
Ex: use an internal autonumber and a textbox to display:
Format(Now(),"yy") & "-" & [ID]

Now, this will quickly show you the limits of this approach and why you should think carefully before using built ID.
Ex:
you have 3 records:
1 -> 02-0001
2 -> 02-0002
3 -> 02-0003
Now an user deletes record 1 and 3 and adds a new record. The new situation will become:
you have 2 records:
2 -> 02-0002
4 -> 02-0004

Other example
you have 3 records:
1 -> 02-0001
2 -> 02-0002
3 -> 02-0003
Now an user cancels a new record he/she was entering. Late he/she adds a new one. The new situation will become:
you have 3 records:
1 -> 02-0001
2 -> 02-0002
3 -> 02-0003
5 -> 02-0005

You cannot expect to have consisent sequential numbers that way.Does it mind to you?
If yes, then 1. you've already understood that you should NOT take the risk to build AND rely on them as primary keys. 2. I can show you a method to avoid such gaps but you should keep in mind that it is not 100% reliable in multi-users and replication environements.
 
Last edited:
I do not need consistent sequential numbers....all I need is a numbering field to display "02-00000". If one is deleted, say 02-00005, and the next one displayed is 02-00006....that is great! I just need a way of having an ID number that displays the current year as the first two digits and increments so that each ID has an unique value! I hope this helps! Let me know if you need more information!
~Nicole
 
Then, in the controlsource of a control on your form, put:
=Format(Now(),"yy") & "-" & left("00000",5-len(cstr([ID]))) & [ID]
where ID is the name of a textbox (eventually hidden) of your form, bound to the autonumber ID of your records.

but you will run into troubles if your autonumber happens to reach 100000 (which does't mean 100000 records as showed above)
 
Last edited:
So if I understand this correctly, the ID won't save in the table as the format I want? It will just display on the form? If this is the case, I don't want this to happen. I want to be able to save the ID with the "02-" or "03-" in front of it into the table. This is because there will be a historical table that has ID's clear back to 1980's so there will be "85-", "93-", etc...... I just want the new ID's to have the same format! Maybe I'm just making this too complicated. I know it can be done, I just need pointed in the right direction. Is there anyway this can be done? Thanks for all the help Alexandre....I appreciate it greatly!
~Nicole
 
The formula I provided to you can be used to store the result in your underlying table if you really want to. But you should not. Make a new field to store the year instead. Then, at any moment, you can retrieve the serial number by using the formula.
If you store the result of the formula, you duplicate data in your DB (Date and/or autonumber) to the least. Potentially, you also create room for inconsistancy among the data you stored since it is hard to ensure that under all cirumstances (updates, deletions, data import...) your built and stored serial number will be properly updated to reflect your Year field and your autonumber.

Now if you really want to do it, you CAN. This is just not a good idea.
To automatically store the year , there are various approaches available. I believe the easiest consists in (after creating the adequate field in your underlying table) setting the fied default value the default value to:
=Right(Year(Now(),2)) to only store the current year (my advice)

Now if your want to store your serial, it is more complicated because you can't refer to fields in the same table in a formula set at table-level.
You'll have for example to set a textbox bound to your serial field on your form, with the default value:
Format(Now(),"yy") & "-" & left("00000",5-len(cstr([ID]))) & [ID]
Or you can also do it using the Before Update event as Pat suggested...
But remember, whatever the method you will use, you will have difficulties to ensure that it won't fail under certain circumstances (ex: data import, action query, pasted records...)

Hope this helps
 
Last edited:
I know it is demanding much for someone like you, Rich. But try to keep serious an do some useful work, for a change. I don't know... For example, find Title for me! :)


BTW, I thought I had some understanding of French, but while I know what is 'bas' and 'bleu', 'bas-bleu' is something new to me. Is this another wild, progressist English concept? (like your unequalled measurement units system, or something of the kind...) :D
 
Last edited:
I guess I'm confused now. I am still extremely new to all of this, so be gentle! Let me give you a run down of my situation. I am an intern doing a project.....long summer to say the least. Anyway, they have a current system, but want something that is more user-friendly....this is where I come in....and they want me to do this on access. Currently the system they have has all the ID's generated from years past stored in the usual format. I am just trying to make my life simpler for when I have to transfer all the past ID's into the new system. I know I am going to have a historical table of all these ID's (where I just input the existing ones into a field in the "00-00000" format), but the new system needs to be able to generate such a number. I guess I don't understand why you say that...
"If you store the result of the formula, you duplicate data in your DB (Date and/or autonumber) to the least. Potentially, you also create room for inconsistancy among the data you stored since it is hard to ensure that under all cirumstances (updates, deletions, data import...) your built and stored serial number will be properly updated to reflect your Year field and your autonumber."

Why is not a good idea to store the year in front of the autonumber? That is how the other ID's are stored! Basically, a user will be able to access the database to either create a new Clearance, or to look at old Clearances by this ID. They will input 95-04672 etc....to look at that Clearance. Does this make sense?

I did try what you suggested, by adding the serial field and another text box to the form with the appropriate default value, and all I get in the new text box is "02". Maybe I need to get rid of the autonumber format with the current ID field and come up with a way to just increment the last five digits of the ID. I'm just lost! Thanks for all your help. If you have any other suggestions, it would be greatly appreciated.
~Nicole
 
Actually, old heavy one, I was being serious. I've seen many posts where posters insist on storing pk's /nos. in this way and have always wondered what advantage this gave db. design.
After your lurid explanation I now realise there is none, and further investigation is pointless.
bas_bleu is next in line for Poo_Bah:)
 
ksGirl,

I am going to tell you what I believe is the best to do and that I would most sincerily do if I were in your case. I had VERY painfull experiences with built-and-stored Primary keys when I worked on replicated DBs and sweared I would never go into this again.

I would:
1. Seek to save into an excel spreadsheets all tables holding those serial numbers that you have to import from the old DB.
This is because you will be able to easily do some string-processing there,
2. Using two formulas, split the serial number into two columns, and give names (ID and Year) to these columns: Right(A1;5) will give you the 5 digits number and Left(A1;2) the two digits year
Note that you could also import your tables directly into acces and use action queries for the same result, but this seems simpler.
3. Create your destination tables in Access with the fields:
- ID as an autonumber
- Year as an integer
... your other fields
4. Use the GetExternalData -> Import Menu to import your Excel spreadsheets into your tables.
5. If you did it well, the autonumber field should be filled with your 5 digits numbers, your Year field with the rest of your serial key and you will be able to apply the method I suggested from now on in your new database (ie use a formula to display, do not store, and set default value for theyear field)

Does this help?

Edit: Forgot something important. Actually the autonumber (ID) is not your primary key in this case. Instead, you would use a two-fields primary key made of Year and ID (select both fields in table design and make them a primary key. A key symbol should show on both lines if you suceeded)
 
Last edited:
I really think that IDs created this way are STUPID. That's my opinion and I'm sticking to it :).

However, since you have lots of data to convert and it already has IDs that have been generated using this method, you don't really have any alternative. So here is what I would do.

1. Separate the year part and the number part into two fields. You'll need to talk to the users about sort order because if you stick with the two digit year as the first field, you'll end up with sorting difficulties since 00, 01, 02, etc. will all sort before 85, 86, etc. Ask about the possibility of changing to a four digit prefix if this will present a problem for them. You can expand the year field after you import the old data into the separate fields.
2. You'll have to restrict their access so that ALL rows are inserted via your form.
3. In the BeforeUpdate event of the form, use a DMax() to find the next available serial number.

NextNum = Format(Nz(DMax("SerialNum","YourTable","YearPrefix = Format(Date(),"yy")),0) + 1,"00000")

This statement finds the record with the maximum sequence number value where the two digit year is equal to the current year. This method has only one redeming feature, it restarts the serial numbers at 1 automatically when the year changes.
4. For printing purposes or display purposes (the primary key field should ALWAYS be locked on a form since you're generating it), you can concatenate the two fields and the users will never know the difference.
YearPrefix & "-" & SerialNum

PS I forgot to warn you that you will need to handle the possibility of generating duplicate numbers if multiple users may be adding records at the same time. I suggested the BeforeUpdate event since this is the LAST possible moment before the record is actually saved and you would be unlucky to run into contention. But, if you have any intention of actually becomming a programmer, you need to understand proper error trapping and you may as well start now. Plus as Alexandre said, limiting the sequence to 5 digits may cause problems since it only allows for 99,999 records per year.
 
Last edited:
BTW, you will notice that your autonumber will continue numbering starting from the highest value you imported in your table. And if that number is already high you will feel relieved to have followed my advice (because your 00-00000 format would have failed as soon as the autonumber reaches 100000).

Let me sum up why this is better than storing the 00-00000 serial:
- Method never fails even if the autonumber goes over 99999 (which can happen WITHOUT having 99999 records in your table, see my previous example)
- No data redundancy
- No risk to get unconsistent data if the user does something that does not trigger your build-and-store-my-serial-key strategy.
- No risk to create conflictual (duplicate when they ought to be unique) serial keys in multi-users or replication environments.

Please, tell me that you are less confused about this, now...:)
 
Last edited:
Thanks Pat and Alexandre. I will tackle your suggestions in the morning! Alexandre- I do now understand why, but in my mind, and of course I'm naive about things, there should be a simpler way!!! I think having an ID this way is stupid too, but as Pat has mentioned, I really have no other options! I came into this internship not knowing anything about access and have self-taught myself along the way....that is probably my biggest problem. I guess that is what I deserve being an engineering student! I'm only here for five more weeks, and then they will pass this task onto someone else! So I have to tough it out for now! Fun, fun! I am very greatful I have found such a wonderful website and people like you to give people like me advice! Thanks again, and keep your eyes posted...I'm sure I'll have more questions involving this one!
~Nicole
 
I just feel like I'm making a fool of myself over this stupid question! And both of you have been wonderful in trying to help me, so I thought I would rack your brain some more. Ok....I think this might work. Let me give you a run down of what I've done:

In the table:
*two fields- 'Clearance ID' (autonumber) and 'Year' (default property set to =Format(Now(),"yy"))
?Do I need to set both of the fields to be primary keys?

In the form:
*Clearance ID field-
Control Source= [Clearance ID]
Default Value= [Year] & "-" & [Clearance ID]
Before Update= [Event Procedure]

Private Sub Clearance_ID_BeforeUpdate(Cancel As Integer)

Dim stNextNum As String

stNextNum = Format(Nz(DMax("[Clearance ID]",
"[Clearance Cover Page]", "Year = Format(Year(Now(),2))"),
0) + 1, "00000")

End Sub

Everything seems to be working fine, no errors at least. But it doesn't store in the table as the "00-00000" format. Plus, when I go to just search the current clearance table, (I have a query that runs the search and a message box pops up for you to enter in a Clearance ID), you just type in "1" not "02-00001" and it pulls up the whole Clearance. I would like for the user to type in the whole format...which I believe they will have to with the 'old' clearance IDs. Oh and when you are entering in a Clearance (on the first form), in the 'Clearance ID' field the number that appears is "00-00023"....somewhere along the lines the "02-" is missing. Am I over looking something? If you are too busy, don't worry about me....I'll just keep plugging away. But I do appreciate all your help. Thanks again.
~Nicole
 
1. You have to make a choice between Pat's suggestion and mine. They are fundamentally the same with one difference: Pat provided you with a formula that simulates an autonumber and WILL RESET for each different year (ex: 02_00001, 02-00002, 02-00003, 03-00001), but you will have to manage POTENTIAL DUPLICATE keys conflicts in multi-users environment, as she explained.
Mine won't reset (ex: 02_00001, 02-00002, 02-00003, 03-00004), but uses true increment autonumber (so you don't have to worry about duplicates. This is managed by Access)
If you decided to go for the autonumber, you can use a two-fields primary key as I suggested, but you do not really need to, since Access will take care of ensuring the uniqueness of the autonumber. It would be really necessary if you decided to use Pat's formula which do not produce unique numbers, but reset for each new years (In that case, only the association year + number may be unique)

2. Neither my nor Pat's suggestion will ever store a built serial key in 00-00000 format in your table. We both exposed extensively why this would be bad practice! Our suggestions will store separately the year and a sequential number, and DISPLAY your 00-00000 format serial. Your users won't see the difference.
Perhaps I was not clear on that, but Pat was: you won't let anyone fill the serial number. On the contrary you will disable/lock this control. Your serials are built automatically through the methods we suggested!
It is a VERY bad idea to let the users enter/modify primary keys! Among various reasons for that: you would have to write code to trap already existing keys entered by your user and get them corrected; You would have also to provide to your users an easy mean to know what keys have already been used...

3. Did you consider Pat's advice regarding negotiating the year format with your customers? (code the year on 4 digits instead of 2). This is something I had hesitated to recomand also. Although not vital, it is practical.

4. Your form Clearance_ID control is not ok. First call it txtSerial, for example, to avoid any confusion with the Clearance_ID field which is only an incrementing number, not the entire serial you want to display. Then, with the method we suggested, you would not use a bound control since your built serial key would not actually be stored in your database. You would just display it on the fly. So txtSerial should be an unbound textbox with acontrol source set to : = [txtYear] & "-" & [txtClearance ID]

5. I suggested to use the default value =Right(Year(Now(),2)) for your txtDate bound control, and not for txtSerial, as an easy mean to store the current year in your underlying table whenever a new record is created.

6. I don't know where you took Format(Year(Now(),2))
I suggested Format(Now(),"yy") and Right(Year(Now(),2)) (unconsistent me ;))
and Pat's: Format(Date(),"yy")
All give the same result. Pat's formula is somewhat more efficient.

7. The above mentionned = [txtYear] & "-" & [txtClearanceID]
in txtSerial implies that you should have two other controls on your form called txtYear and txtClearanceID (note the prefixes to help to distinguish between controls and fields, and to identify a textbox)
These are bound (to Year and ClearanceID) controls, which may be invisible. Why using invisible text boxes ? There would be other ways to get the Year and ClearanceID corresponding to the current record of the underlying table, but this is a very simple way to have them at disposal automatically.

8. Avoid spaces in you field and table names: use Clearance_ID or ClearanceID and ClearanceCoverPage etc.

Please, tell me if I am speaking Chinese. I know my poor English can be confusing. You may get clearer explanations from Pat or others.
 
Last edited:
Alexandre, your mastery of English should put many native speakers to shame. I cringe inside when I read the posts of supposidly educated people who don't know the difference between your and you're and their, there, and they're, etc.

There is one point I would like to make regarding the autonumber solution (which of course I prefer). Due to the existing body of data, I don't believe that a standard autonumber will work. I suspect that the old system started numering again in January of each year. So, without the year prefix, there would be duplicates in the serial number portion making it impossible to load them into an autonumber field. If that is not true, then autonumber will work and is recommended. If my suspicion is true, autonumber will not be usable.
 

Users who are viewing this thread

Back
Top Bottom