Antonio, James, NageswaraRao and all others,
we decided to publish the source code of this puffer-search, that was causing us the performance problems. Maybe it can be of help to someone of you for your own programs.
First a screenshot, it's the blue get-field in the bottom-right corner and responds to the active order that is chosen.
DEFINE MESSAGE OF oWin
DEFINE MSGITEM oPuffertext OF oWin:oMsgBar PROMPT "Puffersuche: " SIZE 120
DEFINE MSGITEM oPuffer OF oWin:oMsgBar ;
SIZE 120 COLOR "R*/BG" ;
ACTION (IIF(MsgYesNo("Puffer löschen?",oPuffer:cMsg),oPuffer:SetText(""),))
oWin:bLostFocus := {||oPuffer:SetText("")}
And this is our buffer-search function:
// Puffersuche mit TGET Feld: der Typ des Anzeigefeldes wird vorher abgefragt
FUNCTION Puffer(nKey,KeyFlags,oPuffer,oLB) // Puffer Suche in Browser Listen
LOCAL cAlias
LOCAL nOldSelect
LOCAL nOldRec
LOCAL cSuchPuffer
LOCAL cPuffer
LOCAL L_DATUM,L_PUFFER
LOCAL cField,nPos
LOCAL cIndexKey, cIndexTyp
LOCAL nYear
LOCAL dTemp, cTemp, nTemp
LOCAL lGet := .f. // bei oPuffer handelt es sich um ein TGET-Object
LOCAL nVor
LOCAL cVorField
cAlias := oLB:cAlias
nOldRec := (cAlias)->(RecNo())
if oPuffer:ClassName()=="TGET"
lGet := .t.
endif
cSuchPuffer := IIF(lGet,oPuffer:VarGet(),oPuffer:cMsg)
DO CASE
CASE nKEY==VK_BACK // letztes Zeichen löschen
if !EMPTY(cSuchPuffer)
cSuchPuffer := SUBSTR(cSuchPuffer,1,LEN(cSuchPuffer)-1)
IIF(lGet,oPuffer:cText(cSuchPuffer),oPuffer:SetText(cSuchPuffer))
return .t.
endif
CASE nKey < VK_SPACE // bei allen anderen Steuerzeichen zurĂŒck
return .t.
OTHERWISE
cSuchPuffer += CHR(nKey)
ENDCASE
// bei leerem Suchpuffer zurĂŒck
if EMPTY(cSuchPuffer)
return .t.
endif
// max. PufferlĂ€nge berĂŒcksichtigen
if LEN(cSuchPuffer) > 25
cSuchPuffer := SUBSTR(cSuchPuffer,LEN(cSuchPuffer),1)
endif
// Tabelle wird ohne Index angezeigt
if (cAlias)->(IndexOrd())==0
(cAlias)->( dbGoto(MAX(MIN(Lastrec(),VAL(cSuchpuffer)),1)) )
DO WHILE (cAlias)->(Deleted()) .and. !(cAlias)->(EOF())
(cAlias)->(dbSkip())
ENDDO
else
// Typ eines Indexes lĂ€Ăt sich nur bestimmen, wenn die Datenbank selectiert ist !!
nOldSelect := Select()
Select(cAlias)
cIndexKey := IndexKey(IndexOrd())
cIndexTyp := TYPE(cIndexKey)
Select(nOldSelect)
//** werte den Puffer aus
// numerisch
IF cIndexTyp=="N"
(cAlias)->(dbSeek(VAL(cSuchPuffer),.t.)) // mit Softseek
// reine Datumswerte
ELSEIF cIndexTyp=="D"
dTemp := &(cAlias+"->"+cIndexKey)
if Empty(dTemp)
dTemp := Date()
endif
IF LEN(cSuchPuffer)==3 .AND. !SUBSTR(cSuchPuffer,3,1)="."
cSuchPuffer := STUFF(cSuchPuffer,3,0,".")
ENDIF
IF LEN(cSuchPuffer)==6 .AND. !SUBSTR(cSuchPuffer,6,1)="."
cSuchPuffer := STUFF(cSuchPuffer,6,0,".")
ENDIF
// abhĂ€ngig von 4 oder 2-stelligen Jahreszahlen entsprechend auffĂŒllen
cPuffer := DTOC(dTemp)
nTemp := MIN(LEN(cSuchPuffer),6)
cTemp := Substr(cSuchPuffer,1,nTemp)
cPuffer := STUFF(cPuffer,1,nTemp,cTemp)
nYear := IIF(__SetCentury(),4,2)
cTemp := Substr(cSuchPuffer,7,nYear)
nTemp := LEN(cTemp)
cPuffer := STUFF(cPuffer,7+nYear-nTemp,nTemp,cTemp)
// Pufferinhalt suchen (als Datum)
(cAlias)->(dbSeek(CTOD(cPuffer),.t.))
ELSEIF "DTOS"$UPPER(cIndexKey)
nPos := At("DTOS",UPPER(cIndexKey))
cField := Substr(cIndexKey,nPos+4)
cField := Sparse(cField)
// Basisdatum herausfinden
dTemp := &(cAlias+"->"+cField)
if Empty(dTemp)
dTemp := Date()
endif
// Herausfinden, wie lang der Vorspann ist
cVorField := Substr(cIndexKey,1,nPos-1)
nVor := LEN(&(cAlias+"->"+cVorField+"'')"))
IF LEN(cSuchPuffer)==(nVor+3) .AND. !SUBSTR(cSuchPuffer,(nVor+3),1)="."
cSuchPuffer := STUFF(cSuchPuffer,(nVor+3),0,".")
ENDIF
IF LEN(cSuchPuffer)==(nVor+6) .AND. !SUBSTR(cSuchPuffer,(nVor+6),1)="."
cSuchPuffer := STUFF(cSuchPuffer,(nVor+6),0,".")
ENDIF
cPuffer := DTOC(dTemp)
nTemp := MIN(LEN(cSuchPuffer)-nVor,6)
cTemp := Substr(cSuchPuffer,1+nVor,nTemp)
cPuffer := STUFF(cPuffer,1,nTemp,cTemp)
nYear := IIF(__SetCentury(),4,2)
cTemp := Substr(cSuchPuffer,(7+nVor),nYear)
nTemp := LEN(cTemp)
cPuffer := STUFF(cPuffer,7+nYear-nTemp,nTemp,cTemp)
// Inhalt des Vorspanns bestimmen
cTemp := SUBSTR(cSuchPuffer,1,nVor)
if "UPPER"$UPPER(cVorField)
cTemp := UPPER(cTemp)
endif
// Text as Buffer-Search
if LEN(cSuchPuffer)>nVor
(cAlias)->(dbSeek(cTemp+DTOS(CTOD(cPuffer)),.t.))
else
(cAlias)->(dbSeek(cTemp,.t.))
endif
ELSEIF "UPPER"$UPPER(cIndexKey)
(cAlias)->(dbSeek(UPPER(cSuchPuffer)))
ELSE
(cAlias)->(dbSeek(cSuchPuffer))
ENDIF
endif
IIF(lGet,oPuffer:cText(cSuchPuffer),oPuffer:SetText(cSuchPuffer))
IF !(cAlias)->(EOF())
(cAlias)->(dbSkip(1))
if (cAlias)->(EOF())
oLB:GoBottom()
else
(cAlias)->(dbSkip(-1))
//oLB:Refresh() // This made our search slow, because after every
oLB:select(0)
oLB:select(1) // This also does the trick for a refresh
oLB:lHitTop := .f.
endif
ELSE
(cAlias)->(dbGoto(nOldRec))
ENDIF
return .t.