XbpBrowse() und :colorBlock

Alle Fragen um die Programmierung, die sich sonst nicht kategorisieren lassen. Von Makro bis Codeblock, von IF bis ENDIF

Moderator: Moderatoren

Antworten
JanR
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 129
Registriert: Di, 18. Okt 2005 14:44

XbpBrowse() und :colorBlock

Beitrag von JanR »

Hallo,

hat schonmal jemand mit XbpBrowse:colorBlock gearbeitet? Ich möchte die Daten in dem Browse je nach Wert in verschiedenen Farben anzeigen lassen. Lokal klappt das ja ganz gut, aber im Netzwerk ist es extrem langsam. Hat jemand eine Idee, wie man das Performancemässig schneller bekommt?


Danke.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15696
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Hallo Jan,

was machst du denn (wie sieht der Code aus) und ist es beim normalen browsen schon langsam oder nur bei color block ?

Im allgemeinen sollte man keinen Filter nutzen, ohne die Satzmenge über set scope deutlich zu reduzieren. Dann sollte man die DAC... Klasse nehmen, da diese zwischenpuffert. Nur so aus der Hüfte :wink:
Gruß
Hubert
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9361
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Beitrag von Tom »

Hallo, Jan.

Was steht denn in Deinem :colorBlock-Codeblock? Eine Abfrage der Art:

Code: Alles auswählen

:colorBlock := {|x|IF(Len(Trim(x))>0,{GRA_CLR_WHITE,GRA_CLR_BLACK},{GRA_CLR_RED,GRA_CLR_WHITE})}
hat überhaupt nichts mit Netzwerk oder nicht Netzwerk zu tun.
Herzlich,
Tom
JanR
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 129
Registriert: Di, 18. Okt 2005 14:44

Beitrag von JanR »

Hallo Hubert,
Hallo Tom,

aus der Datenbank wird erst der Inhalt abgefragt und je nach Inhalt wird dann die Farbe gesetzt. Die Farben sind aber auch in einer Datenbank. Lokal läuft alles super schnell, aber sobald die Anwendung im Netzwerk läuft, wird es langsam.

Mein Quellcode sieht folgendermassen aus:

Aufruf:

Code: Alles auswählen

oColumn2:colorBlock := {|| SetMyColor()}
Funktion:

Code: Alles auswählen

FUNCTION SetMyColor()
   LOCAL aColors
   LOCAL cAlias
   LOCAL i

   aColors := {GRA_CLR_BLACK, GRA_CLR_WHITE}

   Select("test")

   cAlias := Alias()

   USE kategorie.dbf ALIAS kategorie NEW SHARED

   kategorie->(DbGoTop())

   IF  Len(AllTrim(test->kategorie)) <> 0
      FOR i := 1 TO kategorie->(Reccount())
         IF AllTrim(test->kategorie) == AllTrim(kategorie->NAME)
            aColors := {GRA_CLR_BLACK, kategorie->FARBE}
            EXIT
         ENDIF
         kategorie->(DbSkip())
      NEXT
   ENDIF

   kategorie->(DbCloseArea())

   Select(cAlias)
RETURN aColors
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9361
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Beitrag von Tom »

Hallo, Jan.

Du öffnest für jede Zelle, die dargestellt wird, diese Datei, durchläufst sie bis zum Ende und schließt sie wieder. Kein Wunder, daß das im Netz langsam ist, es dürfte sogar lokal recht schnarchig sein. Alleine beim Aufbau eines XbpBrowse() wird jede darzustellende Zelle dreimal angefaßt, und bei jeder anschließenden Navigation auch wieder. Du solltest diese Kategorien in ein Array einlesen und mit AFind() arbeiten. Wenn das nicht geht, weil Du die Möglichkeit einschließen möchtest, daß die Kategorien geändert werden können, während das Browse angezeigt wird, setze eine Relation auf die einmalig (vor Aufbau des Browses) zu öffnende Datei.
Herzlich,
Tom
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9361
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Beitrag von Tom »

Kleine Ergänzung:

Eine Iteration der Art:

Code: Alles auswählen

FOR i := 1 to RecCount()
bewirkt, daß RecCount() bei jedem Durchlauf der Schleife erhoben wird, also nach jedem Inkrement von i geprüft wird, wieviele Datensätze die Tabelle hat. Einfacher und schneller ist sowas:

Code: Alles auswählen

DO WHILE !Eof()
Aber das hat mit Deinem Kernproblem nichts zu tun. Setze spaßenshalber mal ein Stückchen Debug-Code in "MySetColor", z.B. die Anzeige eines Zählers oder so. Du wirst sehen, daß die Funktion zig Male aufgerufen wird, viel öfter, als Du angezeigte Zellen auf dem Bildschirm hast, und jedes Mal wird die Datei geöffnet, geparst und wieder geschlossen.
Herzlich,
Tom
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15696
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Hallo,

deine Funktion wird vom Browser für jede Zeile, die er neu zeichnen muß aufgerufen. Diese Funktion öffnet dann eine DBF auf dem Server, sucht die Felder / Sätze (habe ich jetzt nicht so genau gelesen) durch und gibt dann die Farbe zurück.

Eventuell machen das gleichzeitig 10 andere, während andere Kollegen die dbf durchsuchen, über den Server drucken ....

Was ich damit sagen will ist, dass man alle Arbeit aus den Schleifen rausnehmen muss, die dort nicht nötig ist. Deine Funktion muss die Farben in einem STATIC Array zwischenspeichern und das sollte schon vor dem Browseraufbau geschehen. Ich mache das bei allen lookup Tabellen. In DBF vorhalten (auch wegen der leichten Änderung) aber im Programm nur einmal öffnen und in Array merken.

Code: Alles auswählen

function MyColor(cWert)
     static aColor := NIL
     local x, uReturn := Standardvorgabewert ???
    if cWert=NIL .or. aColor = NIL
       use farben readonly shared alias MyColorFarben
       aColor := {} // Inhalt {cWert, {color,color} }...
                          // oder    {cWert, color } je nach Wunsch
       MyColorFarben->(dbeval(aadd(aColor, {field->VerglWert,field->Farbe})))
       close MyColorFarben
     endif
     if cWert<>NIL
        x := ascan(aColor,cWert)  // eventuell cWert mit codeblock ersetzen
        if x > 0
           uReturn := aColor[x,2] // farbe oder array mit farben ...
        endif
     endif
return uReturn
Einfach die Funktion nach deinen Bedürfnissen überarbeiten (habe ich jetzt nur so aus dem Kopf entworfen, daher Tip und Klammerfehler möglich) und einmal vor und dann im Browser nutzen. Nun sollten nur noch die Hauptdaten bremsen :wink:
Gruß
Hubert
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15696
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Hallo Tom,

ich tippe scheinbar zu langsam, als ich anfing war noch keine Antwort da :wink:
Gruß
Hubert
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9361
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Beitrag von Tom »

Hallo, Hubert.

Macht ja nix, außerdem hast Du gleich seine Funktion überarbeitet.

@Jan: Man muß sich insbesondere bei Objektmethoden darüber im klaren sein, daß ihre Nutzung durch das Objekt erfolgt. Auch, wenn es im Code so aussieht, als würde eine Methode einmalig aufgerufen werden, nämlich bei der Instantiierung der Spalte, erfolgt das quasi pausenlos. Der Codeblock wird zur Laufzeit evaluiert, und zwar jedes Mal, wenn die Zelle refresht wird, was gnadenlos oft geschieht. Du versiehst einen Slot mit einer eigenen Funktionalität, aber die Kontrolle über diesen Slot hat weiterhin das nutzende Objekt.
Herzlich,
Tom
JanR
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 129
Registriert: Di, 18. Okt 2005 14:44

Beitrag von JanR »

Hallo Hubert,
Hallo Tom,

Vielen Dank für eure Hilfe. Ich werde das jetzt über ein Array machen. Wenn man sich das so überlegt, ist mein Ansatz kein guter gewesen :).

Schönes Wochenende.


Jan
Antworten