Seite 1 von 3
(gelöst) Rechnungsnummerntabelle
Verfasst: Mo 30. Mär 2015, 17:38
von Freischreiber
Hallo,
meine externe HSQL-Datenbank hat noch eine große Baustelle: die Tabelle mit Rechnungsnummern.
Sie sieht so aus:
(Bild gelöscht)
Und sie macht im Moment nur eins von selbst: automatisch das aktuelle Datum einfügen mit "alter table ... set default current date". Das klappt.
Sie soll:
- die FortlaufendeNr hochzählen, und zwar aus der Vorgängerzeile +1 (Autowert ist schlecht, der zählt intern stur hoch, auch wenn eine Zeile gelöscht oder korrigiert wurde)
- eine Zufallszahl vergeben, zweistellig
- die AuftragID möglichst aus dem Hauptformular übernehmen (diese Rechnungstabelle wird in einem Unterformular des Auftragsblatts angezeigt und ausgefüllt).
- am Schluß die Rechnungsnummer (Primärschlüssel) zusammensetzen (dafür hat F3K Total mir schonmal was geschrieben à la: "CREATE CACHED TABLE "Namen"("Nachname" VARCHAR(50),"Vorname" VARCHAR(50),"zusammen" VARCHAR(100) GENERATED ALWAYS AS(("Nachname"||', ')||"Vorname") PRIMARY KEY)"
Ich vermute, auch das Hochzählen und die Zufallszahl gehen mit einem Trigger, ich weiß bloß nicht wie (und ich finde dazu auch keine verständliche Dokumentation).
Gruß
Freischreiber
Re: Rechnungsnummerntabelle
Verfasst: Mo 30. Mär 2015, 21:38
von RobertG
Hallo Freischreiber,
ich würde das ganze über ein Makro lösen:
Ein Formular, das nur den letzten Datensatz der Rechnungsnummerntabelle über eine Abfrage anzeigt. Zusätzlich über eine Abfrage ein Feld für die Zufallszahl und eins für das aktuelle Datum erstellen. Zufallszahlen gehen in der HSQLDB über RAND().
Den Inhalt dieses Formular in ein zweites Formular kopieren. Wie so eine Kopie geht habe ich gerade bei den Beispieldatenbanken für LO beschrieben (Liegt auf
http://robert.familiegrosskopf.de/lo_hb_dev/). Die Datenbank liegt in einem *.zip-Paket, da sie auch eine *.csv-Datei enthält. Heißt "Daten_Duplizieren_Einzeldatenbank.zip". Die Beschreibung ist in Base_Beispiele_V45.pdf.
Gruß
Robert
Re: Rechnungsnummerntabelle
Verfasst: Di 31. Mär 2015, 09:41
von RobertG
Hallo Freischreiber,
ich habe das gerade einmal nachgebaut mit Hilfe der o.g. Datenbank.
Extrahiere das Verzeichnis und öffne in der Datenbank das Formular "Default". Wenn Du den Button betätigst wird die nächsthöhere ID geschrieben, das momentane Datum gesetzt und eine zweistellige Zufallszahl generiert (kann natürlich auch anders formatiert werden). Die Daten werden direkt abgespeichert.
Gruß
Robert
Re: Rechnungsnummerntabelle
Verfasst: Di 31. Mär 2015, 11:24
von Freischreiber
Hallo Robert,
es tut mir sehr leid, der Screenshot sollte meinen Tabellenaufbau illustrieren, war aber komplett irreführend, daher habe ich ihn gerade gelöscht.
Bei meiner Rechnungsnummerntabelle handelt es sich um eine ganz normale in der Datenbank integrierte Base-Datentabelle, keine Calc-Tabelle. Daher komme ich wohl ohne das Duplizieren von Daten aus.
Der Button "Neuer Datensatz" in deinem Formular "Defaultwerte" macht aber genau das, was mir vorschwebt. Nur das Makro kann vermutlich viel einfacher ausfallen, oder?
Was nicht ganz paßt, ist, daß das Hochzählen sich nicht nach der Vorgängerzelle richtet, sondern nach einer manuell eingefügten Zeile bei der vorletzten Zeile weiterzählt...
Gruß und bitte nicht sauer sein
Freischreiber
Re: Rechnungsnummerntabelle
Verfasst: Di 31. Mär 2015, 11:33
von RobertG
Hallo Freischreiber,
wenn Du auch manuell Daten mit entsprechender Nummer eingeben willst, dann muss zu Beginn des Makros lediglich das Formular aktualisiert werden. Das lässt sich in den Code einbauen.
Den Code hatte ich so bereits vorliegen. Natürlich geht das auch viel kürzer, da bestimmte Elemente nicht benötigt werden. Hier die kürzeste Variante:
Code: Alles auswählen
SUB DatenKopieren
DIM oFormStart AS OBJECT
DIM oFormZiel AS OBJECT
oFormStart = thisComponent.Drawpage.Forms.getByName("Quellformular")
oFormZiel = thisComponent.Drawpage.Forms.getByName("Zielformular")
oFormStart.reload()
oFormZiel.moveToInsertRow() 'Zum neuen Datensatz springen
oFormZiel.updateString(1, oFormStart.getString(1)) 'Felder aus Startformular auslesen und 1:1 zugeordnet wieder einfügen
oFormZiel.updateString(2, oFormStart.getString(2))
oFormZiel.updateString(3, oFormStart.getString(3))
oFormZiel.insertRow() 'Datensatz schreiben
END SUB
Durch den Reload zum Beginn wird tatsächlich der Datenstand ausgelesen, der tatsächlich in der zugrundeliegenden Datenquelle vorhanden ist.
Bei dem angehängten Beispiel habe ich stattdessen das Makro genutzt, das die Namen der Abfrage und der aufnehmenden Tabelle einander zuordnet.
Gruß
Robert
Re: Rechnungsnummerntabelle
Verfasst: Di 31. Mär 2015, 12:11
von RobertG
Hallo nikki,
es geht dabei um eine eindeutig zuzuordnende Nummer - sonst nichts.
http://www.akademie.de/wissen/fortlaufe ... ungsnummer
Das kann also ohne weiteres der AutoWert einer Tabelle sein, der nach Löschen von Datensätze ja nicht mehr lückenlos ist. Es kann auch eine Kombination verschiedener Nummern und Texte sein. Nur die Eindeutigkeit spielt eine Rolle.
Ich würde schlicht das Feld mit der Rechnungsnummer entweder als Primärschlüssel setzen oder mit einem eindeutigen Index versehen. Das reicht aus.
________________________
Die korrigierte Fassung mit Neueinlesen des Formulars vor der Kopie habe ich übrigens jetzt hier hoch geladen. Auch die Beschreibung ist bereits in den Base-Beispielen integriert:
http://robert.familiegrosskopf.de/lo_hb_dev/
Gruß
Robert
Re: Rechnungsnummerntabelle
Verfasst: Di 31. Mär 2015, 17:34
von Freischreiber
Hallo,
das Makro scheitert gleich mit "BASIC-Laufzeitfehler. Es ist eine Ausnahme aufgetreten Type: com.sun.star.container.NoSuchElementException Message: .".
Einfach den Namen des Unterformulars anzugeben, ist wohl falsch...
Ich verstehe schon die Konstruktion mit Quelle und Ziel nicht, und weshalb Daten dupliziert werden müssen. Ich habe nur ein Unterformular, das die Nummerntabelle anzeigt, abhängig von der Auftragsnummer (Tabellenkontrollfeld). Dort gibt es also eine Tabelle mit Rechnungsnummern, die zur Auftragsnummer gehören. Im Normalfall ist die Tabelle leer, weil es zu dem Auftrag noch keine Rechnung gibt, ich will einen Knopf drücken, es wird eine Nummer hochgezählt und aus dieser eine Rechnungsnummer zusammengesetzt im Format "Auftragsnummer-FortlaufendeNr-Zufallszahl".
Gruß
Freischreiber
Re: Rechnungsnummerntabelle
Verfasst: Di 31. Mär 2015, 20:10
von RobertG
Hallo Freischreiber,
Du brauchst eine Formularoberfläche, in der zwei Formulare nebeneinander liegen. Vielleicht muss ich da in der Beschreibung noch einen Screenshot hinzufügen, damit das auch klar wird.
In dem Makro wird das Formular, in das der Wert eingetragen werden soll, als "Zielformular" bezeichnet. Das Formular liegt auf der höchsten Ebene, ist also so, wie in dem Makro enthalten, nicht irgendein Unterformular von einem anderen Formular.
Das Formular, was über eine Abfrage zu der höchsten ID einen Wert hinzu zählt, eine Zufallsnummer erstellt usw., ist als "Quellformular" bezeichnet. Es ist nur mit der Datenquelle verbunden, zeigt aber im Formular selbst gar nichts an.
Du brauchst einfach 2 Formulare, um von einem zum anderen die Daten transportieren zu können - es sei denn, Du ermittelst die Daten mit SQL direkt im Makro.
Gruß
Robert
Re: Rechnungsnummerntabelle
Verfasst: Mo 6. Apr 2015, 15:35
von Freischreiber
Hallo Robert,
es sei denn, Du ermittelst die Daten mit SQL direkt im Makro
Das klingt einfacher, weil die zu einem Auftrag gehörenden Rechnungen eben durch ein Unterformular angezeigt werden.
Gibt es für so ein Makro auch irgendwo ein Beispiel?
Gruß
Freischreiber
Re: Rechnungsnummerntabelle
Verfasst: Mo 6. Apr 2015, 19:42
von RobertG
Hallo Freischreiber,
Code: Alles auswählen
SUB DefaultSetzenSQL
DIM oDatenquelle AS OBJECT
DIM oVerbindung AS OBJECT
DIM ooSql_Anweisung AS OBJECT
DIM oAbfrageergebnis AS OBJECT
DIM oFormZiel AS OBJECT
DIM stSql AS STRING
oFormZiel = thisComponent.Drawpage.Forms.getByName("Zielformular")
oDatenquelle = ThisComponent.Parent.CurrentController
If NOT (oDatenquelle.isConnected()) THEN
oDatenquelle.connect()
END IF
oVerbindung = oDatenquelle.ActiveConnection()
oSQL_Anweisung = oVerbindung.createStatement()
stSql = "SELECT ""AutoID"" + 1, CURRENT_DATE, ROUND( RAND( ) * 10000, 0 ) FROM ""Default"" ORDER BY ""AutoID"" DESC LIMIT 1"
oAbfrageergebnis = oSQL_Anweisung.executeQuery(stSql)
oFormZiel.moveToInsertRow() 'Zum neuen Datensatz springen
WHILE oAbfrageergebnis.NEXT
oFormZiel.updateString(1, oAbfrageergebnis.getString(1))
oFormZiel.updateString(2, oAbfrageergebnis.getString(2))
oFormZiel.updateString(3, oAbfrageergebnis.getString(3))
WEND
oFormZiel.insertRow() 'Datensatz schreiben
END SUB
Die Datenbankverbindung wird hergestellt. Geht so nur aus em Formular. Der SQL-Code entspricht dem, der in dem Beispiel in der Abfrage drin steht. Der Code wird ausgeführt und die entsprechendenm Werte direkt an das Zielformular weiter gegeben. Statt oFormStart steht hier jetzt immer oAbfrageergebnis.
Gruß
Robert