Seite 1 von 1

[gelöst] Dialog: 100 Labels sehr schnell befüllen.

Verfasst: Mi, 11.07.2012 22:30
von balu
Hallo liebe Gemeinde,

auch wenns nicht danach aussieht, aber das ein oder andere zum Thema "Array" habe ich schon dazu gelernt. Mein ständiger Begleiter, die deutsche Übersetzung von Andrew, ist mir momentan leider keine gute Hilfe, oder ich übersehe da mal wieder etwas.

Folgende Situation.
Ich habe ein mehrdimensionales Array DimArray(3,99), also 4 Spalten mit je 100 Einträgen. Und mit diesem Array möchte ich jetzt in einem Dialog 100 Labels (Beschriftungsfelder) abwechselnd befüllen.

Genauer gesagt.
In dem Array stehen in den Spalten 1 und 3 Farbwerte, und in 2 und 4 die jeweiligen Namen zu den Farbwerten. Und durch eine simples For-Next werden beim ersten Aufruf des Dialogs alle 100 Labels anhand der Farbwerte aus der Spalte 1 farblich gefüllt.

Nun kann man im Dialog mittels eines OptionButton die Labels mit anderen Farbwerten, die aus der dritten Spalte, farblich befüllen. Auch hier kommt wieder die simple For-Next zum Zuge. Und durch einen anderen OptionButton kann man wieder auf die erste Farbspalte umschalten, mit der gleichen For-Next.

Jedoch kann man zusehen wie die Labels langsam der Reihe nach befüllt werden. Zumindest bei mir hier vergeht dabei mindestens 1 Sekunde. Und das nervt mich! Allein schon das zusehen ist nervig.

Nun suche ich eine Möglichkeit diesen Befüllungsprozess zu beschleunigen.

Wenn ich jetzt die Farbwerte der Reihe nach in ein Tabellenblatt eintragen möchte -{nur mal so als Beispiel}-, dann könnte ich ja mit setDataArray arbeiten. Das kann ich aber bei Labels nicht anwenden, da es das dort nicht gibt.
Oder wenn ich 100 Datenpunkte in EINE Listbox eintragen möchte, wäre das für mich auch kein Problem. Nur mit der jetzigen Situiation bin ich irgendwie überfordert.


Könnt ihr mir irgendwie helfen? Und seis auch nur ein Hinweis zur passenden Stelle in Andrews Original PDF, die habe ich auch, aber da komme ich mit meinem englisch nicht so gut voran :(.

Freue mich schon auf eure Antworten.

Eine Beispieldatei ist im Anhang.



Gruß
balu

Re: Dialog: 100 Labels sehr schnell befüllen.

Verfasst: Mi, 11.07.2012 23:26
von Karolus
Hallo Balu

Die Farben werden hier relativ zügig neu aufgebaut (~0,2sec )
Kein Grund zum Klagen.

______________
Ich hatte hier zuerst einen lustigen Nebeneffekt - eine Funktion 'f' aus DMath ( eine Writerextension zum Math-modul ) meldet sich nach Aufruf deines Dialogs mit "..die Argumente wären nicht optimal"
Ich würde behaupten der Funktionsname 'f' ist nicht so optimal...

Karo

Re: Dialog: 100 Labels sehr schnell befüllen.

Verfasst: Do, 12.07.2012 10:03
von balu
Hallo Karo,
Ich würde behaupten der Funktionsname 'f' ist nicht so optimal...
Genau! Was fällt DMath eigentlich ein, den Buchstaben f für sich zu beanspruchen :D

Spaß beiseite.
Nun, einen Funktionsnamen f habe ich ja nicht, sondern nur einen Zähler f für die Schleife. Das spielt aber keine große Rolle, da ich deine Beobachtung mit XRay nachbauen und nachvollziehen kann.

Wenn ich also in der Befüllungsschleife folgende Zeile

Code: Alles auswählen

oFarben.getControl("Label" & f+1).Text = FaLi(iFaPal+1, f)
auf das hier ändere

Code: Alles auswählen

oFarben.getControl("Label" & lf+1).Text = FaLi(iFaPal+1, lf)
bekomme ich in dieser Zeile folgende Fehlermeldung:
BASIC-Laufzeitfehler.
Objektvariable nicht belegt.
Und ich kann das jetzt auch nachvollziehen, da ich ja als Ereigniss beim starten von OOo die XrayTool Library lade. Und dort ist ja LF schon wie folgt deklariert.

Code: Alles auswählen

Public LF As String
Und jetzt ist die Fehlermeldung eigentlich auch schon fast logisch, na ja fast logisch.
In den XrayTools ist LF als String deklariert, aber in der Schleife soll LF einen Numerischen Wert aufnehmen, was ja nicht gut gehen kann.
Ich frag mich nur warum nicht als Fehlermeldung: Datentypen unverträglich (oder so ähnlich) ausgegeben wird?

Das Problem liesse sich jetzt in meiner Beispieldatei natürlich auf 2 Wege beseitigen.
1.
In der Schleife einen anderen, oder den alten Zähler nehmen.

2.
Den Zähler vorher öffentlich neu dekalrieren.

Code: Alles auswählen

Public lf as Integer
Ist schon interessant wo man eventuell überall nach der Ursache für eine Fehlermeldung suchen muss. Das werd ich mir Merken!

Danke das Du mich auf diese Situation aufmerksam gemacht hast.

Die Farben werden hier relativ zügig neu aufgebaut (~0,2sec )
Also doch!
Mit 9 Jahren gehört mein Abakus mehr als nur ins Altenheim. :lol:

Kein Grund zum Klagen.
Da lässt sich drüber diskutieren. Wolln ma abba net.

Dennoch würde es mich interessieren wie man den Ablauf verbessern, optimieren kann. Obwohl es ja nur eine 4 Zeilige Schleife ist, heißt es ja nicht das der Prozess Geschwindigkeitsmäßig Optimal ist. Da gibt es ja genug Beispiele beim Massenhaften befüllen von Zellen in Calc, die das vorführen. Der dafür zuständige Code ist wohl länger als 4 Zeilen, aber die Geschwindigkeitssteigerung ist einfach enorm.

Ich werd wohl selber mir noch so ein paar Gedanken deswegen machen, aber über weitere Antworten würd ich mich dennoch freuen. Egal von wem.

Danke Karo.



Gruß
balu

Re: Dialog: 100 Labels sehr schnell befüllen.

Verfasst: Do, 12.07.2012 11:05
von Karolus
Hallo
Bzgl. 'f' hast du mich missverstanden, - es ist durchaus ok eine Indexvariable an 'f' zu binden, es ist aber keine gute Idee von den Machern von DMath eine Funktion dieses Namens global verfügbar zu machen nach jeder ersten Benutzung von DMath.

Karo

Re: Dialog: 100 Labels sehr schnell befüllen.

Verfasst: Do, 12.07.2012 11:35
von balu
Hallo Karo,
es ist aber keine gute Idee von den Machern von DMath eine Funktion dieses Namens global verfügbar zu machen nach jeder ersten Benutzung von DMath.
Das Zauberwort heißt wohl "Global". Und dadurch ergibt sich jetzt natürlich noch ein ganz anderes Bild.

Aber lassen wir das, bitte schön. Das wird mir sonst zu sehr OT. Uninteressant war es aber dennoch nicht.



Gruß
balu

Re: Dialog: 100 Labels sehr schnell befüllen.

Verfasst: Fr, 13.07.2012 16:15
von balu
Hallo,

da ich ja eh nicht mit meinem Wunsch weiterkomme, habe ich mich jetzt dazu entschieden in der Schleife diese Zeile auszukommentieren.

Code: Alles auswählen

oFarben.getControl("Label" & f+1).Model.HelpText = " " & FaLi(iFNa, f)
Eine genaue Zeitangabe kann ich wohl nicht machen, aber so grob übern Daumen gepeilt braucht der Befüllungsprozess dann nur noch ungefähr die halbe Zeit. Klingt ja auch logisch, da ja nur noch eine Aktion, anstatt zwei durchgeführt werden müssen. Ich kann wohl hier auf meiner Möhre dem Prozess noch immer zusehen, aber es dauert halt nicht mehr ganz so lange. Und damit kann ich jetzt doch leben.

Das ist jetzt mal wieder so ein Thema gewesen, in dem es um Machbar und Nutzen geht. Technisch Machbar ist es, aber der Nutzen hinkt hinterher. Zumal der Farbname in einem extra Label ja eh schon angezeigt wird.



Gruß
balu

Re: Dialog: 100 Labels sehr schnell befüllen.

Verfasst: Fr, 13.07.2012 21:18
von DPunch
Servus

Ein einfacher und sehr effektiver Tip für Dich:
Nimm vor jeder Schleife, generell wenn Du weisst, dass Du das gleiche Objekt mehrfach verwenden wirst, immer den kürzesten Weg.

Code: Alles auswählen

for f = 0 to 99
	oFarben.getControl("Label" & f+1).Model.backgroundcolor = FaLi(iFaPal, f)
	oFarben.getControl("Label" & f+1).Model.HelpText = " " & FaLi(iFNa, f)
next f
In jedem Schleifendurchlauf wird also der Name des gewünschten Labels zusammengesetzt, dann wird das Label aus allen Controls herausgesucht, dann wird dort das Model gesucht, dann wird der HelpText/die Hintergrundfarbe gesetzt. Und das (in der ursprünglichen Form) 2 Mal.
Das ist aber unnötig.
Den Weg kannst Du abkürzen:

Code: Alles auswählen

for f = 0 to 99
	oCtl = oFarben.getControl("Label" & f+1)
	oCtl.Model.backgroundcolor = FaLi(iFaPal, f)
	oCtl.Model.HelpText = " " & FaLi(iFNa, f)
next f
Das dürfte grob über den Daumen gepeilt schonmal 10% Geschwindigkeitszuwachs bringen, weil das zweimalige Heraussuchen des Labels entfällt.
Wie man sieht, gibt es aber noch einen kleineren gemeinsamen Nenner: .Model
Warum also nicht:

Code: Alles auswählen

for f = 0 to 99
	oCtlModel = oFarben.getControl("Label" & f+1).Model
	oCtlModel.backgroundcolor = FaLi(iFaPal, f)
	oCtlModel.HelpText = " " & FaLi(iFNa, f)
next f
Macht nochmal grob geschätzt 10% gut.

Das nur zum Verständnis, wenn Du in Zukunft an Performance-Tuning gehst - gerade OOo Basic ist da sehr, sehr empfänglich für derlei Tuning-Massnahmen.
Das "holen" von gewünschten Objekten (Zellen, Tabellensheets, Steuerelemente etcetc) wird immer wieder so ausgeführt, als würdest Du das gewünschte Ziel das erste Mal ansprechen. Daher ist auch das

Code: Alles auswählen

With meinObejct (...)
-Konstrukt im Gegensatz z.B. zu VBA, wo es in der Regel einen enormen Performance-Zuwachs bedeutet, in OOo überflüssig, zumindest was die Performance angeht.

Langer Reder, kurzer Sinn:
Was Dir weiterhilft, ist der sogenannte Space-time-tradeoff, also der Tausch von (Speicher-)Platz gegen Zeit. Du opferst Arbeitsspeicher für Ausführzeit. Heutzutage, in dem Umfang, den normale Makros annehmen, ohne jegliches Bedenken machbar.
Du weisst von vornherein, welche Label Du ansprechen willst. Also speicher Dir die Labels respektive deren Models von vornherein im Arbeitsspeicher.

Code: Alles auswählen

Public aLabels(99)
Dieses Array befüllst Du direkt nach dem Start mit den Referenzierungen auf Deine Objekte:

Code: Alles auswählen

(...)
	oFarben = CreateUnoDialog(DialogLibraries.Standard.DlgFarbe)
	for f = 0 to 99
		aLabels(f) = oFarben.getControl("Label" & f+1).Model
	next f
(...)
und sparst Dir dann in "Fuellen" sehr, sehr viel Arbeit:

Code: Alles auswählen

sub Fuellen
	for f = 0 to 99
		aLabels(f).backgroundcolor = FaLi(iFaPal, f)
		aLabels(f).HelpText = " " & FaLi(iFNa, f)
	next f
end sub
Ich kenne wenige, wenn nicht gar keine Programmiersprache, bei denen diese Methode so viel Geschwindigkeitszuwachs bringt wie bei OOo Basic.
Solange die Lesbarkeit nicht darunter leidet, empfehle ich Dir, immer diesen Weg zu gehen, sobald Du der Meinung bist, dass etwas doch ein wenig schneller laufen sollte - allerdings auch nur dann. Ansonsten nimm einfach immer den kürzesten Weg, sprich:
wenn Du ein Objekt über "eine Ecke" (oDoc.Sheets.getByName("X")) oder sogar mehrere Ecken mehr als einmal ansprechen willst/musst, nimm eine lokale Variable, in der Du Dir die Zwischenschritte ersparst (oSheets = oDoc.Sheets : oSheets.getByName("X")). Je öfter Du das Objekt ansprichst und je tiefer es liegt (ala: oFarben.getControl("Label" & f+1).Model), desto wertvoller wird diese Vorgehensweise.

Re: Dialog: 100 Labels sehr schnell befüllen.

Verfasst: Fr, 13.07.2012 22:12
von balu
Hallo DPunch,

WOW! Klasse Antwort! Das bringt mich nicht nur bei diesem Thema weiter, sondern auch allgemein. Danke :D.

Also speicher Dir die Labels respektive deren Models von vornherein im Arbeitsspeicher.

Code: Alles auswählen

Public aLabels(99)
Da wir schon mal beim Thema "Public" sind, zwei Fragen dazu.
Wie hebe ich die Speicherung wieder auf?
Kann man das überhaupt während der Laufzeit machen?

Ich Frage deshalb, weil mich das schon seit längerem interessiert, und ich es auch noch nicht bis jetzt ausprobiert hatte da ich das noch nicht brauchte. In der deutschen Übersetzung von Andrew habe ich bis jetzt noch nichts diesbezüglich gefunden, oder aber ich hab Tomaten auf den Augen. Kannst Du mir ruhig sagen wenn dem so ist.

Wenn es nicht geht, außer durch Datei beenden, wäre das auch nicht schlimm da die Datei, in der dieses Makro integriert wird, eh nicht im Dauereinsatz ist. Aber generell würd es mich schon interessieren.


Für heute habe ich Feierabend. Aber morgen werd ich deine Tipps und Ratschläge praktisch anwenden. Da freu ich mich jetzt schon drauf. Ich werd natürlich berichten was dabei rausgekommen ist.



Gruß
balu

Re: Dialog: 100 Labels sehr schnell befüllen.

Verfasst: Fr, 13.07.2012 22:31
von Karolus
Hallo
Da wir schon mal beim Thema "Public" sind, zwei Fragen dazu.
Wie hebe ich die Speicherung wieder auf?
Kann man das überhaupt während der Laufzeit machen?

Code: Alles auswählen

redim aLabels()
Wozu brauchst du das jetzt

Karo

Re: Dialog: 100 Labels sehr schnell befüllen.

Verfasst: Fr, 13.07.2012 23:11
von balu
Hallo Karo,

warum sagst Du mir nicht das ich Tomaten auf den Augen hatte? :lol:
Wozu brauchst du das jetzt
Gar nicht. Ich hatte da etwas durcheinander geworfen. :oops:



Gruß
balu

Re: Dialog: 100 Labels sehr schnell befüllen.

Verfasst: Sa, 14.07.2012 11:26
von balu
Hallo DPunch,

also das mit dem umschreiben der Objekte in der Schleife bringt wohl Zeitlich schon minimal etwas, ist wohl noch nicht der Hammer, aber immerhin. Der Zeitfaktor ist aber nicht immer so wichtig, da durch die Änderung für mich eine bessere lesbarkeit entstehen kann. Aber nicht nur die Lesbarkeit ist da von Vorteil, nein, auch das Editieren geht dadurch leichter und schneller. Und das kann ich an anderen Stellen auch nutzbringend anwenden.

Du weisst von vornherein, welche Label Du ansprechen willst. Also speicher Dir die Labels respektive deren Models von vornherein im Arbeitsspeicher.
Das war das was ich mir so ungefähr vorgestellt hatte. Ich erstelle ein Array mit den Labels, und packe anschließend das Farbarray in dieses rein. Aber ich kam beim umsetzen meiner Ideen einfach nicht voran, mir fehlte einfach der Zündende Gedanke. Und jetzt wo ich deine Lösung sehe, fällts mir wie Schuppen von den Augen. Und ja, ich verstehe auch was da geschieht. Ich kann es regelrecht vor meinem geistigen Auge sehen wie der Ablauf ist.


So, und nun zu dem Zeitergebnis.
-> Ausgangssituation war ja so bei ca. 1 Sekunde.
-> Und jetzt ist es so: Licht ein, Licht aus.
Und das heißt mit anderen Worten: Wenn es bei mir hier schon Verzögerungsfrei läuft, dann kann es auf schnelleren Systemen erst recht keine Verzögerung geben.

So ist es Perfekt!
Ich Danke dir vielmals :D.



Gruß
balu

Re: [gelöst] Dialog: 100 Labels sehr schnell befüllen.

Verfasst: Sa, 14.07.2012 11:39
von turtle47
Hallo Balu,

auf dieser Seite findest Du einen Code, der direkt auf die Farbpalette von OO.o und Konsorten zugreift.

Vielleicht kanst Du da etwas abschauen.

Viel Erfolg.

Jürgen

Re: [gelöst] Dialog: 100 Labels sehr schnell befüllen.

Verfasst: Sa, 14.07.2012 12:03
von balu
Hallo Jürgen,

wat ne Menge Code! Bis das ich da durchgestiegen bin, vergeht ja ne Ewigkeit.
Vielleicht kanst Du da etwas abschauen.
Werd ich so Häppchenweise mal versuchen. Wäre natürlich klasse, wenn ich es selber hinbekomme die mColorMap in meinem Code zu integrieren. Doch dafür nehme ich mir später mal die Zeit, jetzt muss ich anderes erledigen.

Dennoch Danke ich dir :D.



Gruß
balu

Re: Dialog: 100 Labels sehr schnell befüllen.

Verfasst: Di, 17.07.2012 21:23
von DPunch
Servus
balu hat geschrieben:Da wir schon mal beim Thema "Public" sind, zwei Fragen dazu.
Wie hebe ich die Speicherung wieder auf?
Kann man das überhaupt während der Laufzeit machen?
Wenn diese Frage noch aktuell sein sollte:
Public-Variablen behalten ihre Gültigkeit, solange ein Makro in der entsprechenden Library läuft - in Deinem Fall also genau bis zu dem Zeitpunkt, wo der Dialog geschlossen wird.
Danach wird der von der Variable belegte Speicherplatz freigegeben und ist je nach Qualität und Effizienz der Garbage Collection alsbald wieder frei verfügbar.
Darum musst Du Dich also nicht selber kümmern.
Bei globalen Variablen verhält es sich da etwas anders, aber darüber solltest Du Dir wirklich keine Gedanken machen - das Makro, das mit seinem Arbeitsspeicherbedarf allein aufgrund der im Code verwendeten Variablen heutige (oder meinetwegen 5 Jahre alte) Rechner in die Knie zwingt, oder auch nur in Bedrängnis bringt, muss glaube ich erst aufwändig geschrieben werden.
balu hat geschrieben:Der Zeitfaktor ist aber nicht immer so wichtig, da durch die Änderung für mich eine bessere lesbarkeit entstehen kann. Aber nicht nur die Lesbarkeit ist da von Vorteil, nein, auch das Editieren geht dadurch leichter und schneller. Und das kann ich an anderen Stellen auch nutzbringend anwenden.
Das ist ein Effekt, der selbstverständlich ebenso eintreten kann, und es tatsächlich oft auch tut. Genau genommen verwende ich persönlich derartige Konstruke eher für die zentrale Wartbarkeit als für die Performance, da ich schnelle Wartbarkeit des Codes fast in allen Fällen für wichtiger halte als die reine Performance.
Es neigen allerdings viele dazu, alles so (laufzeittechnisch) schnell wie möglich programmieren zu wollen, sobald sie erstmal auf einen Fall "wie diesen" gestossen sind und fangen an den unerwartesten Ecken an, den Code optimieren zu wollen - für 50 Millisekunden Geschwindigkeitszuwachs - und dabei geht dann für an der Programmierung Unbeteiligte die Lesbarkeit zu oft flöten. Daher einfach mal präventiv mein Hinweis.

Re: [gelöst] Dialog: 100 Labels sehr schnell befüllen.

Verfasst: Sa, 11.08.2012 12:47
von balu
Hallo DPunch,

sorry, aber irgendwie war mir deine Antwort nicht mitgeteilt worden. Ich bedanke mich dennoch nachträglich dafür :)


Gruß
balu