Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Go bottom
Message
 
To
10/10/2004 05:18:59
General information
Forum:
Visual FoxPro
Category:
Coding, syntax & commands
Title:
Miscellaneous
Thread ID:
00950231
Message ID:
00950251
Views:
13
Mohammed,

> i put my code under to count how many bills i have at my table to increase for new bill
>
> any new idai.
>
> SELECT 1
> GO BOTTOM
> THISFORM.TEXT1.VALUE=BILLNO+1
>
Problems with this as well as with the two other approaches can occur if You are in a MultiUser-Environment and work with Tablebuffering (but even without)

Imagine User 1 retrieves the next Bill-No (lets say 123) and works on with the bill. User 2 also retrieves the next Bill-NO and if he does before User1 saves the bill, will also receive 123. Even if User1 saves before User 2 requests the Bill-No, User2 might not have the new records yet, depending on SET REFRESH

For cases like this I Use a table that holds the current ID (or bill-no if You like) and this table is only accessed by a method NewID(). that looks somewhat like this:
*=========================================================
*
*         FUNCTION: NewID             
*
*=========================================================
FUNCTION NewID             
*  Created...........:  20.Juli 2002, 11:36 Uhr
*  Changed...........:  26.07.2002
*                        Standort-ID wahlweise über Feld
*                        in der Tabelle
*  Description.......:  Neue ID für eine Tabelle erzeugen
*  Calling Samples...:  ?NewID(<ExpC>[,<ExpN>[,<ExpL1>[,<ExpL2>]]])
*  Parameters........:  tc_Key, tn_Len, tl_NoFill, tl_Numeric
*  Returns...........:  Character or Numeric
lparameters    tc_Key, tn_Len, tl_NoFill, tl_Numeric, tl_KeepOpen
LOCAL ln_WasSel, lc_ID, lc_OldReproc, lv_RetVal, ln_Len

tc_Key     = iif(vartype(tc_Key) = "C", tc_Key, alias())
tn_Len     = iif(vartype(tn_Len) $ "IN", tn_Len, 10) 
tl_NoFill  = iif(vartype(tl_NoFill) = "L", tl_NoFill, .F.)      && fill with leading zeroes
tl_Numeric = iif(vartype(tl_Numeric) = "L", tl_Numeric, .F.)  && return numeric
*-- Keep the Control-File open if it 
*-- was not used before?
tl_KeepOpen= iif(vartype(tl_KeepOpen) = "L", tl_KeepOpen, .F.)

*-- Globale Standort-Variable
*-- zur sicheren Unterscheidung
*-- der Zähler
if vartype(gc_Standort) # "C"
    public gc_StandOrt
    gc_StandOrt = "T"
    gc_Standort = InputBox("Standort-Kürzel eingeben","Standort-Kürzel",gc_Standort,10000, gc_Standort)
endif    

ln_WasSel         = select()
lc_OldReproc     = set("Reprocess")
ll_WasUsed        = used("PP_CONTROL")

*-- von der Länge ggf. die Länge
*-- des Prefix abziehen
*-- if ! tl_Numeric
*--     ln_Len = tn_Len - len(gc_Standort)
*-- else
    ln_Len = tn_Len
*-- endif        

set Reprocess to AUTOMATIC

if ! ll_WasUsed 
    use PP_CUST!PP_CONTROL in 0
endif
select PP_CONTROL

*-- Key auf die Länge des Feldes
*-- auffüllen, damit ich nicht versehentlich
*-- mal falsch lande
tc_Key = padr(upper(tc_Key),len(PP_CONTROL.KEY_NAME))

if ! Seek(tc_Key, "PP_CONTROL", "KEY_NAME")
    *-- Schlüssel nicht gefunden, dann anlegen
    *-- und mit 2 initialisieren. Die jetzt be-
    *-- nötigte ID ist dann 1
    insert into PP_CONTROL (KEY_NAME, VALUE, STANDORT, EDITABLE);
      values (tc_Key, str(2, len(PP_CONTROL.VALUE)), .F., .F.)
    lc_ID = str(1, ln_Len)
else
    if rLock("PP_CONTROL")
        lc_ID = PP_CONTROL.VALUE
        replace PP_CONTROL.VALUE with str(val(allt(lc_ID))+1, len(PP_CONTROL.VALUE))
        
        unLock
    endif      
endif

do case
case tl_Numeric
    *-- Als integer zurückgeben
    lv_RetVal = int(val(lc_ID))
    
case ! tl_Numeric and tl_NoFill
    *-- nicht aufgefüllt
    if PP_CONTROL.STANDORT
        ln_Len       = ln_Len - len(gc_Standort)
        lv_RetVal = gc_Standort + padl(allt(lc_ID), ln_Len)
    else
        lv_RetVal = padl(allt(lc_ID), ln_Len)        
    endif        
other
    *-- Character aufgefüllt mit Nullen
    if PP_CONTROL.STANDORT
        ln_Len       = ln_Len - len(gc_Standort)
        lv_RetVal = gc_Standort + padl(allt(lc_ID), ln_Len, "0")
    else
        lv_RetVal = padl(allt(lc_ID), ln_Len, "0")
    endif        
endcase        

if ! ll_WasUsed and ! tl_KeepOpen and used("PP_CONTROL")
    use in PP_CONTROL
endif    

select (ln_WasSel)
set repro to (lc_OldReproc)
    
return lv_RetVal
*-- eof NewID
The table PP_CONTROL looks like this:
KEY_NAME   char(25)  + INDEX
VALUE      char(25)
EDITABLE   LOGICAL
STANDORT   LOGICAL
KEY_NAME is the Key to the number You want. In Your case this would be "BILL_NUMBER" or something like that.
I also use this for the generation of primary keys. In these cases it's the default ALIAS of the
Table ("CUSTOMER")

VALUE is the current Value. That Would be "123". Don't ask me why we made it a character-field. I'm sure
we had a good reason for that ;-)

EDITABLE You might want Your Customer to be able to set one or the number like the current Customer-Number or
the bill-Number. However You definitely do not want Your customers to be able to modify Your PK-
Numbers. That's what this flag is for.

STANDORT Some of my Applications are distibuted Applications that gather Data from several places. Now if
my PK's simply count from 1 to x, I probably get the same PK in Hamburg and Berlin. So, to make the
numbers unique, a character representing the Office is placed in front of the Number. If STANDORT
= .T. a generated ID will be something like "B00000123" where "B" is for "Berlin"

HTH
Regards from Berlin

Frank

Dietrich Datentechnik (Berlin)
Softwarekombinat Teltow (Teltow)

Frank.Dietrich@dd-tech.de
DFPUG # 327
Previous
Reply
Map
View

Click here to load this message in the networking platform