Erarbeitung eines "POS-Kassenbuchs"

Diskussionen zu Projekten

Moderator: Moderatoren

Forumsregeln
Dieses Unterforum versteht sich als Plattform zur Diskussion/Bearbeitung komplexerer Anfragen bzw. konkret verabredeter Projekte. Das können Dinge sein wie eine komplexere Calc-Datei oder auch die gemeinsame Programmierung eines größeren Makros, wichtig ist immer die Absicht ein Thema über längere Zeit (z.B. 3 Monate) fortlaufend zu besprechen.
Benutzeravatar
balu
********
Beiträge: 3810
Registriert: Fr, 24.08.2007 00:28
Wohnort: Warstein

Re: Erarbeitung eines "POS-Kassenbuchs"

Beitrag von balu »

Hallo Julia,
Wie - weder Kopf- noch Bauchschmerzen?! Du brauchst dringend ein Laster! :P
Ich bin ein Laster :lol:

Aufgrund deines Hinweises vor einiger Zeit, besser die SVERWEISE im Makro berechnen zu lassen, fliegen jetzt alle Formeln aus dem Tabellenblatt.
SPIELVERDERBERIN! Nimmst mir einfach die Arbeit ab.;-)
Aber auf deine Lösung bin ich trotzdem mal sehr gespannt, da ich nicht weiß welche Technik Du da angewendet hast.

Ein anderer Hintergrund ist die Tatsache, dass die Berechnungsformeln in der Tabelle das System verlangsamen, zumal wir auf einem Raspberry arbeiten.
Da die Datei ja je nach Monat ca. 30 Blätter enthalten wird, fallen ein oder 2 Formeln nicht so ins Gewicht. Aber je mehr Formeln pro Blatt, und das mal 30, sieht die Sache schon ganz anders aus. Das spürt man selbst auf einem ausgewachsenen PC mit 4*3GHz, so wie meiner.
Ich weiß wovon ich da Rede, nämlich aus Erfahrung mit meinem damaligem Projekt.

Ich fürchte, du wirst das Kassenbuch nicht wiedererkennen.
Egal! Hauptsache ich bekomme auch noch was zu tun :-D



Gruß
balu
Sei öfter mal ein Faultier, sag öfter mal "Ach was!" Dann kriegst du keinen Herzinfarkt, und hast ne menge Spass.

wehr rächtschraipfähler findet khan si behalden :D
Benutzeravatar
Julia NuN
**
Beiträge: 38
Registriert: Mo, 07.11.2016 14:57

Re: Erarbeitung eines "POS-Kassenbuchs"

Beitrag von Julia NuN »

Hallo balu,
Aufgrund deines Hinweises vor einiger Zeit, besser die SVERWEISE im Makro berechnen zu lassen, fliegen jetzt alle Formeln aus dem Tabellenblatt.
SPIELVERDERBERIN! Nimmst mir einfach die Arbeit ab.;-)
Aber auf deine Lösung bin ich trotzdem mal sehr gespannt, da ich nicht weiß welche Technik Du da angewendet hast
Technik?! Öhm...
Keine Bange - ich glaub', du wirst dich über einen Mangel an Arbeit nicht beklagen können. :D

Gute Nacht!
Wilhelm Busch: "Ein jeder Wunsch, wenn er erfüllt, kriegt augenblicklich Junge."
... ich glaub, der wär heutzutage Programmierer und nicht Schriftsteller.
Benutzeravatar
Julia NuN
**
Beiträge: 38
Registriert: Mo, 07.11.2016 14:57

Re: Erarbeitung eines "POS-Kassenbuchs"

Beitrag von Julia NuN »

Hey balu,

hier mein Upload.
Folgendes ist neu hinzugekommen:

1. Mitarbeiter-Arbeitsstunden
Wir notieren die Mitarbeiter-Arbeitsstunden jetzt auch im POS-Kassenbuch (Blatt „Stunden“).
Daher wurden noch die Namen, der Stundenlohn und eine Liste mit den aktuellen Datumsangaben für den Monat hinterlegt, siehe Punkt 2.

Um die Stunden-Eingaben nach Datum zu sortieren, wurde ein Sortierbutton eingefügt. Das Makro habe ich mit dem Makrorekorder erstellt (neues Modul „Datum_sortieren“).

2. „Preise“ umbenannt in „Stamm“
Die Daten für Punkt 1 (Namen, Stundenlohn, Datum s.o.) befinden sich jetzt alle auch im ehemaligen Blatt „Preise“, das umbenannt wurde zu „Stamm“. Hinzugekommen sind auch die Daten einer Ansprechperson mit Telefonnummer für die MsgBox im Modul "Flaschenverkauf" und die veränderbaren Daten für das Modul „Kiste_Astra“.

Die Referenzierung zu dem Blatt heißt jetzt gemäß deines Vorschlags wie folgt:

Code: Alles auswählen

oBlattStamm = thisComponent.Sheets.GetByName("Stamm")
3. Kopfbereich Blatt „1“
Um sinnvollere Auswertungsdaten zu erhalten, wurde der Kopfbereich geändert.
Insbesondere werden jetzt die Mindereinnahmen einzeln aufgelistet. Mindereinnahmen sind fehlende Einnahmen durch Vergabe von Rabatten (kostenfreie Abgabe/Schwund = Rabatt 100%).

4. Mitarbeiter-Getränke Blatt „1“
Mitarbeiter müssen jetzt nach Eingabe eines Artikels mit Mitarbeiter-Rabatt (50%) ihren Namen auswählen. Dieses Drop-Down-Menü holt seine Daten aus „Stamm“ um immer aktuell zu bleiben.
Sinn der Sache ist, dass die Mitarbeiter sich jetzt ihre persönlichen Getränkekosten rechts im Blatt anzeigen lassen können.

Frage:
Ich habe versucht, so viel wie möglich in der Sub „Dlg_neuer_Artikel“ vorzudefinieren.
Und manchmal erklärt es sich mir nicht, wieso es dann nicht funktioniert.
Z.B. greife ich im Modul „Flaschenverkauf“ in der MsgBox unten auf Daten zu, deren Werte in der Sub „Dlg_neuer_Artikel“ definiert wurden. Das klappt.

Aber wenn ich Ähnliches im Modul „Kiste_Astra“ versuche, geht das nicht. Vielleicht, weil mit den Werten dort gerechnet werden soll?

Modul „Kiste_Astra“
Ich wollte eigentlich die zwei möglichen Preise (30€/35€) für den Verkauf einer Kiste Astra ebenfalls im Stammblatt hinterlegen.
Aber ich hab mir scheinbar durch die Anwendung von .SelectedItemPos selbst ein Bein gestellt. Das müsste man sonst wohl nochmal ganz anders machen.

Modul „Flaschenverkauf“:
Hier ist jetzt doch noch eine Formel drin – ich habe es nicht hinbekommen, die zu ersetzen. Das ist allerdings auch nicht notwendig, das wird nicht so oft benutzt.
Das ist übrigens ein Modul, durch das ich selbst noch nicht recht durchsteige. Ich schätze mal, da geht noch ganz gut was zu verbessern. ;)

Sonstiges:

Code: Alles auswählen

    iArtikelnummer_Art = oArtikelnummer_Artikel.Value()
' Die folgenden 2 Zeilen kannst Du löschen.'
'    sgAnzahl_Art = oAnzahl_Artikel.Value()'
'    sgRabatt_Art = oRabatt_Artikel.Value()'
    
    mySheet.getCellRangeByName("A" & iEnd_Row).Value = iID + 1
    mySheet.getCellRangeByName("B" & iEnd_Row).Formula = oFormulaText_Art
    mySheet.getCellRangeByName("D" & iEnd_Row).Value = iArtikelnummer_Art
    mySheet.getCellRangeByName("E" & iEnd_Row).Value = oAnzahl_Artikel.Value()' jetzt neu'
    mySheet.getCellRangeByName("F" & iEnd_Row).Formula = oFormulaEinnahme_Art
    mySheet.getCellRangeByName("G" & iEnd_Row).Formula = oFormulaEPRabatt_Art
    mySheet.getCellRangeByName("I" & iEnd_Row).Value = oRabatt_Artikel.Value()' jetzt neu'
    mySheet.getCellRangeByName("J" & iEnd_Row).Formula = oFormulaRabattArt_Art
    mySheet.getCellRangeByName("K" & iEnd_Row).Formula = oFormulaMindEinnahme_Art
Ich habe das so gut es ging versucht umzusetzen. Weil ich jetzt aber wegen des Wegfalls der Formeln mit fast allen dieser Feldwerte rechnen musste, um wiederum die anderen Werte zu erhalten, musste ich dann doch wieder so neudefinieren. Hhm... :?
Kann man eigentlich, wenn man "sgRabatt_Art = oRabatt_Artikel.Value()" in Klammern setzt, auch damit rechnen? Fällt mir grad spontan ein - hab's nicht ausprobiert.

Und dann habe ich noch versucht, das hier umzuschreiben:

Code: Alles auswählen

	
	oAktuellesBlatt = thiscomponent.getcurrentcontroller.activesheet
	oCellCursor = oAktuellesBlatt.createCursor()
	oCellCursor.GotoEndOfUsedArea(True)
Mit meiner Kreation

Code: Alles auswählen

	oAktuellesBlatt = thiscomponent.getcurrentcontroller.activesheet.createCursor().GotoEndOfUsedArea(True)
war ich aber nicht erfolgreich.

Liebe Grüße Julia
Dateianhänge
POS_Kassenbuch_Forum_5.ods
(61.43 KiB) 489-mal heruntergeladen
Wilhelm Busch: "Ein jeder Wunsch, wenn er erfüllt, kriegt augenblicklich Junge."
... ich glaub, der wär heutzutage Programmierer und nicht Schriftsteller.
Benutzeravatar
Julia NuN
**
Beiträge: 38
Registriert: Mo, 07.11.2016 14:57

Re: Erarbeitung eines "POS-Kassenbuchs"

Beitrag von Julia NuN »

Achja (seufz), sobald ich was hochlade, finde ich auch schon wieder Fehler…:

Der String sZelleFonChef ist nicht richtig deklariert, daher wird in der obigen Datei noch nicht die Telefonnumer in der MsgBox im Modul „Flaschenverkauf“ angezeigt.

Wenn das SO ist, kann ich gleich noch was schreiben, was ich vergessen hatte.
In selbiger MsgBox gibt es ja auch den errechneten Rabatt. Diesen wollte ich mit FORMAT auf 2 Nachkommastellen formatieren:

Code: Alles auswählen

sgRabatt_Fl = Format(100 - (EPRabatt_Fl * 100 / sgListenpreis_Fl), "##,##0.00")
Das hat auch geklappt. Dann hat er (ist "es" eigentlich eine "sie" oder ein "er"?) aber in der Tabelle einen auf eine ganze Zahl gerundeten Wert eingetragen --> aus "56,5217399597168" wurde "56". Das hab ich nicht verstanden und wieder herausgenommen, weil ich mir nicht sicher war, ob das so vom Wirt gewünst ist.
Ansonsten ist das mit der FORMAT-Funktion aber klasse. Ich nehm an, wir nehmen das auch wieder mit rein.
nimm mal das hier.

Code: Alles auswählen

sFormulaText_Art = "=SVERWEIS(D" & iEnd_Row & ";Preisliste;2;0)"
[...]
mySheet.getCellRangeByName("B" & iEnd_Row).FormulaLocal = SFormulaText_Art
Das war natürlich ein Super-Tipp! Nachdem ich allerdings die Formeln bis auf eine rausgeworfen hatte, habe ich das bei der dann auch vergessen zu ändern. :oops: :mrgreen:

LG Julia
Wilhelm Busch: "Ein jeder Wunsch, wenn er erfüllt, kriegt augenblicklich Junge."
... ich glaub, der wär heutzutage Programmierer und nicht Schriftsteller.
Benutzeravatar
balu
********
Beiträge: 3810
Registriert: Fr, 24.08.2007 00:28
Wohnort: Warstein

Re: Erarbeitung eines "POS-Kassenbuchs"

Beitrag von balu »

Hallo Julia,

ohne die Datei zu sehen, ich muss gleich raus wegen Winterdienst (Straße räumen und streuen... brrr-nasskalt-brrrr :? ), muss ich sagen das Du wohl recht fleißig warst. Und nicht nur der Fleiß ist anerkennenswert, sondern auch die Überlegungen die Du angestellt und umgesetzt hast. Respekt. :-)

Das natürlich noch einige Stolpersteine zu meistern sind, bleibt nicht aus. Das werden wir aber noch alles irgendwie hinbekommen.

ist "es" eigentlich eine "sie" oder ein "er"?
:lol:
Echt klasse das mal ein "Anfänger" sich darüber Gedanken macht.
Ist aber auch nicht ganz so einfach.
- das Tabellenkalkulationsprogramm (Excel, Calc...)
- das Makro
- der Code (vom Makro)
- der Rechner (PC)
- die Formel
Und je nach Problematik kann man dann sagen
- der Code macht nicht was er soll
- die Formel hat ne macke
- ich schmeiß den Rechensklave ausm Fenster
Also pauschalisieren fällt mir auch schwer, deshalb nehme ich das was zur Problematik passt, denn es ist kein Biologisches Lebewesen. ;-).

Ich meld mich wieder wenn ich Zeit hatte und habe.



Gruß
balu
Sei öfter mal ein Faultier, sag öfter mal "Ach was!" Dann kriegst du keinen Herzinfarkt, und hast ne menge Spass.

wehr rächtschraipfähler findet khan si behalden :D
Benutzeravatar
balu
********
Beiträge: 3810
Registriert: Fr, 24.08.2007 00:28
Wohnort: Warstein

Re: Erarbeitung eines "POS-Kassenbuchs"

Beitrag von balu »

So, jetzt hatte ich mir etwas Zeit gönnen können.
Dann hat er [...] aber in der Tabelle einen auf eine ganze Zahl gerundeten Wert eingetragen --> aus "56,5217399597168" wurde "56". Das hab ich nicht verstanden und wieder herausgenommen
Tja, da gibt es einige Regeln zu beachten, wenn man per Makro ausgerechnete Werte in ein Tabellenblatt eintragen will.

1.
Im Makro schon eine Art "Vor-Formatierung" vornehmen

2.
Eintragen

3.
Formatieren

Hört sich einfacher an als es in wirklichkeit ist.
Punkt 1 braucht man nicht immer, aber durchaus öfters.
Handelt es sich um eine Ganzzahl, also ohne Nachkommastellen, dann braucht man da eigentlich nicht viel machen. Mal ein theoretische Grundlagenbeispiel.

Code: Alles auswählen

oBlattStamm.getCellRangeByName("B99").value = sgEP_Korr.value
Und fertig.
Komme gleich nochmal darauf zurück.

Punkt 2 habe ich ja schon grad eben mit dem Grundbeispiel gezeigt.

Punkt 3 kann durchaus seeehr kompliztierter werden.
Will man eine Ganzzahl eintragen, so braucht man eigentlich nix mehr weiter zu machen. Man muss lediglich drauf achten das man sich bei der Zuordnung nicht vertut, also nicht die Zelle als String vorbereiten und dann einen echten Wert eintragen, denn das ergibt dann nämlich einen String. Gemeint ist folgendes Verbot.

Code: Alles auswählen

oBlattStamm.getCellRangeByName("B99").string = sgEP_Korr.value
Anders sieht es aber aus, wenn man Beispielsweise die aktuelle Uhrzeit eintragen will. Denn dann muss vom Makro nach dem eintragen in die Zelle gleich noch eine weitere Aktion durchgeführt werden. Und diese Aktion heißt:

Die Tabellenzelle mit dem richtigen Zahlenformat formatieren.

Und das ist vom Prinzip her nix anderes, als wenn Du von Hand die Zelle z.B. auf Format Uhrzeit: "HH:MM" formatierst. Im Makro ist das aber etwas komplizierter, da man das Format anders einstellt. Hier ein Beispiel.

Code: Alles auswählen

Sub Main
oBlattNo1 = ThisComponent.Sheets.GetByName("Tabelle1")
oBlattNo1.getCellRangeByName("A1:D1").clearContents(255)
oBlattNo1.getCellRangeByName("A1").FormulaLocal =  NOW

oBlattNo1.getCellRangeByName("B1").FormulaLocal =  TimeValue(NOW)

oBlattNo1.getCellRangeByName("C1").FormulaLocal =  NOW
oBlattNo1.getCellRangeByName("C1").Numberformat = 40

oBlattNo1.getCellRangeByName("D1").FormulaLocal =  TimeValue(NOW)
oBlattNo1.getCellRangeByName("D1").Numberformat = 40
End Sub
Nimm eine neue und leere Datei, und starte dies Makro.

Und so ganz nebenbei kommt jetzt auch der Punkt 1 zum tragen. Denn es findet eine "Vor-Formatierung" statt, und zwar durch TimeValue. Und die Zellformatierung wird durch Numberformat = 40 vorgenommen.

Nimm dir ruhig einen Moment Zeit dafür, und schau nicht nur was in der Zelle angezeigt wird, sondern auch oben in der Eingabezeile.



Zelle A1 ist fast identisch zur Eingabezeile.
Zelle B1 ist identisch zur Eingabezeile.
Zelle C1 & D1 sind nicht mehr identisch zur Eingabezeile.

Mit den Zellen C1 & D1 würde ich jetzt so nicht weiterrechnen wollen, wenn man sich nur auf das Aussehen der Zelle beschränkt. Denn es wird etwas anderes angezeigt, als das was wirklich in der Zelle steht. Und das kann sehr schnell zu bösen Problemen führen. Also muss eine andere Lösung daher. Und die kommt jetzt.

Code: Alles auswählen

Sub Mimi
CompatibilityMode(True)
oBlattNo1 = ThisComponent.Sheets.GetByName("Tabelle1")
oBlattNo1.getCellRangeByName("C4:D4").clearContents(255)
oBlattNo1.getCellRangeByName("C4").FormulaLocal =  FormatDateTime(TimeValue(NOW), 4)

oBlattNo1.getCellRangeByName("D4").FormulaLocal =  FormatDateTime(TimeValue(NOW), 4)
oBlattNo1.getCellRangeByName("D4").Numberformat = 40
CompatibilityMode(FALSE)
End Sub
Führe dieses Makro ruhig in der gleichen Datei aus. Ich habe dafür extra andere Zellen genommen damit Du dir die Unterschiede zum ersten Code in Ruhe anschauen und vergleichen kannst.

Es sind jetzt wohl "nur" 2 Dinge dazu gekommen, aber die haben es in sich.
Als erstes wird ein "Kompatibilitäts Modus" aktiviert -{CompatibilityMode}- - (und später wieder deaktiviert), und zweitens können wir dadurch, und zwar nur dadurch, auf eine zusätzliche Funktion drauf zugreifen. Und diese Funktion lautet: FormatDateTime.

Jetzt schlägt die "Vor-Formatierung" aber auch so richtig zu. Denn durch die 4 in FormatDateTime wird gesagt, stelle auf "Stunden und Minuten(hh:mm, Stunden im 24-Stunden-Format)" ein. Nachzulesen in "Andrew Pitonyak", das Buch findest Du hier: http://www.uni-due.de/~abi070/ooo.html
Das ist wirklich eine sehr wichtige Lektüre.

Es gibt aber auch noch eine sehr gute und emfehlenswerte Seite, und das ist Dannenhöfer. Bei dem ist auch dieses Thema vom grundsätzlichen eigentlich schon ganz gut beschrieben. Schau dir mal folgende Links an.
7.1.22 Wie kann man das Zahlenformat auf Standardformate einstellen?
7.1.26 Wie kann man das Zellenformat einstellen?

Besonders der Punkt (7.1.26) ist dir dabei behiflich ein "Zellenformat-Kode" auszulesen, da dort ein kleines aber effektives Hilfsmakro vorhanden ist. Dazu musst Du erstmal eine Zelle selber von Hand Formatieren, also über ->rechtsklick ->Zellen formatieren ..., na den Weg kennst Du ja wohl ;-). Anschließend führst Du das Hilfsmakro von dort aus, und schon bekommst Du die Formatnummer die Du dann weiter verwenden kannst.

Klar hätte ich sofort auf die beiden genannten (Pitonyak, Dannenhöfer) verweisen können, aber so hast Du schon mal etwas womit Du das von mir gesagte ausprobieren kannst, und außerdem gleichzeitig einen sehr schweren Broken von den Füßen. Ich habe jetzt hier wohl nur von der Uhrzeit gesprochen, aber beim Thema Datum verhält es sich nicht wesentlich anders, bis auf folgende kleinigkeiten.

Code: Alles auswählen

FormatDateTime(DateValue(NOW), 2)
Und Numberformat kann entfallen, wenn das Datum beispielsweise so aussehen soll 06.01.17. Damit müsstest Du jetzt eigentlich gut gerüstet sein um Zellen selber per Makro zu formatieren.


Anderes Thema.

Ich glaube das ich jetzt verstanden habe wie Du die SVERWEIS im Makro ersetzt hast. Einfach dadurch das Du durch die Zeilen suchst, und bei einem Treffer dann dementsprechend reagierst. Das ganze mit einer einfachen For...Next.

Ist wohl soweit in Ordnung. Jedoch in deiner jetzigen Testdatei mit mal grad eben 11 Testzeilen spürst Du noch nicht was passiert wenn wirklich 500 Zeilen durchsucht werden müssen. Denn dann macht die Uhr *tick-tack-tick-tack-tick-tack-tick-tack-*

Ich hatte mich schon mal so zwischendurch mit diesem Thema selber befasst, da ich in dieser Art noch keine richtige Erfahrung gesammelt habe, und ich habe da auch eine Lösung für mich gefunden. Ich sage nur eins: Array. Und das ist eine ganz andere Hausnummer. Aber heute gehe ich nicht weiter darauf ein, das kommt später.


Ich sehe Du hast hier im Forum etwas gefunden, was sehr nützlich ist.

Code: Alles auswählen

	aSourceDataArray() = oZellenMitarbeiter.getDataArray() 
	Dim aSource(UBound(aSourceDataArray())) as String  
	For j = LBound(aSource()) To UBound(aSource())
   	aDataArrayRow() = aSourceDataArray(j)
	aSource(j) = aDataArrayRow(0)
Find ich echt klasse wie Du doch so aktiv bist. :mrgreen:
Jedoch
Aber ich hab mir scheinbar durch die Anwendung von .SelectedItemPos selbst ein Bein gestellt.
wird das auch erst später besprochen.

Keine Bange - ich glaub', du wirst dich über einen Mangel an Arbeit nicht beklagen können. :D
Oh jeh! Wie recht Du hast. Da gibts noch so einiges an Arbeit ;-)

Aber, nach einem "Smal-Talk" und einem ausgewachsenen Beitrag von mir, mach ich hier jetzt schluß, und stelle gleich meinen teilweise vorbereiteten Beitrag hier rein. Das wäre dann der dritte in Folge. Dadurch habe ich dann wieder etwas Zeit mich deiner jetzigen unbehandelten Probleme zu befassen, während Du meine Beiträge Abarbeitest.
Och-Mennoooo! Ich brauch doch mal wieder einen kleinen Vorsprung :-)


Gruß
balu
Sei öfter mal ein Faultier, sag öfter mal "Ach was!" Dann kriegst du keinen Herzinfarkt, und hast ne menge Spass.

wehr rächtschraipfähler findet khan si behalden :D
Benutzeravatar
balu
********
Beiträge: 3810
Registriert: Fr, 24.08.2007 00:28
Wohnort: Warstein

Re: Erarbeitung eines "POS-Kassenbuchs"

Beitrag von balu »

So, und nun zum letzten Beitrag für heute.

Auch wenn es dir jetzt vielleicht ein wenig unsinnig, verwirrend oder blöde vorkommt, so verfolge ich doch durchaus ganz bestimmte Ziele mit dem was jetzt kommt.

Ein Ziel ist es, dir so nebenbei Step-by-Step einiges beizubringen was Du noch öfters anwenden kannst. Mir geht es hier dabei auch nicht darum das ich dir jetzt schon Fix und Fertig zeige wie die Dialoge und der dazugehörige Makro-Code komplett überarbeitet aussehen könnten, denn dann könnten wir das Projekt innerhalb weniger Tage abschließen, sondern vielmehr darum zu zeigen wie man aus dem schon vorhandenen etwas ausbauen und verändern kann. Und deshalb sage ich jetzt auch nichts zu den anderen Zielen die ich verfolge. ;-)


Wir nehmen uns jetzt etwas vor, was auf den ersten Blick als "nicht so wichtig" eingestuft werden kann, aber ein gewisser Grundstein für was anderes dient was noch kommen wird, und ferner als ein Lernziel dient.

Als erstes legst Du ein neues Basic Modul an, mit dem Namen:

Text_Mitteilungen

In diesem Modul benennst Du die

Code: Alles auswählen

Sub Main
In das hier um.

Code: Alles auswählen

Sub PoaFaw
Nicht wegen den Namen wundern, Erklärung folgt gleich noch.
Doch nun ein wechsel zum:

Modul: Flaschenverkauf

Du arbeitest ja generell mit der MsgBox, wenn die Datei auf etwas reagieren soll. Das kenne ich selber, und das habe ich früher auch mal so gemacht. Habe das aber mittlerweile aufgegeben und ein anderes System dafür genommen. Doch so weit wollen wir jetzt bei dir noch nicht gehen, aber dennoch uns der MsgBox annehmen.

In diesem besagten Modul hast Du mehrere MessageBoxen.
Fangen wir mit der 1. an, und zwar diese.

Code: Alles auswählen

' Prüfen, ob alle Felder ausgefüllt wurden	    
    If iArtikelnummer_Fl = 0 Or iAnzahl_Fl = 0 Or sgFuellmenge_Fl = 0 Or sgPreis_Fl = 0 Then
	antwort = MsgBox("Du hast nicht alle Felder ausgefüllt.",0," ;-)")
	If antwort = 1 Then exit sub
	Endif
Der Sub Name PoaFaw in dem vorhin angelegten neuen Modul beruht auf die Anfangsbuchstaben in deinem Kommentar, aber ohne Satzzeichen.

PoaFaw = Prüfen ob alle Felder ausgefüllt wurden

Er hat so gesehen momentan einen Wiedererkennungswert wegen Orientierungsmöglichkeit.

Benenne jetzt antwort in iPoaFaw_Antwort um.
Der geänderte Code-Ausschnitt müsste jetzt wie folgt aussehen.

Code: Alles auswählen

' Prüfen, ob alle Felder ausgefüllt wurden'
    If iArtikelnummer_Fl = 0 Or iAnzahl_Fl = 0 Or sgFuellmenge_Fl = 0 Or sgPreis_Fl = 0 Then
    iPoaFaw_Antwort = MsgBox("Du hast nicht alle Felder ausgefüllt.",0," ;-)")
    If iPoaFaw_Antwort = 1 Then exit sub
    Endif
Und aus diesem Ausschnitt kopierst Du folgende Zeile in die Zwischenablage.

Code: Alles auswählen

    iPoaFaw_Antwort = MsgBox("Du hast nicht alle Felder ausgefüllt.",0," ;-)")
 
Und diese Zeile fügst Du nun, - na wohin wohl? - ....... in das Modul Text_Mitteilungen in die

Code: Alles auswählen

Sub PoaFaw
ein.
Dadurch müsste jetzt die dortige Sub wie folgt aussehen.

Code: Alles auswählen

Sub PoaFaw
    iPoaFaw_Antwort = MsgBox("Du hast nicht alle Felder ausgefüllt.",0," ;-)")
end Sub
Okay, noch mal zurück in das Modul Flaschenverkauf.
Dort wird die eben kopierte Zeile wie folgt geändert.

Code: Alles auswählen

' Prüfen, ob alle Felder ausgefüllt wurden'
    If iArtikelnummer_Fl = 0 Or iAnzahl_Fl = 0 Or sgFuellmenge_Fl = 0 Or sgPreis_Fl = 0 Then
        PoaFaw
    If iPoaFaw_Antwort = 1 Then exit sub
    Endif
Wie Du jetzt siehst, hat sich die Anzahl der Zeilen nicht geändert, aber eine Zeile sieht jetzt doch ganz anders aus. Vorher stand da ein etwas längerer "Text", und jetzt nur noch ein "Wort".

Nun, dir ist sicherlich aufgefallen, das das einzelne "Wort" der Name der einen Sub entspricht. Und das soll auch so sein, und das ist auch richtig so.
Denn wenn der Sub-Name so alleine in einer Zeile steht, wird dadurch diese Sub automatisch vom Programm aufgerufen und ausgeführt.

Prinzipiell könntest du jetzt einwänden:

"Wegen einer einzigen Code-Zeile so einen Aufwand?"

Theoretisch hättest Du ja auch recht. Aber das ist ja jetzt nur eine MsgBox mit nur einer Zeile, während ja noch mehrere MsgBoxen mit mehreren Code-Zeilen folgen. Und außerdem ist das jetzt das erste Lernziel:

Wie ruft man auf einfache Art eine andere Sub auf?

Aber damit diese Änderungen und Ergänzungen auch funktionieren, muss noch eine Kleinigkeit gemacht werden. Und dazu gehts ab ins Modul Artikel.
Dort ergänzt Du jetzt die Variablen deklarationen, und zwar um folgendes.

Code: Alles auswählen

' Temporäres'
Dim iPoaFaw_Antwort as Integer
Jetzt speicherst du die geänderte Datei ausm Basic-Editor heraus, nicht aus Calc heraus. Schließt sie, und öffnest sie erneut. Und nur zur Sicherheit kontrollierst Du ob auch die Änderungen gespeichert wurden. Ich empfehle diese Vorgehensweise, weil dadurch sichergestellt werden kann das nicht irgendwelche Variablen sich noch im Arbeitsspeicher befinden, die das Makro durcheinander bringen können.

Danach startest Du den Dialog wie gehabt, gehst auf "Verkauf ganzer Flaschen" und dort klickst Du auf "Übernehmen", ohne irgendein Feld auszufüllen. Daraufhin müsste die dir wohl bekannte MsgBox mitsamt ihrem Text erscheinen.

Und das ist der Beweis das durch den Aufruf des Sub-Namen die dementsprechende Sub nicht nur aufgerufen, sondern auch ausgeführt wird. Es wird jetzt so gesehen wohl nur eine einzige ausgelagerte Zeile abgearbeitet, aber das ist der erste kleine Schritt in Richtung Umfangreichere Sub aufrufe, was sehr viel später noch kommen wird.

In den Dialogen rufst Du ja auch per "Knopfdruck" die eine oder andere Sub auf. Das ist hier im wesentlichen nix anderes, blos das der Auslöser für den Sub-Aufruf etwas anders ist, im Dialog per Knopf, hier per Code.


Und jetzt drückst Du den *großen-imaginären-geistigen-Pause-Button*, und gönnst dir erstmal eine solche.


Wenn Du dich wieder erholt hast, dann gehst Du daher und lagerst ALLE MsgBoxen wie eben gezeigt in das Modul Text_Mitteilungen aus. Achte aber darauf das jede MsgBox ihr eigene Sub bekommt. Und überprüfe auch ob jede MsgBox nach der Auslagerung noch genau so funktioniert wie von dir gedacht und geplant ist.

So! Das wars für heute.
Viel spaß beim "Abarbeiten" :lol:



Gruß
balu
Sei öfter mal ein Faultier, sag öfter mal "Ach was!" Dann kriegst du keinen Herzinfarkt, und hast ne menge Spass.

wehr rächtschraipfähler findet khan si behalden :D
Benutzeravatar
Julia NuN
**
Beiträge: 38
Registriert: Mo, 07.11.2016 14:57

Re: Erarbeitung eines "POS-Kassenbuchs"

Beitrag von Julia NuN »

Wow! Cool! :D
Daaankee!

Das mit dem Auslagern hat's mir besonders angetan.
Ich hab so'n Gefühl, dass man da noch viel mehr auslagern kann.
Aber ich werde mich beherrschen und auf deine Eingaben warten, sonst kommen wir hier noch völlig durcheinander.

Jetzt kann ich mir auch Zeit lassen, die Alpha-Version läuft ja schon. :)

Mit der Verschnaufpause hast du Recht - bei mir ist so einiges anderes liegen geblieben.
Da muss ich morgen auch ran, sonst fliegt mir das um die Ohren... :roll:

CU und Guts Nächte
Julia
Wilhelm Busch: "Ein jeder Wunsch, wenn er erfüllt, kriegt augenblicklich Junge."
... ich glaub, der wär heutzutage Programmierer und nicht Schriftsteller.
Benutzeravatar
balu
********
Beiträge: 3810
Registriert: Fr, 24.08.2007 00:28
Wohnort: Warstein

Re: Erarbeitung eines "POS-Kassenbuchs"

Beitrag von balu »

Hallo Julia,
Wow! Cool!
Daaankee!
Gern geschehen :D

Das mit dem Auslagern hat's mir besonders angetan.
Ich hab so'n Gefühl, dass man da noch viel mehr auslagern kann.
Och jo! Da gibt es noch das eine oder andere ;-)

Also denn! Es gibt viel zu tun. Packen wir es an.


Bitte gewöhne dir bei "For ... next" (Kurz: Schleife) folgendes an.

Code: Alles auswählen

For i = 1 to 10
    [tu irgendetwas]
next i
Denn Du schreibst das next bisher immer ohne den "Zähler". Und das kann unter Umständen durchaus mal zu Problemen führen, wenn mehrere Schleifen ineinander verschachtelt sind. Und beim durchlesen eines Codes kannst Du dann selber ins Stolpern geraten, wenn Du nicht wirklich nachvolziehen kannst welche Schleife abgearbeitet wurde und welche nicht.

Ferner empfehle ich dir auch aus Sicherheitsgründen dabei nicht immer den gleichen Zähler zu benutzen. Also nicht immer nur next i, sondern auch andere Buchstaben, Buchstabenkombinationen oder auch Wörter.

Code: Alles auswählen

For r2d2 = 0 to 5
    [tu irgendetwas]
next r2d2

Code: Alles auswählen

For KistenIndex = 0 to 5
    [tu irgendetwas]
next KistenIndex 
Das sind Erfahrungswerte die sich wirklich lohnen zu merken.


Thema: Fehleranalyse
Frage:
Ich habe versucht, so viel wie möglich in der Sub „Dlg_neuer_Artikel“ vorzudefinieren.
Und manchmal erklärt es sich mir nicht, wieso es dann nicht funktioniert.
Z.B. greife ich im Modul „Flaschenverkauf“ in der MsgBox unten auf Daten zu, deren Werte in der Sub „Dlg_neuer_Artikel“ definiert wurden. Das klappt.

Aber wenn ich Ähnliches im Modul „Kiste_Astra“ versuche, geht das nicht. Vielleicht, weil mit den Werten dort gerechnet werden soll?
Und so was auf nüchteren Magen :-)

Also ich musste auch erstmal nach sofort auffälligen Fehlern suchen, hatte aber auf den ersten Blick nix gefunden.

Dann bin ich daher gegangen und habe den von dir markierten Code-Abschnitt in die "Sub Dlg_neuer_Artikel" kopiert, und in der Problem Sub alles geREMt. Dann den dementsprechenden Dialog gestartet, Testwerte eingegeben und ausgewählt. Es erschien eine Fehlermeldung. Diese konnte ich aber nicht wirkklich nachvollziehen. Also eine Händische Fehlersuche durchgeführt.

Und bei der Fehlersuche ist mir aufgefallen, das Du eine kleinigkeit vergessen hast. Kann vorkommen, kenne das selber. Der Fehler ist nämlich, das Du wohl richtig definiert hast

Code: Alles auswählen

iNrAstra_Ki = oBlattStamm.getCellRangeByName("F27").value
ABER iNrAstra_Ki nicht DEKLARIERT hast. Also füge das zu deiner deklaration noch hinzu.

Code: Alles auswählen

Dim iNrAstra_Ki as Integer
Danach kannst Du den kommentierten Block aus der "Sub Kiste_Astra" komplett in die "Sub Dlg_neuer_Artikel" verschieben.

Das folgende baut nicht der Reihe nach auf dessen auf was Du gesagt hast, sondern es wird Thematisch vorgegangen da das eine auf das andere aufbaut. Arbeite jedes Thema der Reihe nach ab.

Thema. Verbesserung Teil 1
Modul „Kiste_Astra“
Ich wollte eigentlich die zwei möglichen Preise (30€/35€) für den Verkauf einer Kiste Astra ebenfalls im Stammblatt hinterlegen.
Das geht, und das machen wir jetzt auch.

Auch wenn es eine andere Methode gibt, so zeige ich dir eine relativ einfache Methode.
Fangen wir mit der deklaration an.

Code: Alles auswählen

Dim aKistenPreise(1) as Integer
Kommt dir bekannt vor, oder?
Okay, es gibt einen Unterschied. Durch die Klammer mit Inhalt signalisiert man das es sich um ein Array handelt.

"Array? Array? Array? War da nicht etwas?"

Wirst Du dich zu Recht fragen, und JA das hatte ich vor kurzem schon angesprochen. Und außerdem hast Du ja selber schon etwas mit Array eingebaut. Du erinnerst dich an das hier?
balu hat geschrieben: Ich sehe Du hast hier im Forum etwas gefunden, was sehr nützlich ist.

Code: Alles auswählen

   aSourceDataArray() = oZellenMitarbeiter.getDataArray()
   Dim aSource(UBound(aSourceDataArray())) as String 
   For j = LBound(aSource()) To UBound(aSource())
      aDataArrayRow() = aSourceDataArray(j)
   aSource(j) = aDataArrayRow(0)
Find ich echt klasse wie Du doch so aktiv bist.
Ja, dieser Code arbeitet auch mit Array. Ist ja auch gar nicht so schwer zu identifizieren, gelle!
Da dieser Code aber auf ein Tabellenblatt zugreift, und nur mit String arbeitet, können wir vorläufig nicht sehr viel damit anfangen. Also nehmen wir eine andere Methode, ist vom Prinzip eigentlich nicht anders.

Und so nebenbei gibts jetzt einen sehr kleinen Mini Crash-Kurs zum Thema ARRAY.

Das Array aKistenPreise (1) wurde ja jetzt so deklariert. Und die 1 in den Klammern sagt, es handelt sich um 2 Elemente die das Array aufnehmen soll.

"Und warum 2, und nicht 1?"

Ganz einfach, weil es sich automatisch dabei um eine Null-Basierte Zählung handelt. Und damit hast Du ja wohl schon öfters im Makro zu tun gehabt, mit der Null-Basierten Zählung. Also brauche ich wohl nix mehr dazu zu sagen. Es gibt wohl auch noch Ausnahmen davon, aber das passt jetzt nicht zum *Mini Crash-Kurs*, kommt vielleicht später.

Und jetzt muss noch das Array mit Leben befüllt werden.

Code: Alles auswählen

aKistenPreise(0) = 35
aKistenPreise(1) = 30
Im groben kannst Du das jetzt mit einer Spalte in einem Tabellenblatt vergleichen. Und die Zahlen in Klammern wären dann jetzt die Zeilennummern. Und auf ein Tabellenblatt angepasst hätten wir jetzt also folgende Situation.
A1 hat den Wert 35
A2 hat den Wert 30

Nun könnte man folgendes im Makro machen.

Code: Alles auswählen

Print aKistenPreise(1)
Das Ergebnis wäre 30. Tauscht man die 1 gegen die 0, würde beim erneuten ausführen die 35 ausgegeben.
Also vom Prinzip her nix anderes, als wenn man im Tabellenblatt in der Zelle H1 einfach =A2, oder =A1 eingeben würde. Ist doch für den Anfang gar nicht so extrem schwer, oder ;-)

Okay, jetzt muss aber damit die Listbox befüllt werden, und das machen wir hiermit.

Code: Alles auswählen

    For iKP = 0 To UBound(aKistenPreise())
        aKistenPreise(iKP ) = aKistenPreise(iKP )
    Next iKP
        Dlg_Astrakiste.Model.getByName("Preis").StringItemList = aKistenPreise()
Aber Achtung!
Es gibt einen sehr wichtigen Punkt den man berücksichtigen muss.

Du hast wohl korrekt die Listbox wie folgt deklariert,

Code: Alles auswählen

oListBox_Preis = Dlg_Astrakiste.GetControl("Preis")
jedoch das befüllen geschieht nicht über GetControl, sondern mit Model.getByName. Das darf auf gar keinen Fall durcheinander geworfen werden. Denn sonst erlebt man böse Überraschungen.


Das ist kurz, einfach und für den Anfang reicht das für die 2 einzutragenden Werte.
Und hier jetzt noch mal alles zusammen.

Code: Alles auswählen

Dim aKistenPreise(1) as Integer

' Ab hier in die Sub Dlg_neuer_Artikel eintragen'

aKistenPreise(0) = 30
aKistenPreise(1) = 35

    For iKP = 0 To UBound(aKistenPreise())
        aKistenPreise(iKP ) = aKistenPreise(iKP ) 
    Next iKP
        Dlg_Astrakiste.Model.getByName("Preis").StringItemList = aKistenPreise()
 

Thema: Verbesserung Teil 2:
Aber ich hab mir scheinbar durch die Anwendung von .SelectedItemPos selbst ein Bein gestellt. Das müsste man sonst wohl nochmal ganz anders machen.
Stimmt!
Du musst nicht für alles eine zwischenvariable heranziehen, besonders dann, wenn sie nur einmal gebraucht wird. Dadurch wirst Du noch den Überblick verlierern.
Hier ein Beispiel.

Code: Alles auswählen

	LBox_AstraPreis_Ki = oListBox_Preis.selecteditempos()
[...]
If  LBox_AstraPreis_Ki = 0 Then
	LBoxWert_AstraPreis_Ki = 35
Else
 LBoxWert_AstraPreis_Ki = 30
Endif
Das muss nicht wirklich sein.

Das kommende baut auf Verbesserung Teil 1 auf, und ohne dies würde es nicht richtig funktionieren

Mit selecteditempos wird nur die Position ermittelt, also beispielsweise die 2 für die 3. Zeile (Null-Basierte Zählung).

Jedoch mit selecteditem wird der gewählte Eintrag (Text) übernommen.

Und das ganze machen wir uns jetzt zu Nutze. Und zwar kurz und schmerzlos.

Code: Alles auswählen

    LBoxWert_AstraPreis_Ki = VAL(oListBox_Preis.selecteditem)
Da selecteditem einen Text zurückgibt, muss dieser "Text" in einen Wert umgewandelt werden. Und das geschieht mittels VAL.
Mehr brauchts nicht. Also nix mit irgendeiner Schleife drunherum. Anstatt 5, jetzt nur noch 1 Zeile.
Hier ein weiterer Link zu Dannenhöfer. 4.3.9 Welches sind die Besonderheiten von Listboxen?


Thema: Zur kentniss genommen:
Modul „Flaschenverkauf“:
[...]
Das ist übrigens ein Modul, durch das ich selbst noch nicht recht durchsteige. Ich schätze mal, da geht noch ganz gut was zu verbessern.
Wenn du all die MsgBoxen ausgelagert hast, wie ja schon von mir schon erklärt, dann lässt sich das doch schon bestimmt besser lesen. Ni war? ;)

Modul „Flaschenverkauf“:
Hier ist jetzt doch noch eine Formel drin – ich habe es nicht hinbekommen, die zu ersetzen. Das ist allerdings auch nicht notwendig, das wird nicht so oft benutzt.
Ach Du meinst z.B. das hier!

Code: Alles auswählen

"=IF(K" & iEnd_Row & "=0;"""";IF(K" & iEnd_Row & "=50;""Mitarbeiter"";IF(AND(K" & iEnd_Row & ">50;K" & iEnd_Row & "<100);""Sachentnahme"";IF(K" & iEnd_Row & "=100;""Kostenfreie Abgabe"";""Sonstige""))))"
Nun, da hätte ich wohl eine alternative, aber nicht mehr heute.


Thema: Das letzte für heute
Kann man eigentlich, wenn man "sgRabatt_Art = oRabatt_Artikel.Value()" in Klammern setzt, auch damit rechnen? Fällt mir grad spontan ein - hab's nicht ausprobiert.
Das solltest Du noch mal genauer erklären.

Und dann habe ich noch versucht, das hier umzuschreiben:

Code: Alles auswählen

   oAktuellesBlatt = thiscomponent.getcurrentcontroller.activesheet
   oCellCursor = oAktuellesBlatt.createCursor()
   oCellCursor.GotoEndOfUsedArea(True)
Mit meiner Kreation

Code: Alles auswählen

   oAktuellesBlatt = thiscomponent.getcurrentcontroller.activesheet.createCursor().GotoEndOfUsedArea(True)
war ich aber nicht erfolgreich.
Ganz Kurz: Nicht alles kann man als Einzeiler schreiben.


Und nun hoffe ich das die letzten Aktuellen "Weh-Wehchen" erstmal abgehakt sind. Wenn Du auch dieses erledigt hast, dann hänge die aktuellste Version - {inklusive der gestrigen Aktionen} - hier beim nächten mal an. Und dann schaun ma mal wie es weiter geht, falls Du dann nicht noch aktuellere Probleme hast.



Gruß
balu
Sei öfter mal ein Faultier, sag öfter mal "Ach was!" Dann kriegst du keinen Herzinfarkt, und hast ne menge Spass.

wehr rächtschraipfähler findet khan si behalden :D
Benutzeravatar
Julia NuN
**
Beiträge: 38
Registriert: Mo, 07.11.2016 14:57

Re: Erarbeitung eines "POS-Kassenbuchs"

Beitrag von Julia NuN »

Hallo balu,
Jetzt schlägt die "Vor-Formatierung" aber auch so richtig zu. Denn durch die 4 in FormatDateTime wird gesagt, stelle auf "Stunden und Minuten(hh:mm, Stunden im 24-Stunden-Format)" ein. Nachzulesen in "Andrew Pitonyak", das Buch findest Du hier: http://www.uni-due.de/~abi070/ooo.html
Das ist wirklich eine sehr wichtige Lektüre.
Oh, die kannte ich noch nicht. Und es ist sehr ausführlich und verständlich erklärt. Bislang habe ich immer bei Wollmux im Makro-Kochbuch geguckt. Da hatte ich manchmal aber zu große Wissenslücken, um es tatsächlich nachvollziehen zu können.
Dannenhöfer habe ich auch schon häufig frequentiert.

Aha!!!

Jetzt habe ich es so

Code: Alles auswählen

oAktuellesBlatt.getCellRangeByName("K" & iEnd_Row).Value = sgRabatt_Fl
oAktuellesBlatt.getCellRangeByName("K" & iEnd_Row).Numberformat = 2
und so

Code: Alles auswählen

antwort = MsgBox (… "Somit hast du einen Rabatt von " & Format(sgRabatt_Fl, "###.00") & " % vergeben."… 
gemacht.

Dann habe ich noch das hier von dir aufgegriffen

Code: Alles auswählen

oBlattNo1.getCellRangeByName("A1:D1").clearContents(255)
und meine Zeilen

Code: Alles auswählen

oCellRange.clearContents(com.sun.star.sheet.CellFlags.VALUE)
oCellRange.clearContents(com.sun.star.sheet.CellFlags.FORMULA)
oCellRange.clearContents(com.sun.star.sheet.CellFlags.STRING)
so umgeschrieben:

Code: Alles auswählen

oCellRange.clearContents(21) ' (21) = (1+4+16)
Ein Ziel ist es, dir so nebenbei Step-by-Step einiges beizubringen was Du noch öfters anwenden kannst.
Das machst du erstklassig!!!

Ich hab daher auch ein bisschen länger gebraucht, weil ich halt nicht nur einfach was rauskopieren möchte, was ich so gerade noch im Ansatz verstehe. Ich teste auch immer brav deine Beispiel-Codes und guck alle Links nach. Dein Einsatz wird seeeeehr geschätzt! ;)
"Und warum 2, und nicht 1?"

Ganz einfach, weil es sich automatisch dabei um eine Null-Basierte Zählung handelt. Und damit hast Du ja wohl schon öfters im Makro zu tun gehabt, mit der Null-Basierten Zählung. Also brauche ich wohl nix mehr dazu zu sagen…
Jupp!

Code: Alles auswählen

Dim aKistenPreise(1) as Integer
… Da hätt ich jetzt mal ne Frage, die sich mir auch schon bei meinem anderen Array gestellt hat:
Wenn ich ein Array deklariere, dann müsste das eigentlich immer Integer sein, oder?

Ich hab hier

Code: Alles auswählen

aSourceDataArray() = oZellenMitarbeiter.getDataArray()
Dim aSource(UBound(aSourceDataArray())) as String 
For j = LBound(aSource()) To UBound(aSource())
aDataArrayRow() = aSourceDataArray(j)
aSource(j) = aDataArrayRow(0)
nämlich gar keine Deklaration vorgenommen, weil mir

Code: Alles auswählen

Dim aSourceDataArray as Array
doch etwas spanisch vorkam.
Vor allem wegen der Zeile

Code: Alles auswählen

Dim aSource(UBound(aSourceDataArray())) as String 
Und hierfür bräuchte ich noch eine Tüte Logik:

Code: Alles auswählen

For iKP = 0 To UBound(aKistenPreise())
aKistenPreise(iKP) = aKistenPreise(iKP) 
Next iKP
Dlg_Astrakiste.Model.getByName("Preis").StringItemList = aKistenPreise()
iKP ist ja dann „0“ und „1“, denke ich mal, weil wir ja am Anfang aKistenPreise()
wie folgt deklariert haben:

Code: Alles auswählen

Dim aKistenPreise(1) as Integer
Die Zeile

Code: Alles auswählen

aKistenPreise(iKP) = aKistenPreise(iKP)
löst bei mir so etwas aus, wie ein Wort, das einem auf der Zunge liegt, aber es fällt einem trotzdem nicht ein...
Es wäre super, wenn du mir da noch einmal auf die Sprünge helfen könntest. :P

Im Zusammenhang mit den sich selbst befüllenden Listboxen hätte ich noch den Wunsch, dass es einen vorausgewählten Wert/Text gibt. Geht das?
Weil jetzt ist die Listbox ja immer erstmal ohne Inhalt, wenn man den Dialog aufruft.

Die Erneuerung der Listbox für die Mitarbeiterauswahl bei Rabattwert = 50% habe ich jetzt auch in der Sub Dlg_Neuer_Artikel untergebracht.
Bei dem Versuch, hier Teile zu ersetzen bzw. umzuschreiben, habe ich mir einen Knoten ins Gehirn gedacht, daher habe es erstmal so gelassen, wie es war. Ich bin heute im logischen Denken auch nicht so auf der Höhe, hab ich gemerkt.
Kann man eigentlich, wenn man "sgRabatt_Art = oRabatt_Artikel.Value()" in Klammern setzt, auch damit rechnen? Fällt mir grad spontan ein - hab's nicht ausprobiert.

Das solltest Du noch mal genauer erklären.
Ich habs in der Sub Neuer_Artikel gemacht und es funktioniert:

Code: Alles auswählen

MindEinnahme_Art = (oEP_PreisEingabe.Value())*sgAnzahl_Art - Einnahme_Art
oAktuellesBlatt.getCellRangeByName("M" & iEnd_Row).Value = MindEinnahme_Art
Also ich musste auch erstmal nach sofort auffälligen Fehlern suchen, hatte aber auf den ersten Blick nix gefunden. ...
Ohje, da hab ich dir aber viel Arbeit gemacht!
Nächstes Mal wende ich deine Fehlersuche an.

So, damit ich endlich mal wieder etwas hochladen kann, mache ich hier jetzt Schluss, obwohl ich noch viel mehr schreiben könnte. Aber das kann auch warten.

LG Julia
Dateianhänge
POS_Kassenbuch_Forum_6.ods
(65.92 KiB) 569-mal heruntergeladen
Wilhelm Busch: "Ein jeder Wunsch, wenn er erfüllt, kriegt augenblicklich Junge."
... ich glaub, der wär heutzutage Programmierer und nicht Schriftsteller.
Benutzeravatar
balu
********
Beiträge: 3810
Registriert: Fr, 24.08.2007 00:28
Wohnort: Warstein

Re: Erarbeitung eines "POS-Kassenbuchs"

Beitrag von balu »

Hallo Julia,
Oh, die kannte ich noch nicht.
Das du Andrew noch nicht kanntest, dachte ich mir schon fast. Und deshalb der Link.

Und es ist sehr ausführlich und verständlich erklärt.
Ausführlich, ja.
Aber bei verständlich leben wir beide wohl in zwei verschiedenen Welten :lol:.
Das bezieht sich aber mehr auf die Beispielcodes. Sie sind mir stellenweise doch zu abstrakt. Aber dennoch besserr als gar nichts. Das wollen wir jetzt aber hier nicht weiter ausdiskutieren.

Bislang habe ich immer bei Wollmux im Makro-Kochbuch geguckt.
Wollmux ist namentlich nicht grad unbekannt. Aber so weit ich micht recht entsinne, ist es aber auch eine etwas schwerere Kost. Und dennoch, Respekt das Du dich damit befasst hast, liest man hier seeeeehr selten.

Ich bedanke mich für deine Lobende Worte, und auch dafür das Du dich intensiv mit meinen Beiträgen auseinander setzt. Das erfreut mich doch sehr. *schöööön*

Aber zurück an die Arbeit.
so umgeschrieben:

Code: Alles auswählen

oCellRange.clearContents(21) ' (21) = (1+4+16)
Na Prima! Sehr gut aufgepasst.


… Da hätt ich jetzt mal ne Frage, die sich mir auch schon bei meinem anderen Array gestellt hat:
Wenn ich ein Array deklariere, dann müsste das eigentlich immer Integer sein, oder?
Tja, das Thema Array ist sehr umfangreich. Aber so viel sei schon mal gesagt. NEIN! Es muss nicht immer als Integer deklariert werden. Es gibt da verschiedene möglichkeiten es zu deklarieren, als Integer, String oder aber auch als Variant. Und je nach dem was da rein kommen kann/soll muss es dementsprechend deklariert werden.

Bedenke, das Dim aKistenPreise(1) nur angibt wieviele Eintäge aufgenommen werden können. Das sagt aber nichts über den Typ der Einträge aus, wie z.B. Integer. Man muss das in diesem Falle getrennt betrachten.


Mein schon vorbereiteter Beitrag befasst sich auch wider mit dem Thema Array, aber es ist wohl etwas Umfangreicher dafür aber hoffentlich leichter nachzuvollziehen. Dafür mache ich dann hier im Anschluß einen weiteren seperaten Beitrag auf.

Ich hab hier

Code: Alles auswählen

aSourceDataArray() = oZellenMitarbeiter.getDataArray()
Dim aSource(UBound(aSourceDataArray())) as String 
For j = LBound(aSource()) To UBound(aSource())
aDataArrayRow() = aSourceDataArray(j)
aSource(j) = aDataArrayRow(0)
nämlich gar keine Deklaration vorgenommen, weil mir

Code: Alles auswählen

Dim aSourceDataArray as Array
doch etwas spanisch vorkam.
Man muss nicht alles deklarieren, auch wenn es nicht verkehrt wäre. Theoretisch könnte man das ganze auch so schreiben,

Code: Alles auswählen

Dim aSource(UBound(oZellenMitarbeiter.getDataArray())) as String 
For j = LBound(aSource()) To UBound(aSource())
aDataArrayRow() = oZellenMitarbeiter.getDataArray(j)
aSource(j) = aDataArrayRow(0)
aber das dann zu lesen fällt dann wohl schon einem etwas schwerer, weil die Übersicht verloren gegangen ist.

Was Du vielleicht noch nicht weisst, ist die Tatsache das getDataArray per se schon ein Array ist. Eigentlich ist DataArray auch ein Array, blos mit den Vornamen get holt man sich das Array und mit set schreibt man das Array.
Vor allem wegen der Zeile

Code: Alles auswählen

Dim aSource(UBound(aSourceDataArray())) as String 
Korrekt.
Und das ist jetzt auch ein gutes Beispiel dafür, das man nicht immer zum Anfang eines Moduls oder einer Sub etwas deklarieren muss. Denn bei einem Array weiss man wohl schon oft im Vorfeld was für Daten da rein kommen, z.B. String, aber man weiss nicht immer wie Groß das Array sein wird. Es ist also ungewiss ob das Array 2 oder 99 "Datensätze" umfasst.

Und wenn man sich mit getDataArray ein Array holt, und in diesem Falle das umbenennt in aSourceDataArray, dann weiss das Makro das das Array eine bestimmte Größe (Anzahl an Einträgen) hat, die man mittels UBound auslesen kann.

Und hierfür bräuchte ich noch eine Tüte Logik:

Code: Alles auswählen

For iKP = 0 To UBound(aKistenPreise())
aKistenPreise(iKP) = aKistenPreise(iKP) 
Next iKP
Dlg_Astrakiste.Model.getByName("Preis").StringItemList = aKistenPreise()
iKP ist ja dann „0“ und „1“, denke ich mal, weil wir ja am Anfang aKistenPreise()
wie folgt deklariert haben:

Code: Alles auswählen

Dim aKistenPreise(1) as Integer
Die Zeile

Code: Alles auswählen

aKistenPreise(iKP) = aKistenPreise(iKP)
löst bei mir so etwas aus, wie ein Wort, das einem auf der Zunge liegt, aber es fällt einem trotzdem nicht ein...
Es wäre super, wenn du mir da noch einmal auf die Sprünge helfen könntest. :P
Ja, ich verstehe deine Verwirrung. Und da habe ich mir auch mal erlaubt Bockmist zu machen. Ich hab es da echt mal etwas übertieben. Hatte es leider nicht auf eine andere Methode hin überprüft. Kurz und gut, die Schleife, also das hier

Code: Alles auswählen

For iKP = 0 To UBound(aKistenPreise())
aKistenPreise(iKP) = aKistenPreise(iKP) 
Next iKP
kannst Du getrost löschen. Habe es eben in einer Testdatei ausprobiert, und es funktioniert ohne diese Codezeilen. Habe schlicht zu kompliziert gedacht.

Im Zusammenhang mit den sich selbst befüllenden Listboxen hätte ich noch den Wunsch, dass es einen vorausgewählten Wert/Text gibt. Geht das?
Weil jetzt ist die Listbox ja immer erstmal ohne Inhalt, wenn man den Dialog aufruft.
Ja, eine so genannte Vorauswahl gibt es.
Im Modul *Kiste_Astra*, in der Sub Dlg_KastenAstra hast Du ja dort das hier stehen.

Code: Alles auswählen

Sub Dlg_KastenAstra ' Dialog zur Artikeleingabe aufrufen
	Dlg_Astrakiste.title = "Verkauf ganzer Kästen Astra"
	Dlg_Astrakiste.execute
End Sub
Und das änderst Du auf das hier.

Code: Alles auswählen

Sub Dlg_KastenAstra ' Dialog zur Artikeleingabe aufrufen
	Dlg_Astrakiste.title = "Verkauf ganzer Kästen Astra"
	oListBox_Preis.SelectItem(aKistenPreise(1), True)
	Dlg_Astrakiste.execute
End Sub
Hinzugekommen ist lediglich: oListBox_Preis.SelectItem(aKistenPreise(1), True)
Es ist dir überlassen ob Du die 1 übernimmst, oder ob Du die 0 nimmst.


Also ich musste auch erstmal nach sofort auffälligen Fehlern suchen, hatte aber auf den ersten Blick nix gefunden. ...
Ohje, da hab ich dir aber viel Arbeit gemacht!
Ach halb so wild, und auch nicht weiter tragisch. Da ich ja im groben mit der Datei schon gut vertraut bin, ist eine Fehlersuche nicht ganz so tragisch.

Nächstes Mal wende ich deine Fehlersuche an.
Tja, manchmal muss man sich schon für eine Fehlersuche eine gewisse Strategie zurecht legen.
Ich hatte eben auch ein kleines nicht zu verstehendes Problemchen beim testen mit der "oListBox_Preis.SelectItem". Der erste Versuch klappte wunderbar, allerdings im Modul *Artikel*. Dann dachte ich mir das dies nicht der Ideale Ort ist, also habe ich die gezeigte Codezeile in das nun richtige Modul und in die passende Sub eingetragen. Anschließend in der anderen Sub die Codezeile geREMt.

Dialog aufgerufen, und in der Listbox war kein Eintrag vorausgewählt. Komisch, hatte doch vorhin noch funktioniert. Also ab an die Fehlersuche. Aber mir war das ein Rätsel, da doch alles Ordnungsgemäß Deklariert und Defeniert ist.

Und dann musste ich auch noch feststellen, das überhaupt kein Eintrag in der Listbox vorhanden war, sie war schlicht leer. Ja jetzt schaute ich wie ein kaputtes Auto, blos nicht so schnell.

Also noch mal alles genau durchsuchen. Und dann sah ich den Fehler.
Ich blödie hatte die Falsche Zeile zuvor geREMt. War um eine Zeile zu hoch gerutscht.
Also das richtig gestellt, und schon funktionierte es wie ich gedacht hatte.

Ja ja!
Was nützt einem die besste Strategie zur Fehlersuche, wenn man sich selber ein Bein gestellt hat vor lauter Routine? *lach-lach-lach*


Okay, sie sind enttarnt und entdeckt worden.

Code: Alles auswählen

For c3po
for r2d2
Find ich voll gut und echt Luschdich :-D.

Und ich habe auch gesehen, das Du doch schon das ein oder andere im Makro umgeschrieben hast. Und das finde ich echt klasse.

Mein vorbereitetes Thema war eigentlich nur für einen ganz bestimmten Punkt ausgelegt, aber bei genauerer Betrachtung ist dir das auch an anderer Stelle nützlich, wenn Du dann das System verstanden hast. Wie schon gesagt geht es da auch wieder um Array. Und ich werde dann auch erklären wo und wie Du dann das "neue System" noch einsetzen kannst. Jedoch heute nicht mehr, das mache ich morgen am Sonntag.



Gruß
balu
Sei öfter mal ein Faultier, sag öfter mal "Ach was!" Dann kriegst du keinen Herzinfarkt, und hast ne menge Spass.

wehr rächtschraipfähler findet khan si behalden :D
Benutzeravatar
balu
********
Beiträge: 3810
Registriert: Fr, 24.08.2007 00:28
Wohnort: Warstein

Re: Erarbeitung eines "POS-Kassenbuchs"

Beitrag von balu »

Hallo Julia,

Eins vorweg.
Ich zeige hier jetzt keine alternative für die letztens genannte Formel, so wie ich es angesprochen hatte, sondern sie wird jetzt komplett ersetzt und direkt im Makro ausgeführt.

Auch wenn es sich "nur" um eine einzige Formel handelt, die zudem auch nicht immer im Tabellenblatt eingetragen wird, so ist sie doch dafür Ideal geeignet um eine bestimmte Technik zu zeigen. Und damit meine ich *eine IF...THEN in eine Schleife zu packen*. Du wirst nacher noch sehen und verstehen was ich damit meine. Und das ist etwas was man durchaus immer wieder mal irgendwo gebrauchen kann.

Also denn, los gehts!


Thema: Ersatz für eine Formel

Um die Formel zu ersetzen können, muss einiges im Makro ergänzt werden. Es kommen so einige Codezeilen hinzu. Aber da die Arbeit im Arbeitsspeicher erledigt wird, und das auch nur wenn die dementsprechende Sub abgearbeitet wird, ist kein Geschwindigkeitseinbruch zu erwarten. Und außerdem wird dadurch die Ladezeit der Datei verringert, da beim öffnen keine Neuberechnung der Zellinhalte vorgenommen werden muss. Und das entlastet ja wohl den kleinen Arduino bei seiner Arbeit ;-)

Um das Ziel zu erreichen arbeite ich jetzt wieder mit Array.

Diese Formel

Code: Alles auswählen

=WENN(K11=0;"";WENN(K11=50;"Mitarbeiter";WENN(UND(K11>50;K11<100);"Sachentnahme";WENN(K11=100;"Kostenfreie Abgabe";"Sonstige"))))
soll jetzt nicht mehr im Tabellenblatt erscheinen, aber dennoch soll im Makro deren Funktion nachgebildet werden, so das in der dementsprechenden Zelle der richtige Text ausgegeben wird wie z.B. Sachentnahme.

Auf den ersten Blick, so dachte ich zumindest für mich, stört der folgende Vergleich.

Code: Alles auswählen

UND(K11>50;K11<100)
Denn wenn sich alle Wahrheitsüberprüfungen der WENN() auf z.B. (=) beziehen würden, wäre ein abzufragendes Array recht schnell aufgebaut. Aber dem ist ja nicht so, und folglich muss ein kleiner Trick herhalten.

Doch bevor es zum Trick geht, schauen wir uns noch mal kurz die Funktionsweise einer WENN(PRÜFUNG;DANN;SONST) Funktion im Tabellenblatt und einer IF ... THEN ... ELSE... END IF Anweisung an.
Sie machen beide das gleiche. Es findet eine Wahrheitsüberprüfung statt, und je nachdem wie die Überprüfung ausgefallen ist, geht es dann dementsprechend weiter.

Die Überprüfung ergibt WAHR:
Bei der Funktion gehts mit DANN weiter.
Bei der Makro Anweisung geht es mit THEN weiter.

Beide kann man sehr stark ineinander verschachteln, bei der Funktion ist ja die obige gezeigte Formel (die ja jetzt auch ersetzt werden soll) der Beweis dafür. Und auch die Makro Anweisung liese sich sehr stark verschachteln. Jedoch kann sich das unter Umständen zu einem wahrlichem *Makro-Code Monster* entwickeln. Und manchmal bleibt einem so ein Monster nicht erspart. Aber hier kann man sich mit der richtigen Überlegung einiges an Arbeit ersparen, vorausgesetzt man hat eine gewisse Erfahrung. ;-)

Die WENN-Formel hat in diesem Falle einen doch großen Vorteil, der uns sehr entgegen kommt. Da sie nur auf fest vorgegebene Werte hin ein Vergleich anstellt, lässt sich das jetzt recht leicht direkt im Makro ausführen. Anders würds aussehen, wenn verschiedene zwischenberechnungen mit variablem Ergebnis durchgeführt würden. Doch dem ist ja nicht so.


Aber zerpflücken wir erstmal die Formel in die wichtigsten Bestandteile.

Code: Alles auswählen

WENN(K11=0;"";
WENN(K11=50;"Mitarbeiter";
WENN(UND(K11>50;K11<100);"Sachentnahme";
WENN(K11=100;"Kostenfreie Abgabe";
Es fällt auf, das ich etwas ausgelassen habe, und zwar das hier.

Code: Alles auswählen

"Sonstige"))))
Das hat auch seinen Grund. Denn das sind alles Überprüfungen und deren Reaktionen darauf, wenn WAHR zurückgegeben wird. Das ausgelassene jedoch kommt erst dann zum tragen, wenn FALSCH zurückgegeben wird.

Jetzt kommen wir zu dem eben angesprochenen störenden Vergleich, und zu meinem Trick.
Wie wir ja wissen, kann eine IF ... THEN z.B wie folgt aufgebaut sein.

Code: Alles auswählen

IF a= xx OR  (a> xx AND a< xx) THEN
Das heißt, es können verschiedene und/oder mehrere Vergleichsoperanten angewendet werden.
Diese Vergleichsform wollen wir auch tatsächlich so anwenden. Denn schließlich spiegelt sie das wieder, was in der WENN-Formel passiert. Dort wird ja auch auf (=) hin überprüft, aber auch einmal auf UND. Da Du ja diese Technik ja selber schon angewendet hast, brauch ich jetzt nicht mehr viel was dazu sagen.

Jetzt kommen wir zum Punkt *Array*.
Ich hatte letztens schon mal diesen Punkt kurz erklärt, und vorgeführt. Und diesmal brauchen wir 3 solcher einfachen Arrays.


Bevor es weiter geht, solltest Du ein neues Modul anlegen. Denn in dieses Modul kommt zu testzwecken alles rein was gleich noch folgt. Das hat den Vorteil das Du dadrin selber ein wenig experimentieren kannst, ohne jedesmal den Dialog auszuführen. Und wenn Du dich so weit davon überzeugt hast, das alles korrekt funktioniert, kopierst Du dann alles in das richtige Modul.


Als erstes müssen diese Arrays Deklariert werden. Doch diesmal machen wir das nicht öffentlich, also so wie bisher, sondern Lokal. Und das bedeutet, das in dem neu angelegten Modul in der *Sub Main* Deklariert wird.

Code: Alles auswählen

Sub Main
Dim aUnterGrenze(3) as Integer, aOberGrenze(3) as Integer
Dim aRabattText(3) as String
Jetzt werden die Arrays definiert und mit Leben befüllt.

Code: Alles auswählen

aUnterGrenze(0) = 0 : aOberGrenze(0) = 0 : aRabattText(0) = " - "
aUnterGrenze(1) = 50 : aOberGrenze(1) = 50 : aRabattText(1) = "Mitarbeiter"
aUnterGrenze(2) = 50 : aOberGrenze(2) = 100 : aRabattText(2) = "Sachentnahme"
aUnterGrenze(3) = 100 : aOberGrenze(3) = 100 : aRabattText(3) = "Kostenfreie Abgabe"
Das kopierst Du genau so in die Sub rein, und zwar direkt unter der Deklaration.
Achte aber unbedingt darauf das mindestens 1 Leerzeichen VOR und HINTER dem Doppelpunkt (:) steht. Denn wenn das nicht der Fall ist, gibts garantiert Probleme.

Du siehst jetzt so betrachtet eigentlich 4 Zeilen. Aber in wirklichkeit sind das jedoch 12 Zeilen. Der Grund für diese Art der Zeilenkomprimierung ist der Doppelpunkt (:). Denn durch dem wird dem Makro in diesem speziellen Falle gesagt, das das folgende eine weitere Zeile ist. So kann man leichter verstehen was wo zugeordnet ist. Das jetzt aber der RabattText "Sonstige" fehlt, hat wiederum seinen Grund, das wirst Du aber nachher noch verstehen warum das so ist.

Durch diese spezielle Anordnung der einzelnen Arrays kann man sich nun auch leichter merken, und vor allem auch nachvollziehen, das ein Array starke ähnlichkeit mit einem Tabellenblatt hat. Im Tabellenblatt kann man einzelne durchgehende Spalten mit einem Titel versehen, wie z.B. Untergrenze. Das ist jetzt im Array auch so, blos hier habe ich ein Array verständlicherweise als aUntergrenze benannt. Also 3 einzel Arrays mit 3 unterschiedlichen Titeln. Aber alle haben, und das ist extrem wichtig zu beachten, die gleiche Anzahl an Zeilen.


Jetzt sind so gesehen alle grundlegenden Bedingungen erfüllt, um eine Abfrage und Auswertung zu starten, die die Formel ersetzen soll. Also ran an den Feind :-)

Die folgende Auswertung ist nicht vollständig ausgefüllt, da Du jetzt nicht abgelenkt werden sollst. Und ferner dient das jetzt nur der Erklärung, also nicht in die Sub eingeben.

Code: Alles auswählen

iTmp = 0
    For iFE = LBound(aUnterGrenze()) to UBound(aUnterGrenze())
        If sgRabatt_Fl= aOberGrenze(iFE) OR (sgRabatt_Fl> aUnterGrenze(iFE) AND sgRabatt_Fl< aOberGrenze(iFE))

        End If
    Next iFE
         
    If iTmp = 0 then
        sZellRabatt = "Sonstige"
    end If

    MsgBox sZellRabatt 
"Was geschieht dort?"

Als erstes habe ich, ich sags mal so rum, ein "Wechselschalter" iTmp eingebaut. Vergleichbar mit einem Lichtschalter. Dieser hat, wie zu sehen, vor der Auswertung den Wert 0 (Null), das Licht bleibt aus.
Nun wird die Schleife (For Next) ausgeführt. Und innerhalb der Schleife wird überprüft ob die zu sehende Vergleichsbedingung zutrifft. Und wir sagen jetzt mal das alle 4 Durchläufe negativ ausgefallen sind. Und auf Grund dessen kommt bei der IF gar nicht der THEN Teil zum tragen, es bleibt also vorläufig im Dunkeln was dort steht.

Kurz dazwischen. iFE heißt integerFormelErsatz (meine Kreation, die Du aber nicht übernehmen musst).

Jetzt wird wieder ein Vergleich angestellt, ob iTmp gleich 0 (Null) ist. Und da das offensichtlich der Fall ist, wird jetzt der Variable sZellRabatt der Text Sonstige zugewiesen.
Anschließend wird der Inhalt der Variable in der MsgBox ausgegeben.


So, und nun fast das gleiche noch mal, aber diesmal ist die Auswertung vollständig komplett, also nix mehr ausgeblendet oder so. Und diesmal kopierst Du jetzt alles so wie zu sehen in die *Sub Main* rein.

Code: Alles auswählen

sgRabatt_Fl = '<- dort zu testzwecken verschiedene Werte eingeben'
iTmp = 0
    For iFE = LBound(aUnterGrenze()) to UBound(aUnterGrenze())
        If sgRabatt_Fl= aOberGrenze(iFE) OR (sgRabatt_Fl> aUnterGrenze(iFE) AND sgRabatt_Fl< aOberGrenze(iFE)) Then
           iTmp = 1
           sZellRabatt = aRabattText(iFE)
        End If
    Next iFE

    If iTmp = 0 then
        sZellRabatt = "Sonstige"
    end If

    MsgBox sZellRabatt 
In die erste Zeile kannst Du, wie zu lesen, Werte eingeben um die Funktion zu überprüfen.

Prinzipiell das gleiche wie vorhin. Jedoch sagen wir jetzt diesmal, das im 2. Schleifendurchlauf der Vergleich in der IF positiv ist und dementsprechend der THEN Teil zum tragen kommt. Dadurch wird iTmp auf 1 geschaltet, das Licht geht also jetzt an, und es wird jetzt der Variable sZellRabatt der Text aus dem passenden Array aRabattText(1) zugewiesen.

Wenn jetzt die Schleife (FOR...NEXT) fertig durchgelaufen ist, so hat ja iTmp den Wert 1. Und es geht weiter mit dem jetzt folgenden Vergleich.

Diesmal ist iTmp aber nicht gleich 0 (Null), wurde ja vorhin auf 1 geschaltet/gesetzt, und folglich kommt hier jetzt NICHT der THEN Teil zum tragen. Dadurch wird jetzt die schon beschriebene Variable sZellRabatt nicht noch mal beschrieben, beziehungsweise überschrieben. Also wird jetzt der Inhalt der Variable in der MsgBox ausgegeben.

Code: Alles auswählen

For iFE = LBound(aUnterGrenze()) to UBound(aUnterGrenze())
Warum habe ich das so gemacht, und nicht einfach *0 TO 3*?

Nun, da die Arrays ordnungsgemäß Deklariert wurden, haben sie eine Untere und eine Obere Begrenzung. Und diese Begrenzungen kann man mit LBound (Untere) und UBound (Obere) auslesen lassen. Man kann sich z.B. so gesehen nicht veschreiben, also anstatt 0 to 3 hätte man 0 to 4 geschrieben. Die Folge bei dem vertuer ist nämlich der, das es zwangsläufig zu einer Fehlermeldung kommt.

Ferner besteht der Vorteil auch dadrin, das bei einer Erweiterung, oder Verkürzung des Array die Schleife nicht geändert werden muss. Man muss lediglich die Deklaration anpassen und die Array Einträge erweitern oder reduzieren. Kurzes Beispiel dazu, was lediglich zeigt wo was geändert werden muss.

Code: Alles auswählen

Dim aUnterGrenze(5) as Integer, aOberGrenze(5) as Integer
Dim aRabattText(5) as String
aUnterGrenze(0) = 0 : aOberGrenze(0) = 0 : aRabattText(0) = " - "
aUnterGrenze(1) = 50 : aOberGrenze(1) = 50 : aRabattText(1) = "Mitarbeiter"
aUnterGrenze(2) = 50 : aOberGrenze(2) = 100 : aRabattText(2) = "Sachentnahme"
aUnterGrenze(3) = 100 : aOberGrenze(3) = 100 : aRabattText(3) = "Kostenfreie Abgabe"
aUnterGrenze(4) = 150 : aOberGrenze(4) = 200 : aRabattText(4) = "Freies Gelage"
aUnterGrenze(5) = 200 : aOberGrenze(5) = 300 : aRabattText(5) = "Kater Stimmung"
Die Auswertung bleibt unberührt, die bleibt so wie sie ist.

Jetzt muss natürlich nach erfolgreichen Tests alles noch an seinen richtigen Platz hinkommen.
Also, es kommt alles in das Modul *Flachenverkauf*. Und zwar wie folgt.
In die Sub Neuer_Flaschenverkauf kommt gleich zu Anfang das hier rein.

Code: Alles auswählen

Dim aUnterGrenze(3) as Integer, aOberGrenze(3) as Integer
Dim aRabattText(3) as String

aUnterGrenze(0) = 0 : aOberGrenze(0) = 0 : aRabattText(0) = " - "
aUnterGrenze(1) = 50 : aOberGrenze(1) = 50 : aRabattText(1) = "Mitarbeiter"
aUnterGrenze(2) = 50 : aOberGrenze(2) = 100 : aRabattText(2) = "Sachentnahme"
aUnterGrenze(3) = 100 : aOberGrenze(3) = 100 : aRabattText(3) = "Kostenfreie Abgabe"
Dann schmeißt Du folgende Zeile raus, einfach löschen.

Code: Alles auswählen

sFormulaRabattArt_Fl = "=IF(K" & iEnd_Row & "=0;"""";IF(K" & iEnd_Row & "=50;""Mitarbeiter"";IF(AND(K" & iEnd_Row & ">50;K" & iEnd_Row & "<100);""Sachentnahme"";IF(K" & iEnd_Row & "=100;""Kostenfreie Abgabe"";""Sonstige""))))"
Dann kommt ja der Block: ' Prüfen, ob Rabatt kleiner 0
Und nach dem dortigem Endif kommt dann das folgende rein, also noch vor ' Ausschluss vorhandener Flaschen-Artikelnummern.

Code: Alles auswählen

iTmp = 0
    For iFE = LBound(aUnterGrenze()) to UBound(aUnterGrenze())
        If sgRabatt_Fl= aOberGrenze(iFE) OR (sgRabatt_Fl> aUnterGrenze(iFE) AND sgRabatt_Fl< aOberGrenze(iFE)) Then
           iTmp = 1
           sZellRabatt = aRabattText(iFE)
        End If
    Next iFE

    If iTmp = 0 then
        sZellRabatt = "Sonstige"
    end If
Ein paar Zeilen tiefer kommt ja das hier.

Code: Alles auswählen

	oAktuellesBlatt.getCellRangeByName("L" & iEnd_Row).Formula = sFormulaRabattArt_Fl
Das änderst Du nun wie folgt um.

Code: Alles auswählen

	oAktuellesBlatt.getCellRangeByName("L" & iEnd_Row).String = sZellRabatt
Jetzt löscht Du das temporär eingefügte Modul, speicherst die Datei, und öffnest sie erneut.
Anschließend den Dialog aufrufen und testen ob auch mit dem Dialog die vorgenommenen Änderungen so weit alles funktioniert.


Eigentlich wollte ich dir ja noch zeigen wo Du das neue System mit dem Array noch anwenden kannst, aber ich habs mir noch mal überlegt und komme zu folgendem Entschluß: Für heute solls das gewesen sein.
Wenn Du alles so weit zufrieden stellend nachbauen konntest, dann sag bescheid, und dann hole ich das jetzt ausgelassene nach.

Viel Spaß, und Erfolg 8)



Gruß
balu
Sei öfter mal ein Faultier, sag öfter mal "Ach was!" Dann kriegst du keinen Herzinfarkt, und hast ne menge Spass.

wehr rächtschraipfähler findet khan si behalden :D
Benutzeravatar
Julia NuN
**
Beiträge: 38
Registriert: Mo, 07.11.2016 14:57

Re: Erarbeitung eines "POS-Kassenbuchs"

Beitrag von Julia NuN »

Hallo balu,

diesmal poste ich mal schon was vorneweg ohne die Datei hochzuladen. Denn noch habe ich die Formel nicht als makro umgeschrieben. Aber deinen vorherigen Beitrag habe ich abgearbeitet. :D
Das du Andrew noch nicht kanntest, dachte ich mir schon fast. Und deshalb der Link.
Und es ist sehr ausführlich und verständlich erklärt.
Ausführlich, ja.
Aber bei verständlich leben wir beide wohl in zwei verschiedenen Welten .
Hehe, ich glaube, aus meiner Anfänger-Sicht ist es so: Je mehr drin steht, umso mehr Anhaltspunkte habe ich, um das Richtige woanders nachzugucken. Somit ist umfangreicher=verständlicher. Ich habe gerade bei genauerer Betrachtung festgestellt, dass ich da keinen Unterschied mache, weil ich bei solcher Lektüre eh erstmal nix verstehe. Soviel zum Thema „verständlich“… :P

Boah, also das mit den Arrays ist wirklich eine Herausforderung für mich.
Da brauch ich mit Sicherheit noch ein bisschen Übung, bis der Groschen fällt.
Ja, eine so genannte Vorauswahl gibt es. ...
Hinzugekommen ist lediglich: oListBox_Preis.SelectItem(aKistenPreise(1), True)
Okay, das habe ich „verstanden“, höhö. ;)

Wichtig war weiterführend deine Erläuterung:
Und wenn man sich mit getDataArray ein Array holt, und in diesem Falle das umbenennt in aSourceDataArray, dann weiss das Makro das das Array eine bestimmte Größe (Anzahl an Einträgen) hat, die man mittels UBound auslesen kann.
Denn jetzt wollte ich das Ganze auch bei den Mitarbeiter-Namen machen. Mir schien, dass das hier wegen der erst lokal in der Sub Dlg_Neuer_Artikel deklarierten Größe des Arrays nur geht, wenn ich die Voreinstellung auf einen Mitarbeiter genau in dieser Sub vornehme und nicht erst beim Aufruf des Dialogs selbst (was ja in einer anderen Sub geschieht).

Hier habe ich es deshalb jetzt so gemacht, dass ich im Anschluss an die Definition für die Mitarbeiter-Listbox-Inhalte direkt die Vorauswahl festlege:

Code: Alles auswählen

' Listbox für Mitarbeiter-Rabatt mit Namen füllen:
aSourceDataArray() = oZellenMitarbeiter.getDataArray() 
Dim aSource(UBound(aSourceDataArray())) as String  
For c3po = LBound(aSource()) To UBound(aSource())
   aDataArrayRow() = aSourceDataArray(c3po)
aSource(c3po) = aDataArrayRow(0)
Next c3po
Dlg_Rabatt50.Model.getByName("RabattArt_50").StringItemList = aSource()
oListBox_Rabatt50.SelectItem(aSource(0), True) ' Erster Listbox-Eintrag vorausgewählt
Ich gehe davon aus, dass ich auf aSource() in diesem Fall nur zugreifen kann, wenn dies in derselben Sub passiert, weil das Element ja lokal und nicht global deklariert wurde.
Und eine Auslagerung von

Code: Alles auswählen

Dim aSource(UBound(aSourceDataArray())) as String 
an den Anfang des Moduls geht nicht, weil das aSourceDataArray() und die oZellenMitarbeiter ja auch erst später in der Sub Dlg_Neuer_Artikel definiert werden. Oder?

Ui, kompliziert.

Jedenfalls habe ich wegen des logischen Aufbaus dann die Vorauswahl eines Astrakisten-Preises auch in der Sub Dlg_Neuer_Artikel vorgenommen:

Code: Alles auswählen

' Listbox für Astrakistenverkauf mit Preisen füllen:
Dlg_Astrakiste.Model.getByName("Preis").StringItemList = aKistenPreise()
oListBox_Preis.SelectItem(aKistenPreise(0), True) ' vorausgewählter Listbox-Wert, hier der erste: 35,-€
Also nicht hier, wie vorgeschlagen (was in diesem Fall natürlich auch funktioniert):

Code: Alles auswählen

Sub Dlg_KastenAstra ' Dialog zur Artikeleingabe aufrufen
Dlg_Astrakiste.title = "Verkauf ganzer Kästen Astra"
oListBox_Preis.SelectItem(aKistenPreise(1), True)
Dlg_Astrakiste.execute
End Sub
Okay, sie sind enttarnt und entdeckt worden.

Code: Alles auswählen

For c3po
for r2d2
Find ich voll gut und echt Luschdich .
Freut mich! Ich hatte auch meinen Spaß dabei! :D

LG Julia
Wilhelm Busch: "Ein jeder Wunsch, wenn er erfüllt, kriegt augenblicklich Junge."
... ich glaub, der wär heutzutage Programmierer und nicht Schriftsteller.
Benutzeravatar
balu
********
Beiträge: 3810
Registriert: Fr, 24.08.2007 00:28
Wohnort: Warstein

Re: Erarbeitung eines "POS-Kassenbuchs"

Beitrag von balu »

Hallo Julia,

ja alles klar, jetzt verstehe ich "verständlich" besser. :lol:

Boah, also das mit den Arrays ist wirklich eine Herausforderung für mich.
Da brauch ich mit Sicherheit noch ein bisschen Übung, bis der Groschen fällt.
Das glaube ich dir sofort.

Ich gehe davon aus, dass ich auf aSource() in diesem Fall nur zugreifen kann, wenn dies in derselben Sub passiert, weil das Element ja lokal und nicht global deklariert wurde.
Korrekt.


Und eine Auslagerung von

Code: Alles auswählen

Dim aSource(UBound(aSourceDataArray())) as String 
an den Anfang des Moduls geht nicht, weil das aSourceDataArray() und die oZellenMitarbeiter ja auch erst später in der Sub Dlg_Neuer_Artikel definiert werden. Oder?
Man kann vieles machen, aber manche Dinge sollte man doch zusammenhängend erledigen, also nicht auseinander reißen.

Du hast den betroffenen Code-Abschnit wie folgt tituliert: ' Listbox für Mitarbeiter-Rabatt mit Namen füllen:
Was dir aber noch nicht ersichtlich ist, weil Du es noch nicht kennst, dieser Code-Abschnitt ist so gesehen eine "Routine". Und damit meine ich nicht eine Routine in der Form von; Ich bin geübt im Briefe schreiben. Viel mehr heißt das, das dies in gewisser Hinsicht ein abgeschlossener Code ist, den man auch noch anders einsetzen kann. Doch ich will jetzt nicht an dieser Stelle etwas vorweg greifen, was demnächst noch dran kommt.

Ui, kompliziert.
Tja, das stimmt. Und dabei ist das Thema Array hier noch nicht abgehakt. Aber bange machen gillt nicht. Wirt schon alles gut gehen ;-)

Jedenfalls habe ich wegen des logischen Aufbaus dann die Vorauswahl eines Astrakisten-Preises auch in der Sub Dlg_Neuer_Artikel vorgenommen:

Code: Alles auswählen

' Listbox für Astrakistenverkauf mit Preisen füllen:
Dlg_Astrakiste.Model.getByName("Preis").StringItemList = aKistenPreise()
oListBox_Preis.SelectItem(aKistenPreise(0), True) ' vorausgewählter Listbox-Wert, hier der erste: 35,-€
Also nicht hier, wie vorgeschlagen (was in diesem Fall natürlich auch funktioniert):

Code: Alles auswählen

Sub Dlg_KastenAstra ' Dialog zur Artikeleingabe aufrufen
Dlg_Astrakiste.title = "Verkauf ganzer Kästen Astra"
oListBox_Preis.SelectItem(aKistenPreise(1), True)
Dlg_Astrakiste.execute
End Sub
Hast Du auch überprüft das bei jedem erneuten Aufruf von *Verkauf Kiste Astra* in der dementsprechenden Listbox immer die richtge Vorauswahl steht?
Mach mal folgendes.

Den "Hauptdialog" (Artikel eingeben) aufrufen, in verschiedenen Dialogen Daten eingeben inklusive *Verkauf Kiste Astra*, den Hauptdialog nicht beenden. Dann weiter Daten eingeben ohne den Hauptdialog zu beenden und auch wieder in *Verkauf Kiste Astra* reinschauen. Beobachte wie sich die Vorauswahl der dementsprechenden Listbox verhällt.



Gruß
balu
Sei öfter mal ein Faultier, sag öfter mal "Ach was!" Dann kriegst du keinen Herzinfarkt, und hast ne menge Spass.

wehr rächtschraipfähler findet khan si behalden :D
Benutzeravatar
Julia NuN
**
Beiträge: 38
Registriert: Mo, 07.11.2016 14:57

Re: Erarbeitung eines "POS-Kassenbuchs"

Beitrag von Julia NuN »

Hallo balu,

am Wochenende hatte ich einen Durchhänger – die Woche war anscheinend zu voll und der Akku leer.
Ich hatte echt Probleme, mich in die Arrays hineinzudenken.
Dabei hast du es perfekt erklärt, wie ich mit vollem Akku heute morgen feststellen konnte. :)
Und somit kommt hier endlich eine überarbeitete Fassung, siehe Anhang.

Code: Alles auswählen

aUnterGrenze(0) = 0 : aOberGrenze(0) = 0 : aRabattText(0) = " - "
aUnterGrenze(1) = 50 : aOberGrenze(1) = 50 : aRabattText(1) = "Mitarbeiter"
aUnterGrenze(2) = 50 : aOberGrenze(2) = 100 : aRabattText(2) = "Sachentnahme"
aUnterGrenze(3) = 100 : aOberGrenze(3) = 100 : aRabattText(3) = "Kostenfreie Abgabe"
Du siehst jetzt so betrachtet eigentlich 4 Zeilen. Aber in wirklichkeit sind das jedoch 12 Zeilen. Der Grund für diese Art der Zeilenkomprimierung ist der Doppelpunkt (:). Denn durch dem wird dem Makro in diesem speziellen Falle gesagt, das das folgende eine weitere Zeile ist.
Jo!
Durch diese spezielle Anordnung der einzelnen Arrays kann man sich nun auch leichter merken, und vor allem auch nachvollziehen, das ein Array starke ähnlichkeit mit einem Tabellenblatt hat. Im Tabellenblatt kann man einzelne durchgehende Spalten mit einem Titel versehen, wie z.B. Untergrenze. Das ist jetzt im Array auch so, blos hier habe ich ein Array verständlicherweise als aUntergrenze benannt. Also 3 einzel Arrays mit 3 unterschiedlichen Titeln. Aber alle haben, und das ist extrem wichtig zu beachten, die gleiche Anzahl an Zeilen.
Alles klar!
Als erstes habe ich, ich sags mal so rum, ein "Wechselschalter" iTmp eingebaut. Vergleichbar mit einem Lichtschalter. Dieser hat, wie zu sehen, vor der Auswertung den Wert 0 (Null), das Licht bleibt aus.
Super Vergleich! Der Lichtschalter ist eine Komponente, von der ich befürchten würde, sie nicht immer gleich parat zu haben. Aber hier ist sie jetzt ja zum Glück ins Netz gemeißelt...

… öhhmm… zumal ich zu meiner Schande feststellen musste, dass eine solche Rabatt-Text-Festlegung gar nicht sinnvoll ist… Leider brauchen wir das hier gar nicht, weil es im Grunde nur den Rabatt-Text „Sonstige“ geben wird. Denn Mitarbeiter und Chefetage, die eine ganze Flasche einer Spirituose entnehmen, ersetzen sie einfach später. Und es wäre auch fast unmöglich für Mitarbeiter, den Flaschenpreis von 50% über den Dialog herauszubekommen.
Ich habe es jetzt trotzdem drin gelassen, weil´s so schön ist.

UND – weil ich denke, das war ein klasse Beispiel, wie Arrays funktionieren.

Ich hab ein bisschen darauf herumgedacht, ob es für den Lichtschalter auch noch andere Aggregatzustände geben kann als „an“ und „aus“. Ja, nä?
Mir ist bloß in dem Zusammenhang hier keine geeignete Variante eingefallen, die ich einsetzen kann.

Code: Alles auswählen

aUnterGrenze(4) = 150 : aOberGrenze(4) = 200 : aRabattText(4) = "Freies Gelage"
aUnterGrenze(5) = 200 : aOberGrenze(5) = 300 : aRabattText(5) = "Kater Stimmung"
Haha! Das gefällt mir!

Bezüglich der Vorauswahl von Listbox-Werten in der Sub „Dlg_Neuer_Artikel“ (andere bzw. früher aufgerufene Sub als der Dialogaufruf selbst):

Code: Alles auswählen

' Listbox für Astrakistenverkauf mit Preisen füllen:
Dlg_Astrakiste.Model.getByName("Preis").StringItemList = aKistenPreise()
oListBox_Preis.SelectItem(aKistenPreise(0), True) ' vorausgewählter Listbox-Wert, hier der erste: 35,-€
Hast Du auch überprüft das bei jedem erneuten Aufruf von *Verkauf Kiste Astra* in der dementsprechenden Listbox immer die richtge Vorauswahl steht?
Jetzt schon. ;) Guter Hinweis!

Na gut, denn doch wieder ab ins Modul „Kiste_Astra“:

Code: Alles auswählen

Sub Dlg_KastenAstra ' Dialog zur Artikeleingabe aufrufen
Dlg_Astrakiste.title = "Verkauf ganzer Kästen Astra"
Dlg_Astrakiste.Model.getByName("Preis").StringItemList = aKistenPreise() ' Kistenpreise aus Tabelle in Listbox eintr.
oListBox_Preis.SelectItem(aKistenPreise(0), True) ' Listbox-Wert Voreinstellung, hier der erste: 35,-€
oListBox_AusserHaus.SelectItemPos((0), True) ' Listbox-Wert Voreinstellung auf "Nein"
Dlg_Astrakiste.execute
End Sub
Gleiches Problem bestand sowieso auch schon bei der „Ausser Haus“-Vorauswahl, die ich nämlich im Dialog selbst festgelegt hatte (Auswahl „0“ - falls ich mich nicht verständlich ausgedrückt habe, unten ein Screenshot mit der entsprechenden Dialogvoreinstellung). Auch hier stellte sich der Wert nach Beendigung und Wiederaufruf des Dialogs nicht wieder auf den eingestellten Wert „0“ zurück.

Deshalb habe ich das hier stattdessen eingefügt, s.o. und hier:

Code: Alles auswählen

oListBox_AusserHaus.SelectItemPos((0), True) ' Listbox-Wert Voreinstellung auf "Nein"

Jetzt habe ich noch eine andere Frage:
Es wurde der Wunsch geäußert, dass im Tabellenblatt immer automatisch etwas hochgescrollt wird während der Eingabe. Jetzt muss man dafür ja immer erst die Dialog schließen.
Ich hab auch vielleicht die entsprechende Anweisung dazu gefunden, jedoch krieg ich das nicht so hingebastelt, dass es funktioniert.

Code: Alles auswählen

oAktuellesBlatt.getCellRangeByName("A" & iEnd_Row).Select

Was mich schon recht lange beschäftigt hat, ist folgendes:

Code: Alles auswählen

oAktuellesBlatt = thiscomponent.getcurrentcontroller.activesheet
oCellCursor = oAktuellesBlatt.createCursor()
oCellCursor.GotoEndOfUsedArea(True)
iEnd_Row = oCellCursor.getRangeAddress.EndRow
Nach einigen Tests habe ich den Eindruck, dass der Cursor, wenn er gebraucht wird, immer neu „created“ werden muss.
Jetzt habe ich, weil das so oft vorkam und so eine unschöne Verlängerung des Codes in den einzelnen Subs verursacht hat, ein Modul „Funktionen“ angelegt und das dahin verschoben.
Die Funktion wird jetzt mit ClZ aufgerufen (Cursor letzte Zeile).

Dank deiner Erläuterungen zu unserem vor Kurzem ebenfalls neu erstellten Modul „Text-Mitteilungen“ klappt der Aufruf auch.
:D

iiiiiiiiiiiiiiiih!
Jetzt kurz vor „Abschicken“ taucht etwas auf, womit ich mich schon einmal in einer ganz anderen Tabelle verzweifelt herumgeschlagen habe UND keine Lösung gefunden habe. Das habe ich seitdem völlig vergessen!

Wenn man in die von mir zuletzt eingegebene Zeile in die Spalte "Mindereinnahmen" klickt, sieht man oben in der Leiste nicht den eigentlichen, einfachen Wert „0“, sondern einen negativen, nämlich „-2,22044604925031E-016“.
Dadurch ändert sich in diesem Fall auch die Darstellung in -0,00 € statt - €.
Diesbezüglich habe ich damals das Internet tagelang durchforstet, weil ich nämlich alle Werte mit Null wegfiltern wollte und das dann deswegen nicht ging und ich es per Hand erledigen musste.

Ich wage gar nicht zu hoffen, dass du die Lösung kennst…!?

Ganz liebe Grüße
Julia
Dateianhänge
POS_Kassenbuch_Forum_7.ods
(65.76 KiB) 593-mal heruntergeladen
Vorauswahl im Dialog.PNG
Vorauswahl im Dialog.PNG (4.65 KiB) 22748 mal betrachtet
Wilhelm Busch: "Ein jeder Wunsch, wenn er erfüllt, kriegt augenblicklich Junge."
... ich glaub, der wär heutzutage Programmierer und nicht Schriftsteller.
Antworten