FUNCTION LastNumber( xcTAbla , xcIndice , xcCampo , xnDigitos )
&& Si se omite xnDigitos, se autodetermina para el caso de Character
&& xnDigitos no se emplea en caso Numeric o Interger
LOCAL lcOrder,lnRecord,lcType,lcEval,lFlag,lnValor,;
lcExact,lnElemen
LOCAL ARRAY gaFields(1)
* <Detección de errores>
IF EMPTY(xcTabla)
MESSAGEBOX("No consignó el nombre de la tabla")
RETURN ""
ENDIF
IF EMPTY(xcIndice)
MESSAGEBOX("No consignó la etiqueta de índice")
RETURN ""
ENDIF
IF EMPTY(xcCampo)
MESSAGEBOX("No consignó el nombre del campo de control")
RETURN ""
ENDIF
IF !USED(xcTabla)
MESSAGEBOX("La tabla &xcTabla no está en uso")
RETURN ""
ENDIF
AFIELDS(gaFields,xcTabla)
lcExact=SET("Exact")
SET EXACT ON
lnElemen=ASCAN(gaFields,UPPER(xcCampo))
SET EXACT &lcExact
IF lnElemen=0
MESSAGEBOX("El campo indicado no existe en la tabla &xcTabla")
RETURN ""
ENDIF
lcType=gaFields[lnElemen+1]
IF lcType="C"
xnDigitos=EVL(xnDigitos,gaFields[lnElemen+2])
ENDIF
IF !INLIST(lcType,"C","N","I")
MESSAGEBOX("El campo &xcCampo indicado tiene un tipo incorrecto")
RETURN ""
ENDIF
* </Detección de errores>
lcEval=xcTabla+"."+xcCampo
lnValor=0
select (xcTabla)
lcOrder=Order()
lnRecord=Recno()
SET ORDER TO (xcIndice)
go bott
if !eof()
IF lcType="C"
&& Rulo en prevención de que existan
&& códigos alfabéticos reservados.
DO WHILE VAL(EVALUATE(lcEval))=0
SKIP -1
IF BOF()
lFlag=.t.
EXIT
ENDIF
ENDDO
IF !lFlag
lnValor=VAL(alltrim(Evaluate(lcEval)))
ENDIF
ELSE
lnValor=EVALUATE(lcEval)
ENDIF
ENDIF
* Reponer el estado en que se encontró
if !Empty(lcOrder)
set order to (lcOrder)
endif
if !empty(lnRecord)
go LnRecord
ENDIF
* Devolver el valor de acuerdo al tipo detectado.
Return IIF(lcType="C",;
Padl(LTRIM(STR(lnValor+1)),xnDigitos,"0"),;
lnValor+1)
ENDFUNC