| | roPTools | TurboDB Studio | TurboDB VCL | >VDP < | KALHelp | Downloads | Verweise | Suche | Kontakt | Impressum | |
|
Alle Tipps und Tricks
|
| Topic Restrukturierungsmeldungen bei der Tabellendefinition | Kapitel Tabellen |
| Topic Importfehler: Typen stimmen nicht überein | Kapitel Tabellen |
|
Der Fehler besteht darin, daß der Spaltentyp nicht mit dem übereinstimmt, was in der zu importierende Tabelle gefunden wurde. Beispiel: Spaltentyp = Festkomma In der zu importierende Tabelle wurde aber ein Alphazeichen (a,b,...) gefunden.
|
| Topic Festhalten wann ein Datensatz das letzte Mal geändert wurde | Kapitel Tabellen |
| Topic Suche nach den ersten Eintrag bei einen Index bestehend aus Laufende_Nummer + einen String | Kapitel Tabellen |
|
Index: Suche nach den ersten Eintrag bei einen Index bestehend aus Laufende_Nummer + einen String ActivateForm("TABELLE.Formular"); Access(TABELLE, "TABELLE.ID"); Find("TABELLE.ID", Str(TABELLE2.Laufende_Nummer) +","); Der Trick ist hinter dem Komma keine Angabe zu setzen
|
| Topic Memofelder Inhalt löschen | Kapitel Tabellen |
|
Werden Datensätze mit Memofelder gelöscht, dann stellt sich immer wieder heraus, daß die Memofelder ihren Inhalt beibehalten haben. Lediglich der Verweis ist gelöscht. Auch die Ausführung von Indizes wiederherstellen, hat keinen Einfluß. Um den Inhalt zu löschen muß die Tabelle restrukturiert werden. Vorgang: Tabellenstruktur editieren, keine Veränderungen vornehmen, OK klicken, die Tabelle wird restrukturiert und dabei wird der nicht zugeordnete Inhalt der Memofelder gelöscht.
|
| Topic Wie lässt sich ein Index anlegen, der nur die nicht gelöschten Sätze anzeigt? | Kapitel Tabellen |
|
Ist leider nicht machbar, weil die Datensätze sofort physikalisch gelöscht werden. Damit ist die Konsistenz aller Indexdateien während der Löschung gewährleistet, die gelöschten Datensätzen sind daher nicht mehr herstellbar.
|
| Topic Import von verknüpften Tabellen | Kapitel Tabellen |
|
Import von verknüpfte Tabellen. Wenn Tabelle A ein Linkfeld auf Tabelle B hat, dann erst Tabelle B und anschließend Tabelle A importieren. Wenn eine Tabelle leer ist, (auch wenn die Einträge nur gelöscht wurden) und man importiert vorher exportierte Datensätze, dann werden exakt die selben Auto-Nummern vergeben. VDP vergibt erst neue Auto-Nummern, wenn ein bereits angelegter Datensatz mit einer höheren Nummer existiert. Grundsätzlich kann man also die Einträge importieren und anschließend muß auch die Zuordnung wieder stimmen.
|
| Topic Zeitfeld | Kapitel Tabellen |
|
Ein Zeitfeld speichert die Uhrzeit in Anzahl Minuten nach Miternacht, also als reines Zahlenfeld (max. Wert ca. 1460). Aus diesem Grund kann man damit rechnen, wie mit einem anderen Zahlenfeld. Beispiel: ZeitFeld * DM Hinweis: Als Feldnamen nicht Zeit oder datum verwenden. Diese Angaben sind für VDP reserviert.
|
| Topic Wiederherstellung einer Tabelle mit einem HexEditor | Kapitel Tabellen |
|
Vorgehensweise zur Wiederherstellung einer Tabelle mit Hilfe eines HexEditors 1.Tabelle sichern, damit man das mehrfach wiederholen kann. 2. attrib readonly von tabelle nehmen 3. Tabelle mit HexEditor aufmachen z.B. ultraedit 4. Die ersten 4 Byte auf die richtige Datengröße setzen. Falls Wert nicht bekannt, dann experimentieren. In diesem Fall ging es mit EE EE EE 00 Achtung: nicht größer, da ansonsten negativer Wert 5. Speichern und Tabelle mit VDP öffnen. 6. FileSize ansehen und restrukturieren.
|
| Topic Datenzerstörung beim Versuch der Volltext-Indizierung | Kapitel Tabellen |
| Topic Datensätze einer Tabelle vergleichen | Kapitel Tabellen |
|
Datensätze einer Tabelle können verglichen werden, in dem das Kommando RELATION verwendet wird. Mit dem Kommando RELATION temp=tabelle wird einen zweiten Handle von der Tabelle "tabelle" mit einem eigenen Satzpuffer erzeugt. Ein Satz aus Tabelle mittels readrec(tabelle,x) einlesen und mit readrec(temp,y) den zu vergleichenden Satz einlesen. Jetzt kann beispielsweise mit diff:=$temp.Feld - $tabelle.Feld auf die einzelnen Felder zugreifen. Mit Dank an Ulrich Kern.
|
| Topic Memofelder exportieren | Kapitel Tabellen |
|
Der Inhalt von Memofelder lassen sich mittels easy wie folgt exportieren: Alle Memos einer Datei werden in getrennte Textdateien geschrieben. Die Namen der Textdateien sind "RECx", wobei x der physikalische Satznummer entspricht. Link(TABELLE, CopyMemo(MEMOFEL, "REC" + STR(RecNo(TABELLE))))
|
| Topic Importproblem bei Feldnamen länger 30 Buchstaben | Kapitel Tabellen |
|
Beim Importieren von Textdateien in VDP Versionen tritt folgender Fehler auf: Alle Felder die über 30 Buchstaben haben (in der Textdatei) werden nicht eingelesen. Sind die Felder höchstens 30 Buchstaben lang, dann funktioniert es wie geplant. Die Felder in VDP 3.x können aber bis zu 255 Buchstaben lang sein. Lösung: Es ist ein Fehler in VDP und kann mittels folgendem Workaround umgangen werden: Die Tabellenüberschriften in der CSV-Datei identisch mit der DAT-Datei machen und unbedingt die Reihenfolge einhalten.
|
| Topic Serienbriefe mit Word für Windows | Kapitel Serienbriefe |
| Topic Bekannte Probleme der verschiedenen VDP Versionen | Kapitel Allgemeine Tipps |
| Topic Fehlermeldungen: Tipps | Kapitel Allgemeine Tipps |
| Topic Fehlermeldungen: Liste TDB/WinTDB/VDP Meldungen (unvollständig) | Kapitel Allgemeine Tipps |
| Topic Absturz WinTDB/VDP | Kapitel Allgemeine Tipps |
|
Sollte es vorkommen, das die Anwendung WinTDB.exe oder VDP.exe eine allgemeine Schutzverletzung liefert, m.a.w. abstürzt, dann reicht es nicht die Anwendung WinTDB/VDP neu zu starten, aber Windows muß neu gestartet werden! Das gilt für Windows 3.11 und Windows 95. Windows NT überlebt die Problematik. Obiges gilt natürlich auch für fertige VDP-Anwendungen. Warum (gilt für Windows 3.x und 95): Wenn VDP abstürzt bleiben Teile der Anwendung im Hauptspeicher "hängen" oder belegt. Das hängt mit der Hauptspeicherverwaltung von Windows zusammen. Zu erkennen ist das u.a. an der Große der verbleibende Kapazität der Windows Systemressourcen. Wird die VDP gleich neu gestartet, kann es unter Umstände zu der Verwendung von falsche Hauptspeicher-Seiten führen. Ist eine sehr technische Angelegenheit. Daher keine weitere Details. Um absolut sicher zu gehen, ist es auch ratsam bei große Datenmengen, alle Tabellen der VDP-Anwendung zu restaurieren. Ich spreche da aus Erfahrung.
|
| Topic Liste der Zuordnung für das Contextmapping. | Kapitel Allgemeine Tipps |
| Topic Mehrere VDP Versionen auf einem Rechner | Kapitel Allgemeine Tipps |
|
Es können mehrere VDP Versionen, z.B. VDP 2 und VDP 3 auf einem Rechner installiert werden, wenn die VDP DLLs jeweils im VDP BIN Verzeichnis abgelegt werden. Vorgehensweise: 1.VDP installieren 2.Folgende Batchdatei vom VDP BIN Verzeichnis (z.B. c:\prog\vdp2\bin) ausführen: rem rem Batchdatei: cleanvdp.bat rem VDP DLL-Dateien aus dem Windows-System-Verzeichnis ins VDP BIN Verzeichnis verschieben. rem Copy C:\WINDOWS\SYSTEM\BWCC32.DLL Copy C:\WINDOWS\SYSTEM\CW3230.DLL Copy C:\WINDOWS\SYSTEM\Owl52f.dll Copy C:\WINDOWS\SYSTEM\Bds52f.dll rem del C:\WINDOWS\SYSTEM\BWCC32.DLL del C:\WINDOWS\SYSTEM\CW3230.DLL del C:\WINDOWS\SYSTEM\Owl52f.dll del C:\WINDOWS\SYSTEM\Bds52f.dll Noch ein Tip: Wenn Sie feststellen möchten, ob VDP die richtige TDBEngine verwendet, dann VDP starten und versuchen die tdbengine, z.B. tdbengin40.dll umzubenennen.
|
| Topic Menüfunktionen | Kapitel Allgemeine Tipps |
| Topic SELF - Schnittstellenentwicklungsleitfaden | Kapitel Allgemeine Tipps |
|
Wer mehr über Schnittstellenprogrammierung wissen möchte: SELF - Schnittstellenentwicklungsleitfaden für Fremdanwendungen Tel. 0911-3191545
|
| Topic System-Tabelle verwenden | Kapitel Allgemeine Tipps |
| Topic tdbengine | Kapitel Allgemeine Tipps |
| Topic Daten grafisch darstellen | Kapitel Allgemeine Tipps |
|
Das Programm AUTOGRAPH kann Grafiken aus eine Datenbank generieren. Informationen: Martin Pflug Sachsenstrasse 26 32130 Hiddenhausen Tel:05223/84879 Fax:05223/878436 eMail:Pflug-@t-online.de
|
| Topic VDP Beschränkungen | Kapitel Allgemeine Tipps |
| VDP bis zu Version 2.03 Revision 90 |
Maximal Anzahl Tabellen: 30 Maximum Zeichen für die Beschreibung eines Index: 40
|
| Topic Import Tipps | Kapitel Allgemeine Tipps |
| Topic Verschiedene Zusatzprodukte | Kapitel Allgemeine Tipps |
| tdbText |
| Netzwerkfähigkeit |
tdbText wurde hinsichtlich Netzwerkfunktionalität nie speziell aufbereitet. Wenn zwei im Netz tdbText zum gleichen Datensatz aufrufen, dann kann dies durchaus kollidieren. Sie können jedoch versuchen, dies dadurch zu verhindern, daß man einfach einen temporären Dateinamen beim Aufruf verwendet. |
| Verschiedenes |
| Kopierschutz |
Tool zur Dateien-Verschlüsselungs-DLL für den VDP: Eine Möglichkeit ist www.mrk-soft.de (encryption, und auch in deutscher Sprache).
|
| Topic Kopierschutz | Kapitel Allgemeine Tipps |
| Kopierschutz wenn erstellten Programme auf CD weitergegeben werden |
Informationen zu Software: http://www.aladdin.de
|
| Topic Hilfreiche Formelfelder für Formularen | Kapitel Formulare |
| Topic Bericht aus einem Formular aufrufen | Kapitel Formulare |
|
Von einem Formular mittels eines Makros ein Bericht aufrufen, wobei als Selektion der aktuelle Datensatz übergeben wird. Makro im Formular: NOTE(STR($TABNAME.Nummer)); RUN("TABNAME.Bereicht_MEINBERICHT"); Berichtsselektionskriterium: Nummer = VAL(NOTE) Nummer ist ein Auto_Nummer-Feld der Tabelle TABNAME. Berichte haben den Vorteil daß das Layout wesentlich besser ist als gegenüber Datenbankjobs und Serienbriefe. Weitere Hinweise: NOTE kann auch verwendet werden um ein komplettes Selektionskriterium zu übergeben. Als Beispiel soll einen Bericht über den aktuellen Datensatz ausgegeben werden: Berichtsselektionskriterium: NOTE Wenn Sie in einem Formular ein Formelfeld mit dem Inhalt NOTE($Feldname) definieren, dann enthält dieses Feld immer den aktuellen Wert. Somit kann mittels Drucken, den aktuellen Datensatz-Bericht gedruckt werden (im Bericht oben aufgeführtes Bereichsselektionskriterium definieren). Vorteil ist, daß kein Makro definiert werden muß.
|
| Topic Bitmap Makros | Kapitel Formulare |
|
Die Standardschalter(Buttons) der WinTDB/VDP können mit einem Bitmap versehen werden: Vorgehensweise: o Anzeigeelement "Logo" im Formular einfügen o Makro Schalter in gleicher Größe wie das Anzeigeelement "Logo" auf dem Anzeigeelement rübersetzen und als Rahmenstil unsichtbar wählen.
|
| Topic Laufende Nummer des Koppelfeldes in einem Formel anzeigen | Kapitel Formulare |
|
Beispiel: Feld Kopplung gekoppelt mit ADRESSEN Formelfeld: ADRESSEN.Laufende_Nummer
|
| Topic Letzte Änderung eine Tabelle feststellen | Kapitel Formulare |
|
Mittels FirstDir lassen sich Datei-Informationen ausgeben. An Position27 fängt das Dateidatum an. Die folgende 18 Zeichen enthalten Datum und Zeit. Mittels DBName und FileNr kann die Änderung für die aktuelle Tabelleausgegeben werden: "Letzte Änderung: " + FirstDir(DBName(FileNr),"")[27,18] Beispieltabelle: adressen.dat "Letzte Änderung: " + FirstDir("adressen.dat","")[27,18]
|
| Topic ExecMacro eine andere Tabelle | Kapitel Formulare |
|
Wenn in einem Formular ein ExecMacro eine andere Tabelle ausgeführt wird, kann es vorkommen, daß nachdem Datensätze markiert sind und ein Formular in Tabellensicht aufgerufen wird, keine Datensätze angezeigt werden. Hierzu folgenden Tip wie die Datensätze angezeigt werden: Statt Makro-Befehl EXECMACRO(Tabelle, Ausdruck...), den Befehl ACTIVATEFORM(Formular);EXECMACRO(Tabelle, Ausdruck...) verwenden.
|
| Topic Inhalt geht beim Logo kopieren verloren | Kapitel Formulare |
|
Ist ein Bild in einem Logo eingebettet, dann wird mittels Bearbeiten,Kopieren der Logo-Inhalt nicht kopiert.
|
| Topic Tabelle im Formular: aktuell angezeigtes Record aufrufen | Kapitel Formulare |
|
Ist in einem Formular ein Anzeigeelement Tabelle definiert, dann ist esmanchmal sinnvoll auf den aktuell ausgewählte Datensatz (der angekoppelte Tabelle)zuzugreifen. Im Tabellenmodul folgende Prozedur definieren: Procedure ZeigeGekoppeltesRecord Var nRNo = RecNr(ANGEKOPPELTETABELLE); ActivateForm("ANGEKOPPELTETABELLE.Formular); SetMark(ANGEKOPPELTETABELLE. NRNo); Attach; Sortierung("Markierung"); Endproc Diese Prozedur durch folgendes Makro ExecMacro(TABELLE, ZeigeGekoppeltesRecord) aufrufen.
|
| Topic Ändern von Auswahlfelder | Kapitel Formulare |
|
Beim Ändern von Auswahlfelder ist folgendes zu beachten: In ein bestehendes Formular das Auswahlfeld löschen, wieder neuhinzufügen und Numerierung der Objekte anpassen. WinTDB/VDP speichert die Auswahlmöglichkeiten im Formular mit ab.
|
| Topic Feldinhalt mit Leerzeichen am Anfang abfangen | Kapitel Formulare |
|
Im Datenfeld unter Eingabekontrolle, Überprüfung folgende Bedingung setzen: Überprüfung: Links($Feld, 1) <> " " Meldung: Feld darf nicht mit einem Leerzeichen anfangen!
|
| Topic Umwandlung Großbuchstaben | Kapitel Formulare |
|
Umwandlung in Großbuchstaben mittels: Deutsch: TABELLE.Feld := GROß(TABELLE.Feld);Refresh; Englisch: TABELLE.Feld := UPPER(TABELLE.Feld); Refresh; Hinweis: wichtig ist das Refresh benutzt wird!!!
|
| Topic Feld verlassen Befehl | Kapitel Formulare |
|
Im Formulareditor kann ein Befehl ausgeführt werden, wenn das Feldverlassen wird. Es ist hier nicht notwendig bei der Änderung eines Feldinhaltes den Refresh-Befehl einzusetzen. Beispiel: Ausführen beim verlassen: $PreisMWST := $PreisNetto * 1,14;Refresh; Refresh ist NICHT notwendig, der $PreisMWST wird automatisch richtig gesetzt.
|
| Topic Formelfeld formatiert darstellen | Kapitel Formulare |
|
Bei der Verwendung von numerischen berechneten Feldern in Formularen und Berichten kann es störend sein, daß immer zwei Nachkommastellen ausgegeben werden. Hier kann die Funktion STR Abhilfe schaffen: Wenn Ihr bisheriger Ausdruck <Formel> war, sollten Sie STR(<Formel>, 0,n) angeben, wobei n die gewünschte Anzahl von Nachkommastellen ist. Beispiel: STR(INT(Geburtstag),5,0)
|
| Topic Meldung "Fehlerhafte Gültigkeitsbedingung" | Kapitel Formulare |
|
Die Gültigkeitsbedingung, die unter Eingabekontrolle eingegeben wurde,kann nicht berechnet werden. Beispiele: o Feldname falsch geschrieben o Makro hat sich geändert
|
| Topic Gezielt ausfüllen von Felder | Kapitel Formulare |
|
Die Fragestellung habe ich schon ein paar Mal gehört und kann folgende Lösung dazu bieten: Beispiel: Das Feld LAND (Werte z.B. D, NL, B etc., Länderkennungen sindgespeichert in der Tabelle TELLNDVW ) soll in die Felder TEL und FAX den jeweiligen Ländervorwahlsetzen. Weiterhin enthält eine globale Systemtabelle SYSTEM die Option ob dieLänderkennung mit einem Plus Zeichen oder mit 00 anfangen soll (Feld AdressenVorwahlPräfix). Für Holland währe es +31 oder 0031 und dann die Telefon- oderFaxnummer. Lösung: In der Eingabekontrolle für das Feld "LAND", Ausführen beim Verlassenfolgenden Befehl einsetzen: ExecMacro(ADRESSEN, SetzeTelFaxVorgaben(0)) Die Prozedur SetzeTelFaxVorgaben(0) (Dummy Parameter damit die Prozedurnicht in der Werkzeug/Makroliste erscheint) aus dem Modul Adressenmakros hatfolgenden Aufbau: Procedure SetzeTelFaxVorgaben(nDummy : Real); ..anhand von der eingabe im feld land, werden aus der tabelle tellndvw ..die vorwahlnummern fuer tel und fax gesetzt ..lokale proc der via execmakro beim verlassen des feldes Landausgeführt wird Vardef sVorwahl : STRING; ReadRec(SYSTEM, 1); .. lese system record IF $SYSTEM.AdressenSetzeTelFaxVorgaben = 1 AND GetMode = 2 ..suche Land aus der tabelle TELLNDVW nRNo := FindRec(TELLNDVW, $Land, "TEL-KENN.IND", 1); .. nichts gefunden, dann verlassen proc ?nRNo = 0 / Return ReadRec(TELLNDVW, nRNo); ..vorwahl setzen. präfix leer dann lasse wie es ist ?$SYSTEM. AdressenVorwahlPräfix = "" / sVorwahl := "" +$TELLNDVW.Vorwahl + " " ?$SYSTEM.AdressenVorwahlPräfix <> "" / sVorwahl :=$SYSTEM.AdressenVorwahlPräfix + $TELLNDVW.Vorwahl[3, Length($TELLNDVW.Vorwahl) - 2] + " " ..abhängig von der sparte tel und fax setzen IF $ADRESSEN.Sparte = 6 .. privat $ADRESSEN.Tel-Privat := sVorwahl $ADRESSEN.Fax-Privat := sVorwahl End IF $ADRESSEN.Sparte = 3 .. geschaeft $ADRESSEN.Tel-Geschaeft := sVorwahl $ADRESSEN.Fax-Geschaeft := sVorwahl End Refresh End EndProc
|
| Topic Prüfung ob ein Memofeld Inhalt hat oder nicht | Kapitel Formulare |
|
Definition eines Formelfeldes mit folgendem Inhalt : Choice(Sel(MemoLen(TABELLE.Memofeld)=0),"Leer","Inhalt") oder Choice(Sel(MemoLen(TABELLE.Memofeld)=0),"","vorhanden")
|
| Topic Memos in der Tabellensicht anzeigen | Kapitel Formulare |
|
Wird ein Memo-Feld in eine Tabellensicht angezeigt, dann wird das WortMEMO angezeigt. Verwenden Sie die Funktion MemoStr(Memo-Feld) um die ersten 255 Zeichendes Memos anzuzeigen. Die gleiche Möglichkeit kann in eingebetteten Tabellen verwendetwerden. Beispiel: Feld: Aenderung, Typ: MEMO, Anzeige als MemoStr(Aenderung) stattAenderung
|
| Topic Strings in der Tabellensicht links oder rechtsbündig ausgeben | Kapitel Formulare |
|
Um in der Tabellensicht Zeichenketten rechtsbündig auszugeben, öffnenSie das Dialogfenster mit dem Spaltenformat (Ansicht/Spalte ändern) und tragenunter Anzahl Nachkommastellen 0 ein. Siehe da: Die Spalte wird rechtsbündig ausgerichtet. Für linksbündig wird im Nachkommastellen-Feld nichts eingetragen (leerlassen).
|
| Topic Sounddatei abspielen | Kapitel Formulare |
|
Das Einlesen einer WAV-Datei geschieht genau wie das eines Bildes: DerSound erscheint als Schalter im Formular. Zuerst muß man den Editiermodus einschalten.Nach Drücken des Schalters wird ein Fenster geöffnet, in welchem ein Mikrofonsymbolenthält, fallsda Zum Abspielen eines Sounds braucht man auf jeden Fall die FunktionPlaySound. Plazieren Sie einfach einen Makroschalter in Ihr Formular und geben Sie alsMakrobefehl an: PlaySound(Klangfeld) Wobei "Klangfeld" das Label Ihres Soundfeldes ist.
|
| Topic Kompakte If-Abfragen mit der Choice-Funktion | Kapitel Formulare |
|
Die mit Abstand am meisten benötigte Steuerstruktur ist mit Sicherheitdie IfThenElse-Abfrage. Mit der Funktion Choice können einfache If-Abfragen realisiert werden.Diese Konstruktion kann man an den unterschiedlichsten Stellen nutzbringend einsetzen vorallem da, wo nur Ausdrücke und keine Kommandos syntaktisch zulässig sind: inTabellenformaten,in Choice(Wahl, a1, a2, a3 ... an) Der erste Parameter der Choice-Funktion muß eine Zahl sein. Diesebestimmt, welcher der nachfolgenden Ausdrücke das Funktionsergebnis bildet. Beträgt der Wertvon Wahl beispielsweise 2, ist das Funktionsergebnis der Ausdruck in a2. Wennder Wert des ersten Parameters nicht im Bereich von 1 bis n liegt, wird alsFunktionsergebnis von Choiceimmer Bei einer If-Abfrage gibt es für den Parameter Wahl nur zwei Werte,nämlich wahr und falsch. Ist Wahl wahr (Wert 1), wird der Parameter a1, zurückgegeben.Ist Wahl falsch (Wert 0), dann entspricht das Funktionsergebnis dem letzten Parameter(sinnvollerweisea Beispiel: Choice( Sel(Postfach < > ""), "Postfach: "+Postfach, Strasse) Erklärung: Mit der Funktion Sel wird die Bedingung geprüft: Postfach < > "" Ist das Feld Postfach nicht leer, trifft die Bedingung also zu, dannbildet der Eintrag in Postfach mit vorangestellter Konstante "Postfach: " dasFunktionsergebnis der Choice-Funktion. Ist das Feld Postfach hingegen leer, dann wird alsFunktionsergebnisderE Anmerkung: Die Angabe des bloßen Feldlabels bei einer Bedingung ist eine Abkürzungfür Feld < > "" daher kann der Funktionsaufruf auch lauten: Choice( SEL(Postfach), "Postfach: "+Postfach, Strasse) Weitere Beispiele sind: Nur einen Wert in eine Formel setzen wenn eine Bedingung erfüllt ist Setze im Formelfeld ALTER einen Wert wenn im Datenbankfeld GEBURTSTAGeinen Wert eingetragen wurde. Lösung: Choice(INT(Geburtstag)+1, 0, (Today - Geburtstag) / 365.25) Noch eleganter (speziell für oben genannte Aufgabenstellung): Choice(INT(Geburtstag)+1, "", "Alter:"+STR(INT((Today - Geburtstag) /365.25),3,0)) Gebe eine Informationszeile aus, wenn im Feld Ort einen Eintragvorhanden ist "A Gebe das Wort Termin aus, wenn eine Bedingung erfüllt wurde Choice(LINK(TERMLIST.AdressenRecNo = RecNo(ADRESSEN)), "Termin", "")
|
| Topic Zählen von angekoppelten Datensätzen | Kapitel Formulare |
|
Die Funktion der Wahl lautet 'LinkCount', bzw. Link und Count. Im Formular ein Formelfeld einfügen mit dem Inhalt LinkCount (TABELLE),wobei TABELLE der Name der angekoppelten Datei ist. Wenn es nicht funktioniert, gibt es Alternative folgende Formelverwenden: Link(TABELLE) * Count(TABELLE.Laufende_Nummer)! LinkCount geht auch über mehrere Distanzen hinweg, so dass auchZwischenkopplungen gezählt werden können.
|
| Topic Eingebettete Tabellen in einem Formular bearbeiten | Kapitel Formulare |
|
Folgende 3 Prozeduren ermöglichen eine direkte Bearbeitung von Datensätzen einer eingebettete Tabelle. Die Prozeduren können mittels Makro-Schalter auseinem Formular aufgerufen werden. Procedure DelSatz(nAktRec : Real); ..#Datensatz löschen ..#Parameter: ..#nAktRec = aktueller Datensatz If nAktRec > 0 ?Message("Satz wirklich löschen?", "Satz löschen", 3) = 6 /DelRec(TABELLE, nAktRec); End Endproc Procedure EditSatz(nAktRec : Real) : Real; ..#Datensatz bearbeiten ..#Parameter: ..#nAktRec = aktueller Datensatz Vardef nRT : Real; If nAktRec = 0 / Return 0 DatensätzeBearbeiten("TABELLE.Formular"); Readrec(TABELLE, nAktRec); nRT := EditRec("Ändern Sie die Angaben. Abbruch mit ESC."); CloseWnd; Return nRT Endproc Procedure NewSatz(nDummy : Real); ..#Neuer Satz anlegen ..#Parameter: ..#nDummy = damit die Prozedur nicht in der Makroliste erscheint Vardef nRNo, nAktRec : Real; nAktRec := ReadRec(PRIMTABELLE, RecNr(PRIMTABELLE)); If nAktRec > 0 ReadRec(TABELLE, 0); TABELLE.tFeld1 := "<Neu>"; Writerec(TABELLE, 1 + FileSize(TABELLE)); End nRNo := FindRec(TABELLE, Str(TABELLE.Laufende_Nummer), "TABELLE.INR",1); If nRNo > 0 ?EditSatz(nRNo) = 0 / DelSatz(nRNo); End Endproc
|
| Topic POS Befehl bei Feldverlassen verwenden | Kapitel Formulare |
|
Folgende Methode prüft das vorhanden sein einer Dateierweiterung. Ist keine Dateierweiterung vorhanden, dann wird eine Erweiterunggesetzt: Beispiel prüft ob eine Dateierweiterung HLP vorhanden ist: Choice(POS(".HLP", Upper(sHLPDateiname)) + 1, sHLPDateiname :=sHLPDateiname + ".hlp", "");Refresh; Wird beim Befehl Feldverlassen eines Formulars verwendet.
|
| Topic Reihenfolge in Ausführen-Menü | Kapitel Formulare |
|
Die Reihenfolge der Menüpunkte im Menü Ausführen ist im Entwurfsmodusanders als im Usermodus. Die Reihenfolge im Usermodus richtet sich nach derReihenfolge der Prozedureinträge ohne Parameter im ersten Formular, wogegen imEntwurfsmoduls die Prozedurenalph Sie müssen allerdings drauf achten, daß die Module in der richtigenReihenfolge übersetzt werden. Im Beispiel: erst Modul THELM003, dann THELM002 und THELM000 Beispiel: Modul THELM000 Prozedure Ausführen_Menüpunkt_1 ExecMacro(THELM001, Menüpunkt1(Parameter)); ..der Parameter kann auch ein Dummy Parameter sein Endproc Prozedure Ausführen_Menüpunkt_2 ExecMacro(THELM003, Menüpunkt2(Parameter)); ..der Parameter kann auch ein Dummy Parameter sein Endproc
|
| Topic Tabellenansicht löschen | Kapitel Formulare |
|
Ist keine Tabellenansicht gewünscht dann ist es Möglich dieTabellenseite zu löschen. Hierzu erst die Tabelle selektieren und mit Bearbeiten|Löschen löschen.Die Seite läßt sich auch über Bearbeiten|Löschen löschen. Die Seite muß allerdings komplettleersein
|
| Topic Änderungsdatum festhalten | Kapitel Formulare |
|
Das Änderungsdatum eines Datensatzes kann mit folgende Möglichkeit festgehalten werden: Für VDP: Legen Sie ein Datumsfeld an und geben Sie bei diesem im Formular unter Eigenschaften/Eingabekontrolle im Feld "Automatischer Eintrag" TODAY an ("Formel" vorher ankreuzen). Für TDB (DOS): Änderung am:_##########DF(heute) Diese Formel reagiert nur beim Editieren. So kann bei einer nachfolgenden Auswertung einfach alle - und nur diese - Datensätze auswählt werden, die voher editiert wurden.
|
| Topic Formularseiten beim Aufruf steuern | Kapitel Formulare |
|
Über die Eigenschaft Formular-Ereignisse | beim öffnen läßt sich u.a.auch die Seite die beim Aufruf des Formulars gezeigt werden soll steuern. Es gibt eine Reihe von Möglichkeiten. Tip 1: Via den Wert eines Feldes aus eine SYSTEM-Tabelle. Feld-Definition: SYSTEM.nPageNr, wobei nPageNr ein Byte-Feld ist Beispiel: procedure SetPage ..lese system record If ReadRec(SYSTEM, 1) > 0 ..setze seitennummer ViewPage(SYSTEM.nPageNr); end endproc Aufruf im Ereignis-Feld: ExecMacro(SYSLM001, SetPage) SYSLM001.MOD ist ein Modul der SYSTEM-Tabelle. Tip 2: wie Tip 1 nur direkt mittels ViewPage. Beispiel: ViewPage(SYSTEM.nPageNr) Aufruf im Ereignis-Feld: ViewPage(SYSTEM.nPageNr)
|
| Topic Dynamische Schalterbeschriftung | Kapitel Formulare |
|
Die Bezeichnung der Formularschalter sind standardmäßig starr aufgebaut, d.h. ein Formular wird erstellt. Die Felder und deren Bezeichnung definiert. Der Anwender hat keine Möglichkeit die Bezeichung zu ändern. Es gibt folgende Möglichkeit dynamische Schalterbezeichungen zudefinieren: Es gibt die Möglichkeit Formelfelder zu definieren. Anstatt eine feste Bezeichnung kann ein Formelfeld der einen Wert einer Tabelle dargestellt, verwendet werden. Beispiel: Es wird eine Tabelle SYSTEM angelegt. In der Tabelle werden alphanumerische Felder, z.B. Feld Bezeichnung-Schalter1 mit 20 Zeichen Feld Bezeichnung-Schalter2 mit 20 Zeichen usw. angelegt. Dazu wird ein Formular, z.B. "Schaltereinstellungen" definiert. Im Formular kann der Benutzer die Bezeichnung eingeben. Im Hauptformular wie folgt vorgehen: 1.Schalter definieren; Eigenschaften Farbe silber und Rahmen unsichtbar. 2.Formelfeld mit als Inhalt: SYSTEM.Bezeichnung-Schalter1 definieren und als Rahmen-Eigenschaft hervorgehoben. Sollte das nicht klappen, dann gibt es noch folgende Möglichkeiten: Formelfeld: ReadRec(SYSTEM ,1);SYSTEM.Bezeichnung-Schalter1 oder Formelfeld: SYSTEM.Bezeichnung-Schalter1[1, 255] 3.Formelfeld ausschneiden (über Menü Bearbeiten | Ausschneiden) 4.Formeld in Rahmen des Schalters einfügen (über Menü Bearbeiten |Einfügen) 5.Maße der beiden Elemente (Schalter und Formelfeld) gleich setzen (über Menü Ausrichten) das wars. Siehe auch Dynamische Feldbeschriftung.
|
| Topic Dynamische Feldbeschriftung | Kapitel Formulare |
|
Die Bezeichnung der Formularfelder sind standardmäßig starr aufgebaut, d.h. ein Formular wird erstellt. Die Felder und deren Bezeichnung definiert. Der Anwender hat keine Möglichkeit die Bezeichung zu ändern. Es gibt folgende Möglichkeit dynamische Feldbezeichungen zu definieren: Es gibt die Möglichkeit Formelfelder zu definieren. Anstatt eine feste Bezeichnung kann ein Formelfeld der einen Wert einer Tabelle dargestellt, verwendet werden. Beispiel: Es wird eine Tabelle SYSTEM angelegt. In der Tabelle werden alphanumerische Felder, z.B. FeldBezeichnung-Motiv mit 20 Zeichen usw. angelegt. Dazu wird ein Formular, z.B. "Feldeinstellungen" definiert. Im Formular kann der Benutzer die Bezeichnung eingeben. Im Hauptformular wird ein Formelfeld mit als Inhalt: SYSTEM.Bezeichnung-Motiv definiert. Daneben das Eingabefeld Motiv. Formelfeld: SYSTEM.Bezeichnung-Motiv Eingabefeld: Motiv Sollte das nicht klappen, dann gibt es noch folgende Möglichkeiten: Formelfeld: ReadRec(SYSTEM ,1);SYSTEM.Bezeichnung-Motiv oder Formelfeld: SYSTEM.Bezeichnung-Motiv[1, 255] Siehe auch Dynamische Schalterbeschriftung.
|
| Topic Unsichtbare Felder | Kapitel Formulare |
|
Ein Feld kann als Eigenschaft unsichtbar erhalten. Wenn jetzt einVorgabewert für das unsichtbare Feld definiert werden soll, komt VDP mit der Fehlermeldung;Falscher Ausdruck für dieses Feld. Sobald das Feld wieder sichtbar gemacht wird, istalles ok. Es ist aber möglich ein festen Vorgabewert zu definieren.
|
| Topic Formeln in eingebettete Formulare | Kapitel Formulare |
|
Eingebettete Formularen können bearbeitet werden, wenn die Optionenunter Tabelleneigenschaften gesetzt wurden. Es können Tabellen-Felder direktin der Tabellenzeile bearbeitet werden. Ist es notwendig Felder mitttelsFormeln mit einem Wert zu belegen, dannk Beispiel: Eingebette Tabelle (EINBETTAB) mit den Felder Feld1, Feld2 Haupttabelle (TABELLE) mit dem Feld Summe. Summe soll das Produkt vonFeld 1 und Feld2 erhalten, also Summe := Feld1 * Feld2 In der eingebettete Tabelle werden folgende Felder definiert: Feld1 (der Wert wird eingegeben) Feld2 := Feld1 * 1,16 (errechneter Wert, keine Eingabe möglich) Da Feld2 berechnet wird, wird diese nicht in der Datenbank geschrieben.Somit kann die Summe nicht berechnet werden. Was nun? Man kommt nicht drum rum ein EASY-Makro zu schreiben: Procedure SetSumme(nDummy : Real) : Real; ReadRec(EINBETTAB, RecNr(EINBETTAB)); Feld2 := Feld1 * 1,16; WriteRec(EINBETTAB, RecNr(EINBETTAB)); TABELLE.Summe := Feld1 * Feld2 Return Feld2 Endproc In der eingebette Tabelle kann anstatt Feld2 := Feld1 * 1,16, das MakroSetSumme(0) definiert werden. Zu beachten ist, daß SetSumme(0) mittelsExecMacro(MODUL, SetSumme(0)) aufgerufen werden muß.
|
| Topic Bedingter Formularzugang bei Mehrplatzbetrieb | Kapitel Formulare |
|
Im Mehrplatzbetrieb können Formulare und Formularfelder mittels eine Benutzertabelle gezielt gesteuert werden. Tip 1: Die Formulare können über Ihre Eigenschaft | nur Aktiv falls oder über die Eigenschaft | beim öffnen gesteuert werden. Das gleiche gilt für Felder. Beispielmöglichkeit Der Benutzer meldet sich bei VDP mittels Benutzername und Passwort an. Diese befinden sich zum Beispiel in eine Tabelle USER. Die Tabelle hat den Felder Benutzername Passwort Rechte Die Möglichkeiten sind vielfältig. Wenn Rechte z.B. 2 ist, darf der Benutzer auf Tabelle A aber nicht auf Tabelle B zugreifen. Das kann in eine easy-Prozedur abgefragt werden. Anmeldeablauf 1.Benutzername und Passwort beim Start der VDP-Anwendung abfragen. Aus der Tabelle USER 2.Benutzername in eine SYSTEM-Tabelle zwischen speichern. Zum Beispiel in der Tabelle SYSTEM mit dem Feld AktUser. Die SYSTEM-Tabelle kann auch mit USER verknüpft werden. 3.Bei jedes Formular etc. Benutzername und Rechte abfragen. Eintrag in nur Aktiv Falls: ExecMacro(SYSTEM, UserOK) = 1 Procedure UserOK If SYSTEM.AktUser.Rechte = 2 return 1 else return 0 Endproc 4.Das Gleiche für Formularseiten, Felder etc. Tip 2: Von einem Unbekannten aus dem TDB-Forum. Vielen Dank. Es gibt im Projekt eine eigene Tabelle zur Userverwaltung in der für jeden User ein Datensatz besteht in dem für alle gewünschten Rechte Ja/Nein Felder definiert sind. Beim Programmstart muß sich jeder User über ein Modul in dieser Tabelle anmelden, der Datensatz des angemeldeten Users wird dabei in dieser Tabelle markiert und der Zugriff auf Markierung gesetzt. Über die Abfrage der Rechtefelder in der Usertabelle kann nun in allen Formularen und Tabellen mit userabhängigen feldbezogenen Rechten gearbeitet werden. Den userabhängigen Zugriff auf verschiedene Tabellen/Formulare wird über eine "Hauptmenü-Seite" in dieser Usertabelle gestaltet. Auf diese Seite gelangt man nach dem Anmelden automatisch. Von hier können alle anderen Tabellen/Formulare per Macro/Procedure abhängig von den Userrechten aufgerufen werden. Die standartmäßigen Menüpunkte wie Tabellenliste etc. müssen natürlich angepasst bzw. entfernt werden.
|
| Topic Beschriftung in einen Rahmen oben bzw. unten einbinden | Kapitel Formulare |
|
Viele Formularmasken bekommen Ihren letzten Schliff erst durch Ihre Optik. Was leider noch nicht Version 2.01 vorhanden ist: Beschriftung in einen Rahmen oben bzw. unten einbinden. Die Beschriftung befindet sich z.Zz. nur über dem Rahmen. Mit einem kleinen Trick ist es doch möglich. Gewünschte Tabelle öffnen. Im Formulareditor das zu ändernde Formular öffnen. Es werden hier 2 Rahmen benötigt. Einen Hauptrahmen und einen Schriftrahmen. Gewünschten eigentlichen Hauptrahmen anlegen bzw. vorhandenen markieren. Beispiel: Breite 3.00 Höhe 2.00 Eigenschaften des Rahmens wie folgt anlegen: Beispiel: Farbe: Hintergrund , Rahmen: Rille. Wichtig : Rahmen nach hinten !!! Einen zweiten Rahmen anlegen. Dieser zweite Rahmen ist nun für dieSchrift verantwortlich. Eigenschaften des zweiten Rahmens: Farbe: Hintergrund , Rahmen: Keiner!!! Wichtig :Rahmen nach vorne!! Unter Stil den gewünschten Text eingeben. Unter Format gewünschte Schriftart und Ausrichtung auf Zentriert einstellen. Hinweis: Hier sehen Sie unter "Ausrichtung" einen eingebunden Text "Ausrichtung " im Rahmen von VDP 2.01 selbst. Beispiel: Text 10 pt. Beschriftung: "Test". Die Breite währe hier ca.0,83 Höhe 0,63 eventuell verkleinern. Der Text "Test" befindet sich nun über dem zweiten Rahmen. Der Trick dabei ist nun, daß dieser Text durch die oben genannten Einstellungen über den ersten Rahmen der oberen oder unteren Linie gelegt werden kann. Der zweite Rahmen verdeckt nun mit seiner Schriftzug die obere oder untere Linie. Dies hat den Effekt , als währe der Schriftzug in den Rahmeneingebunden. Der zweite Rahmen ist in der Höhe so klein wie möglich zu halten, damit der Rest des Rahmens unter der Schrift nicht die Felder im Formular stört. Natürlich können auch andere Rahmeneigenschaften Farbe und Hintergrund eingestellt werden. Wichtig ist nur das "nach vorne" und nach hinten "eingehalten" werden! Dieser Beitrag stammt von Georg Eisenbeiser. Vielen Dank.
|
| Topic Ein Formularfeld so formatieren, dass der erste Buchstabe immer ein Großbuchstabe ist | Kapitel Formulare |
| Topic Ein Feld vorbelegen, dass bei der Neuanlage automatisch die nächste Nummer eingetragen wird | Kapitel Formulare |
|
Die Lösung läßt sich am Besten anhand eines Beispiels erklären. Beispielfelder: Kundennummer (Alpha 20) Laufende_Nummer (Auto-Nummer) 1.easy-Prozedur definieren Procedure SetKundennummer : String; ..#setzt die nächste Kundennummer ..#es können auch komplexere Nummern vergeben werden. Zum Beispiel durch die ..#Verwendung einer Systemtabelle Return Str(Laufende_Nummer) ..oder Return "A" + Str(Laufende_Nummer,1,0) Endproc 2.Unter Formulareigenschaften, beim Öffnen die Kundennummer setzen: $Kundennummer := SetKundennummer;
|
| Topic Ereignis Beim_Verlassen | Kapitel Formulare |
|
Verschiedene Fragen und Antworten. Frage 1: Wie lässt sich eine Formular-Eigenschaft BEIM SPEICHERN programmieren? Antwort: Das Ereignis Beim_Verlassen wird aufgerufen, bevor der Datensatz gespeichert ist. Hier können Zuweisungen getroffen werden und mit Refresh in den Puffer geschrieben werden. Beispiel: PROCEDURE Beim_Verlassen; Eingabedatum := Today; Refresh; ENDPROC Das Ereignis Nach_dem_Verlassen bedeutet, daß der Eintrag bereits abgespeichert ist. Das Ereignis wird jedoch nur aufgerufen, wenn an dem Datensatz etwas geändert wurde (außer Änderungen in Memofeldern und Blobfeldern). In diesem Fall muß der Eintrag jedoch explizit abgespeichert werden. PROCEDURE Nach_dem_Verlassen ReadRec( FileNr, Recnr( FileNr)); Eingabedatum := Today; WriteRec( FileNr, RecNr( FileNr)); ENDPROC
|
| Topic Symbolleisten | Kapitel Formulare |
|
Jedes Formular kann eine eigene Symbolleiste haben. Somit kann man fürz.B. Masken-und Tabellenmodus getrennte Formulare anlegen.
|
| Topic Daten, wie Bilder einer Eingebettete Tabelle in ein Formular zeigen | Kapitel Formulare |
|
Ein Formular enthält eine eingebettete Tabelle. Diese Tabelle enthält ein Bildfeld. Die Aufgabe lautet; wie kann das entsprechende Bild dargestellt werden,wenn duch die Tabelle gescrollt wird. Diese Aufgabe ist recht komplex. Die beschriebene Prozedur ist daherrecht aufwendig. Ein Hinweis: In ein Formelfeld können alpha, numerische Felder direkt ausgegeben werden. Beispiele: Str(BYTEFELD) ALPHAFELD Procedure ShowBildAusTab(nArt : Real); ..#gehe durch eine eingebettete tabelle ..#der Aufruf erfolgt mittels Schalter im Formular ..#soll ein bild aus eine andere tabelle dargestellt werden, dann mußin der haupttabelle ..#auch ein bildfeld definiert werden. dieses bildfeld wird dann aulszwischenspeicher ..#verwendet. ich habe noch keine andere möglichkeit gefunden. einemöglichkeit wäre ..#das statische element logo zu verwenden. allerdings weiß ich nichtwie diese ..#angesprochen wird. ..#Parameter: ..#nArt = 1 vorheriger satz, 2 nächster satz, 3 anfang, 4 ende Vardef nRNo : Real; Vardef nBMPArt : Real; Vardef sStr : String; Vardef Q : Object; Vardef X : Object; ..eingebettete tabelle im formular suchen Q := FindDataWnd("SYSTEM.SYSTEM", "EINTAB"); Q.Use; ?nArt = 1 / Q.VorherigerDatensatz; ?nArt = 2 / Q.NächsterDatensatz; ?nArt = 3 / Q.AnfangDerTabelle; ?nArt = 4 / Q.EndeDerTabelle; ..lese aktuelles record aus der eingebettete tabelle If ReadRec(EINTAB, RecNr(EINTAB)) = 0 Return End ..halte recordnummer und pfad zu grafik fest nRNo := Q.RecNr(EINTAB); sStr := GetLinkedFile(EINTAB.Bildx); IF Length(sStr) > 0 ..suche hauptformular wieder (hat den namen SYSTAB) X := FindDataWnd("SYSTEM.SYSTEM", "SYSTAB"); ..setze bearbeitungsmodus X.ModifyRecords; ..verbinde grafik; 1 = BMP Datei. für andere bitmaps entsprechendesetzen ?Upper(sStr) hat ".BMP" / nBMPArt := 1; ?Upper(sStr) hat ".DIB" / nBMPArt := 1; ?Upper(sStr) hat ".PCX" / nBMPArt := 2; ?Upper(sStr) hat ".WMF" / nBMPArt := 4; ?Upper(sStr) hat ".GIF" / nBMPArt := 5; ..setze link LinkBlob(SYSTEM.Bildx, sStr, nBMPArt); ..beende bearbeitungsmodus X.ModifyRecords; END; ..setze datenzeiger der eingebette tabelle wieder richtig Q.ShowRec(nRNo) Refresh; Endproc
|
| Topic Formular als modaler Dialog | Kapitel Formulare |
|
Frage: Ich habe ein Formular modal als Dialog geöffnet und will aus ihm herauseinweites Formular (eine Hilfe) modal öffnen und erhalte die Fehlermeldung: Prozedur konnte nicht ausgeführt werden. Starte ich das Formular in der Entwicklerumgebung direkt, also nichtmodal, wird das Makro ausgeführt. Antwort: bei modalen Fenstern wird empfohlen, Makros nicht direkt, sondern überexecmacro(.. aufzurufen. Dann wird die gesuchte Funktione auch gefunden, weil VDP weiß, inwelchem Modul er nachsehen muß. Dies sollte aber nur bei Bedarf angewendet werden, da der Aufruf über Execmacro dazu führt, daß das Modul komplett gelesen , die Funktionaufgerufen und anschließend sofort wieder aus dem Speicher geworfen wird. Sind viele Aufruf z.B. beim Verlassen eines Feldes vorhanden, kann diesdie Performance beinflußen.
|
| Topic Eingebettete Tabellen-Objekte in Formularen(1) | Kapitel Formulare |
|
Folgende Prozeduren zeigen Beispiele zur Bearbeitung von eingebettete Tabellen in Formularen. procedure DoThemaPutStar; ..#setzt eine markierung Vardef RNo, nNoRecs, i : Real; VarDef oThemaTab : Object; oThemaTab := FindDataWnd("MLTTHEMA.Multi-Thema", "Thema"); oThemaTab.Use; oThemaTab.PutStar; oThemaTab.Attach; Return endproc; procedure DoThemaLoop; Vardef RNo, nNoRecs, i : Real; VarDef oThemaTab : Object; oThemaTab := FindDataWnd("MLTTHEMA.Multi-Thema", "Thema"); ?oThemaTab = 0 / Return oThemaTab.Use; oThemaTab.SetSortOrder("Markierung"); ..gibt es markierte sätze nNoRecs := Link(THEMA) * Count(THEMA); ?nNoRecs = 0 / Return ..Message(Str(nNoRecs)); i := 1; ..lese die themen oThemaTab.TopOfTable Repeat RNo := ReadRec(THEMA, RecNr(THEMA)); Message(Str(RNo) + "#" + THEMA.sThema, Str(i) + "/" + Str(nNoRecs)); oThemaTab.NextRecord; i := i + 1; Until i > nNoRecs oThemaTab.SetSortOrder("THEMA.ID"); Return endproc; procedure DoThemaGetStarNum : real; ..#liefert anzahl markierte datensätze VarDef oThemaTab : Object; oThemaTab := FindDataWnd("MLTTHEMA.Multithema", "Thema"); oThemaTab.Use; oThemaTab.SetSortOrder("Markierung"); ..gibt es markierte sätze Return Link(THEMA) * Count(THEMA); endproc; procedure DoThemaSort; ..#setzt die sortierung auf standard.id VarDef oThemaTab : Object; oThemaTab := FindDataWnd("MLTTHEMA.Multithema", "Thema"); oThemaTab.Use; oThemaTab.SetSortOrder("THEMA.ID"); oThemaTab.TopOfTable; Return endproc;
|
| Topic Darstellung Link-Felder | Kapitel Formulare |
|
Alle Datenfelder aus anderen Tabellen, die mit Koppelfelder verbunden sind, können auch in der Tabellenansicht dargestellt werden. Die Syntax hierzu entspricht der sogenannten Link-Notation: Beispiel: Spalte 1: RechnungsNr Spalte 2: Kunde.Name Spalte 3: Kunde.Vorname Spalte 4: Währung.Währungskennzeichen Wenn das Linkfeld jedoch in der anderen Tabelle steht und auf die Primärtabelle zeigt, kann man die Information nicht in neben den Felder der Primärtabeledarstellen, sondern muß man für diese Tabelle eine eingebunde Tabelle ins Formulareinsetzen.
|
| Topic Eingebettete Tabellen-Objekte in Formularen(2) | Kapitel Formulare |
|
Folgende Prozeduren zeigen wie auf eingebette Tabellen zugegriffenwerden kann. procedure ThemaTabGetStarNum(nDummy : real) : real; ..#liefert anzahl markierte datensätze der eingebettete tabelle thema VarDef oThemaTab : Object; VarDef nRNo, i, nNoRecs : Real; oThemaTab := FindDataWnd("MLTTHEMA.Multi-Thema", "Thema"); ?oThemaTab = 0 / Return 0 oThemaTab.Use; oThemaTab.SetSortOrder("Markierung"); nRNo := ReadRec(THEMA, RecNr(THEMA)); ?nRNo = 0 / nNoRecs := 0; ?nRNo > 0 / nNoRecs := Link(THEMA) * Count(THEMA); ..oThemaTab.SetSortOrder("THEMA.ID"); ..oThemaTab.TopOfTable; Return nNoRecs endproc; procedure DoThemaPutStar; ..#setzt eine markierung Vardef RNo, nNoRecs, i : Real; VarDef oThemaTab : Object; oThemaTab := FindDataWnd("MLTTHEMA.Multi-Thema", "Thema"); oThemaTab.Use; oThemaTab.PutStar; oThemaTab.Attach; Return endproc; procedure DoThemaTabLoop; ..#eine sehr umständliche procedure aber sie funktioniert Vardef RNo, nNoRecs, i : Real; VarDef oThemaTab : Object; ..gibt es markierte sätze nNoRecs := ThemaTabGetStarNum(0); oThemaTab := FindDataWnd("MLTTHEMA.Multi-Thema", "Thema"); oThemaTab.Use; If nNoRecs = 0 oThemaTab.SetSortOrder("THEMA.ID"); oThemaTab.TopOfTable; return End oThemaTab.SetSortOrder("Markierung"); i := 1; ..lese die themen oThemaTab.TopOfTable Repeat RNo := ReadRec(THEMA, RecNr(THEMA)); ?RNo > 0 / Message(Str(RNo) + "#" + THEMA.sThema, Str(i) + "/" + Str(nNoRecs)); ?i < nNoRecs / oThemaTab.NextRecord; i := i + 1; Until i > nNoRecs oThemaTab.SetSortOrder("THEMA.ID"); oThemaTab.TopOfTable; Return endproc; procedure DoThemaTabGetStarNum : real; ..#liefert anzahl markierte datensätze VarDef oThemaTab : Object; oThemaTab := FindDataWnd("MLTTHEMA.Multithema", "Thema"); oThemaTab.Use; oThemaTab.SetSortOrder("Markierung"); ..gibt es markierte sätze Return Link(THEMA) * Count(THEMA); endproc; procedure DoThemaTabGetNoRecs : real; ..#liefert anzahl datensätze VarDef oThemaTab : Object; oThemaTab := FindDataWnd("MLTTHEMA.Multithema", "Thema"); oThemaTab.Use; Return Link(THEMA) * Count(THEMA); endproc; procedure DoThemaTabSort; ..#setzt die sortierung auf standard.id VarDef oThemaTab : Object; oThemaTab := FindDataWnd("MLTTHEMA.Multithema", "Thema"); oThemaTab.Use; oThemaTab.SetSortOrder("THEMA.ID"); oThemaTab.TopOfTable; Return endproc;
|
| Topic Neuen Datensatz eingebettete Tabelle anlegen (Koppelfeld) | Kapitel Formulare |
|
Ausgangsbasis Tabelle RECHNUNG Tabelle POSTEN POSTEN hat ein Koppelfeld Rechnung auf der Tabelle RECHNUNG Neben der eingebettete Tabelle im Formular soll ein Schalter NEU angelegt werden, der ein makro ausführt welches ein neuen Datensatz der Tabelle POSTEN anlegt. Procedure POSTENNEU Vardef nRNo, nRLN : Real; ..aktuelle rechung lesen nRNo := ReadRec(RECHNUNG, RecNr(RECHNUNG)); ?nRNo = 0 / Return ..speichere rechnungs laufende nummer nRLN := RECHNUNG.Laufende_Nummer; ..lege neuen POSTEN Datensatz an ReadRec(POSTEN, 0); ..koppele POSTEN mit RECHNUNG POSTEN.Rechnung := nRLN; ..alternativ mittels POSTEN.Rechnung := RECHNUNG.Laufende_Nummer; ..speichere POSTEN WriteRec(POSTEN, FileSize(POSTEN) + 1); .. Message("Tabelle POSTEN: Datensatz angelegt.", "Hinweis"); Endproc
|
| Topic Feldbeschriftungen | Kapitel Formulare |
|
Tip 1: ja/nein-Feld mit Beschriftung Date&Time wird dargestellt als Date_Time. Das & wird von Windows bei Beschriftungen in Menüs und Controls als Unterstrich umgesetzt. Das ist von Windows so definiert, daran gibt es nichts zu ändern.
|
| Topic Felder auf Inhalt prüfen | Kapitel Formulare |
| Tipp 1 |
Prüfen ob ein Datumsfeld Inhalt hat. Lösung: Choice(Sel(Datumsfeld = 0), "Leer", DateStr(Datumsfeld)); oder in easy bzw. Datenbankjob If Datumsfeld = 0 Message("dann ist es leer!") End
|
| Topic Anzeigeprobleme nach Änderung an Tabelle | Kapitel Formulare |
|
Nach Änderung einer Tabelle (ein Koppelfeld wurde entfernt, neue Datenfelder hinzugefügt) erscheint in der Tabellenansicht immer noch das gelöschte Koppelfeld, die neuen Felder (Spalten) sehe ich aber nicht. Diese Tabellensicht wird wie folgt aktualisiert: Menü: Ansicht -> Standard-Tabellenformat VDP speichert die Ansicht, wie es der User eingerichtet hat. Diese wird nicht automatisch geändert. Das Standard-Tabellenformat kann man aber über oben genannten Menüpunkt abrufen.
|
| Topic Fenster im Vollbild öffnen | Kapitel Formulare |
|
Unter Programm Eigenschaften die Option Einfenster Anwendung wählen.
|
| Topic Felder aktivieren / deaktivieren | Kapitel Formulare |
|
Unter Feld/Eigenschaften/Aktivierung kann unter Bedingung eine Abfrage definiert werden. Abhängig vom Ergebnis können Daten geändert werden oder nicht. Möglichkeit 1: In eine Systemtabelle ein numerisches Feld zur Steuerung definieren. Zum Beispiel: Feldzugriff Dann im Formular Feld Eingenschaften Bedingung setzen. Zum Beispiel: SYSTEM.Feldzugriff = 1 ermöglicht den Zugriff, wenn ungleich 1 dann kein Zugriff Möglichkeit 2: Mittels eine Ini-Datei und dann wie oben.
|
| Topic Reihenfolge der Bereiche in einem Datenbankjob | Kapitel Datenbankjobs |
|
Nachfolgend eine klare Darstellung der Bereichsreihenfolge in einem Datenbankjob: .Report .Prolog ..Steuerzeichen .GP 1 etc. ..Zugriff .SetAccess MyTab.ind .Selektion $1=MySel .Kopf Ich bin eine Kopfzeile vom $heute Seite $Seite .Fuß Ich bin die Fußzeile ..Gruppierung nach Feldname .Gruppe MyFeld[1] .Daten $1 $2 .Epilog
|
| Topic Datenbereich in ein Datenbankjob | Kapitel Datenbankjobs |
|
Ein Datenbereich muß immer eine Datenausgabe haben, damit Daten erscheinen. Wenn im Datenbereich nichts steht als ein Subreport, dann erhalten Sie keine Ausgabe. Daher immer: .DATEN $(<Mindestens ein Feld der Primärtabelle>) .SUB $(<Felder der angekoppelten Tabelle(n)>) .ENDSUB Header leitet übrigens eine Gruppendefinition ein, die Sie nichtbenötigen, wenn Sie SubReports verwenden. Wenn im Daten-Bereich nicht direkt ein Wert ausgegeben werden soll,gibt es folgenden Trick: Definition eine Dummy-Variable: .Var x = 0 Im Datenbereich folgende Zuweisung: .DATEN .Do x := TABELLE.Laufende_Nummer ..
|
| Topic Kommando Report oder Serienbrief | Kapitel Datenbankjobs |
|
Das Kommando .REPORT oder .SERIENBRIEF (.LETTER) muß immer in der ersten Zeile des Jobs stehen. Ansonsten werden sie ignoriert. .REPORT oder .LETTER
|
| Topic Dialogfenster in Datenbankjobs | Kapitel Datenbankjobs |
|
Bekanntlich verwendet easy Formulare von speziellen Hilfstabellen als Dialogfenster zur Benutzerinteraktion. Leider kann man in Datenbankjobs auf diese Methode nicht zurückgreifen, weil es sonst in der Druckvorschau zueinem Deadlock (Endlosschleife) kommt. Es geht dann nichts geht mehr. Will man also auf die Druckvorschau nicht verzichten hilft nur eines: Das Dialogfenster muß in eine Prozedur ausgelagert werden, welche anschließend den Datenbankjob ohne Dialogfenster mit der Menüfunktion Druckenstartet.
|
| Topic Ausgabe indirekt angekoppelter Informationen | Kapitel Datenbankjobs |
|
Bei einem System mit zwei Dateien, die über ein Koppelfeld miteinanderverbunden sind, bietet die Benutzeroberfläche der Turbo Datenbank für Windows komfortable Funktionen zur Dateneingabe und zur Ansicht derverknüpften Informationen. Auch die Formulierungvon Ausgabejobs ist durch das ADL-System denkbar einfach. Lediglich für die Ausgabe indirekt angekoppelter Informationen muß man wissen, daß es den Subreport gibt. Angenommen es gibt eine Tabelle mit den Datenfeldern Tabelle FIRMEN Spalten Firma, Straße, PLZ, Ort, Telefon und eine zweite Tabelle mit den Ansprechpartnern. Tabelle ANSPRECH Spalten AName, AVorname, AAbteilung, ADurchwahl, AFirma (Koppelfeld auf die Firmentabelle) Diese Datenstruktur hat den großen Vorteil, daß beliebig viele Ansprechpartner mit einem Firmeneintrag verknüpft sein können. Ein Ansprechpartner kann allerdings nur mit einem Firmeneintrag verbunden sein. Hier liegt also eine 1:n-Verbindung vor. Diese Datenbank kann man nun von zwei Seiten aus betrachten. Bei aktiver Primärtabelle ANSPRECH (wenn z.B. ein Formular der Anprechpartner-Tabelle aktiv ist), ist der jeweilige Firmeneintrag (direkt) verknüpft und kann mit der Menüoption "Ansicht/Verknüpfte Datensätze" eingesehen werden. Wird die Primärtabelle gewechselt, beispielsweise durch Aktivierung eines Formulars der Firmen-Datei, sind nun die Ansprechpartner (indirekt) angekoppelt und lassen sich über "Ansicht/VerknüpfteDatensätze" einblenden und bearbeiten. Nun aber zur Datenausgabe innerhalb eines Datenbankjobs. Direkt verbundene Datensätze lassen sich meist ganz einfach, durch die Angabe des Spaltennamens ansprechen (sofern kein Konflikt durchgleichlautende Spaltennamen vorliegt). So kann man eine Adressliste füralle Ansprechpartner ganz einfach auf folgende Weise erstellen. .REPORT .PROLOGUE .PrimTableIs ANSPRECH .DATEN $Firma $AAbteilung $(AVorname+" "?(AVorname) AName) $Strasse $PLZ $Ort Nun das Ganze einmal von der anderen Seite. Für jede Firma sollen die Ansprechpartner aufgeführt werden. In diesem Fall werden also indirekt angekoppelte Informationenausgewertet. Das macht man immer mit einem Subreport: .REPORT .PROLOG .PrimTableIs FIRMEN .DATEN $(Firma:25 Telefon r 15) $Straße, $PLZ $Ort Ansprechpartner: .SUB $(AName:15 AVorname:10 AAbteilung:10 ADurchwahl r 15) .ENDSUB .EPILOG
|
| Topic Funktionsaufrufe in Datenbankjobs | Kapitel Datenbankjobs |
|
Der Einsatz von Standardfunktionen innerhalb von Datenbankjobs ist problemlos möglich, wenn es sich um Funktionen handelt, die ein Ergebnis liefern (z.B. Today, SQRT etc.). Sie werden einfach innerhalb von Ausdrücken verwendet, z.B. bei Variablenzuweisungen oder in einem Ausgabeformat. Zahlreiche Funktionen liefern nicht nur ein Ergebnis, sondern erfüllen in erster Linie eine Aufgabe, wie z.B. die Ausgabe einer Nachricht (Message) oder das Lesen eines bestimmten Datensatzes (ReadRec). Da auch diese Funktionen einen Wert liefern,kann man sie wie jede andere Funktion verwenden. Quasi als Nebeneffekt wird der eigentliche Zweck der Funktion ausgeführt. Oft gibt der Rückgabewert der Funktion Aufschluß über den Erfolg der Aktion. Daher ist der Aufruf der Funktion innerhalb einer Variablenzuweisung oft sinnvoll. Beispiel für eine bedingte Ausgabe in einem Serienbrief: .VAR DruckeOrt = Message("Auch den Ortsnamen ausgeben?", "Anfrage", 3) $(Name, Vorname) .FALLS DruckeOrt = 6 $(PLZ Ort) .ENDE (Zur Erinnerung: die Funktion Message liefert den Wert 6 zurück, wennder Anwender den Ja- Schalter gedrückt hat.) Wird der Rückgabewert nicht benötigt oder handelt es sich um eineselbst definierte Prozedur, welche gar keinen Wert zurück liefert, kann man die Funktion auch mittels des Kommandos .DO aufrufen. Beispiel: .DO ShowWait("Auswertung läuft. Bitte etwas Geduld...") ..Weitere Befehle .DO HideWait
|
| Topic Druckparameter aus Tabelle setzen | Kapitel Datenbankjobs |
|
Es ist sinnvoll eine Tabelle mit Einstellungen für Ihr Projekt zudefinieren, z.B. Tabelle SYSTEM. Diese Tabelle kann dann u.a. Einstellungen für Reports enthalten. Diese Einstellungen können innerhalb eines Datenbankjobs wie folgt gesetzt werden: .REPORT .PROLOG ..lese einzigster Datensatz aus der Tabelle SYSTEM .DO ReadRec(SYSTEM, 1) .DO SetPara(".PL"+STR(SYSTEM.EL)+", PO"+STR(SYSTEM.ER)) ...
|
| Topic Schriftarten bei Listen und Jobs | Kapitel Datenbankjobs |
|
Die Formatierung der Ausgabe erfolgt nur zeichenorientiert, d.h. es können keine Proportionalschriften (s.g. TrueType Schriftarten) verwendet werden, aber nur Zeichensätze mit fester Breit, wie z.B. Courier. True Type Schriftarten sind am Zusatz New zu erkennen, z.B. Times NewRoman, Courier New.
|
| Topic Seitenlänge einstellen für Listen | Kapitel Datenbankjobs |
|
Prinzipiell gilt für Listen und andere Ausdrucke, daß die Papierlänge unter dem Menüpunkt Datei | Drucker eingestellt wird.
|
| Topic Links und Rechtsbündige Kopf-/Fußzeilen | Kapitel Datenbankjobs |
|
Folgende Darstellung in eine Fußzeile: TDBprov-Projektdetailbericht, ausgegeben am 31.12.96 um 09:00 Seite 1 ist wie folgt in einem Job zu definieren: .Footer .HL $("TDBProv-Projektdetailbericht, ausgegeben am "+$heute+" um "+$jetzt)$("Seite "+$Seite R_Form ToMargin ) Die Plus Zeichen (+) nicht vergessen, da sonst die Leerzeichen nicht sauber dargestellt werden. Für die Kopfzeile (Header) gilt Gleiches. Noch einen Hinweis: Sollte die Kopfzeile auf jede Seite erscheinen, dann das Punktkommando.HE 1 verwenden: .HE 1 .Header $(...
|
| Topic Job (Liste) mit laufendem Numerierung | Kapitel Datenbankjobs |
| Topic Daten in Fußzeile ausgeben | Kapitel Datenbankjobs |
|
Es können wie folgt Daten aus einer Tabelle in der Fußzeile (Footer) ausgegeben werden: .Report .Prolog .Header .Var sStr = TABELLE.Feld1 + " : " + Str(TABELLE.Laufende_Nummer) .. .Footer $(@a10n sStr C_Form ToMargin)
|
| Topic Job-Vorlage: Generelle Version | Kapitel Datenbankjobs |
|
.Report ..#Datei: ..#TABLJxxx.JOB fuer Datenbank TABELLE.DAT ..#Hinweise: ..#TABELLE ersetzen durch richtige Tabellennamen ..#SELEKTION erweitern ..#HEADER ersetzen ..#Erstellt: ..#tt.mm.jjjj Autor .. .Prolog .MT 3, PO 5 .FONT a8n = Arial, 8, n .FONT a10n = Arial, 10, n .FONT a10i = Arial, 10, i .FONT a10b = Arial, 10, b .FONT a10u = Arial, 10, u .FONT a12b = Arial, 12, b .FONT a12n = Arial, 12, n .FONT a14b = Arial, 14, b .FONT a14bu = Arial, 14, bu .FONT a16b = Arial, 16, b .FONT a16bi = Arial, 16, bi .FONT a24bi = Arial, 24, bi .. .PRIMTABLEIS TABELLE .. .ZUGRIFF TABELLE.ID .SELEKTION .. .. Header ohne Deckblatt .HE 1 .Header $(@a10n "Projektname") ..HEADER ersetzen $(@a16bi HEADER C_Form ToMargin) .HL .Footer .HL $(@a10n "Detailinformationen, ausgegeben am " + $heute + " um " +$jetzt) $("Seite "+$Seite R_Form ToMargin ) .. .Daten $(/) .Epilog
|
| Topic Aktueller Datensatz ausgeben | Kapitel Datenbankjobs |
|
Immer wieder kommt das Problem der Ausgabe des aktuellen Datensatzes. Folgender Abschnitt im PROLOG-Teil ermöglich die Ausgabe des aktuellen Datensatzes im Formular (Beispiel Tabelle PROJEKT): ..Datenbankjob .Prolog .Do ReadRec(PROJEKT, RecNr(PROJEKT) ) .Var nLN = PROJEKT.Laufende_Nummer .Selection Laufende_Nummer = nLN
|
| Topic Job-Vorlage: HTML-Job mit Tabellen | Kapitel Datenbankjobs |
|
.Report ..#Datei: DBJxxx.JOB ..#Beschreibung: ..#HTML Tabellen-Gerüst. .. ..#Hinweise: ..#o DBTAB durch die richtige Tabelle ersetzen ..#o Feld1 bis Feld5 durch die richtige Felder ersetzen ..#o Zugriff und Selektion anpassen ..#o Width, Title und Head anpassen .. ..#Historie: ..#22.02.1997 R.W.B.Linn .. .Prolog ..MT 3, PO 5 .Zugriff DBTAB.ID .Selection .Daten <!--- $DBTAB.Feld1 --> <!DOCTYPE HTML PUBLIC -//W3C//DTD HTML 3.2//EN> <!Datei: xyz.HTM> <html> <head> <title>DBTAB</title> </head> <body bgcolor=white> .. <table border> <caption>DBTAB</caption> .. ..heading setzen <tr> <th width=400 align=left>Feld1</th> <th width=400 align=left>Feld2</th> <th width=400 align=left>Feld3</th> <th width=400 align=left>Feld4</th> <th width=400 align=left>Feld5</th> </tr> ..felder ausgeben .sub <tr> <td width=400 align=left>$DBTAB.Feld1</td> <td width=400 align=left>$DBTAB.Feld2</td> <td width=400 align=left>$DBTAB.Feld3</td> <td width=400 align=left>$DBTAB.Feld4</td> <td width=400 align=left>$DBTAB.Feld5</td> </tr> .endsub </table> </body> </html> .Epilog
|
| Topic Job-Vorlage: HTML-Job mit Listeneinträge | Kapitel Datenbankjobs |
|
.Report ..#Datei: jobname.job ..#Beschreibung: HTML-Datei mit Listeneinträge erstellen ..#Hinweise: Beim Drucken Ausgabe in Datei mit Windowstext wählen ..#Historie: ..#05.03.97 R.W.B.Linn .. .Prolog ..geht leider nicht ..WOHIN "C:\X.HTM" .PRIMTABLEIS PROJEKT .ZUGRIFF PROJEKT.ID ..aktueller Datensatz wählen .Do ReadRec(PROJEKT, RecNr(PROJEKT) ) .Var nLN = PROJEKT.Laufende_Nummer .. Für Tests ..Var nLN = 64 .Selection Laufende_Nummer = nLN .. .. Hauptteil .GROUP PROJEKT.ProjektName[1] .Daten <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.0//EN"> <HTML> <HEAD> $("<TITLE>Projekthistorie " + PROJEKT.ProjektName + "</TITLE>") </HEAD> <BODY BGCOLOR=#00FFFF> $("<H1>Projekthistorie " + PROJEKT.ProjektName + "</H1>") $("<H2>Historie der ProjektÄnderungen</H2>") .. Gibt es Einträge für das Projekt? .If LINK(HISTORIE) = 1 <UL> .SUB ProjektVersion $("<LI> Version: " HISTORIE.ProjektVersion:10 " Datum: "HISTORIE.Wann:15 " Wer: " HISTORIE.Wer:15 "<BR>") ..Memofeld mit PRE ausgeben, weil sonst Umbrüche nicht mehr stimmen. $("<PRE>") $(HISTORIE.Aenderung:70) $("</PRE>") $("<P>") .ENDSUB .Else $("Keine Einträge vorhanden." C_Form ToMargin) .End </UL> .. $("<ADDRESS> Autor: " PROJEKT.AutorName ", " DateStr(ToDay)"</ADDRESS>") </BODY> .Epilog
|
| Topic Job-Vorlage: Aktueller Datensatz ausgeben | Kapitel Datenbankjobs |
|
.Report ..Datei: ..TABLJxxx.JOB fuer Datenbank TABELLE.DAT ..Hinweise: ..TABELLE ersetzen durch richtige Tabellennamen ..SELEKTION erweitern ..HEADER ersetzen ..Erstellt: ..tt.mm.jjjj Autor .. .Prolog .MT 3, PO 5 .FONT a8n = Arial, 8, n .FONT a10n = Arial, 10, n .FONT a10i = Arial, 10, i .FONT a10b = Arial, 10, b .FONT a10u = Arial, 10, u .FONT a12b = Arial, 12, b .FONT a12n = Arial, 12, n .FONT a14b = Arial, 14, b .FONT a14bu = Arial, 14, bu .FONT a16b = Arial, 16, b .FONT a16bi = Arial, 16, bi .FONT a24bi = Arial, 24, bi .. .PRIMTABLEIS TABELLE .. .ZUGRIFF TABELLE.ID .Do ReadRec(TABELLE, RecNr(TABELLE) ) .Var nLN = TABELLE.Laufende_Nummer .. Für Tests ..Var nLN = 145 .Selection Laufende_Nummer = nLN .If nLN = 0 .Do Message("Kein Datensatz vorhanden!", "Fehler") .ST .End .. .. Header ohne Deckblatt .HE 1 .Header $(@a10n "Projektname") $(@a16bi HEADER C_Form ToMargin) .HL .Footer .HL $(@a10n "Detailinformationen, ausgegeben am " + $heute + " um " +$jetzt) $("Seite "+$Seite R_Form ToMargin ) .. .Daten $(/) .Epilog
|
| Topic Job-Vorlage: HTML-Job mit gruppierte Ausgabe | Kapitel Datenbankjobs |
|
.Report ..#Beispiel: Gruppierte Ausgabe von Datensaetze in HTML-Format ..#Autor: R.W.B.Linn 18.03.1997 .. .Prolog .GP 1 .Zugriff TEST2.ID ..Ruecksprungadresse setzen $("<A NAME='TOP'") ..aufbau des alphabetes .Var i = 0 .While i < 26 $(" <A HREF='#"+Chr(65 + i)+"'>"+Chr(65 + i)+"</a>") .Do i := i + 1 .End $("<HR>") .. .Header .. .Footer .Gruppe Name[1] ..ausgabe der gruppen-buchstabe $("<A HREF='#TOP'>Zurück</A>") $("<A NAME='"+G_Neu+"'><H1>"+G_Neu+"</H1></A>") .. .Daten ..der eigentliche inhalt $(Name+"<BR>")
|
| Topic Subreport sortieren | Kapitel Datenbankjobs |
|
Wenn die Ausgabe über SUB läuft, hinter ENDSUB eine Indexbeschreibung angeben. Beispiel: .Sub $Name, $Ort .Endsub "Name, Ort"
|
| Topic Schriftarten in Jobs definieren | Kapitel Datenbankjobs |
|
Im Prolog werden Schriftarten mit dem Punktbefehl .FONT definiert. Verwendet werden die definierte Schriftarten mit .SETFONT. Beispiel: .Prolog .Font arial_klein = Arial,9,n .Font arial_gross = arial,16,b .Daten .SetFont arial_gross Hier eine Überschrift .SetFont arial_klein Hier normaler Text .Epilog
|
| Topic Zeilenumbruch wenn weniger als nn Zeilen frei | Kapitel Datenbankjobs |
|
Anzahl Zeilen mit .LET in eine Variable ablegen und diese Variable dannan .CP übergeben. Da man Punktkommandos nicht mit Variablen aufrufen kann, gibt es die Funktion SETPARA. Beispiel: SETPARA("CP " + Str(nVar)) wobei nVar die Variable ist.
|
| Topic Selektion eingeben | Kapitel Datenbankjobs |
|
Über einen JOB oder MAKRO eine Liste drucken, bei der die Bedingung für die Selektion vom Anwender selbst eingegeben werden kann. Makro schreiben: Input ("Selektion:","Frage") SUB _T-Eingabe SetMark (FileNo, RecNo (FileNo)) ENDSUB Name, Vorname SetSortOrder ("Markierung") Run ("Liste") ...bzw. 'Liste' druckt nur markierte Datensaetze.
|
| Topic Selektiver Listendruck | Kapitel Datenbankjobs |
|
Frage: Wie kann ein selektiver Berichts- oder Listenausdruck erfolgen? Antwort: Im Bericht "Berichtsname" bei der Datensatzauswahl lediglich NOTE eingeben. Bericht dann speichern. Ein Makro erstellen: Input("Kriterium eingeben") Note(T-Eingabe) Drucken("Berichtsname")
|
| Topic Abfrage der Funktion EINGABE | Kapitel Datenbankjobs |
|
Frage: In Datenbankjobs kann man mit der Funktion EINGABE ein Fenster für dieEingabe einer Auswahl öffnen. Das Fenster hat zwei Funktionsknöpfe: OK / Abruch. Wie kann man den Abruch des Fensters abfragen ? Antwort: Folgendes Beispiel zeigt eine Möglichkeit: .Let T-Eingabe = "Voreinstellung" .Let nRT = Input ("Bitte Text eingeben","Abfrage") ..nRT auswerten, wenn 0 dann abbrechen, z.B. mittels ST (=Stop) Befehl .If nRT = 0 ..Abbruch .ST .Else ..Hier weitermachen .End
|
| Topic Ausgabe von Bildfelder in Datenbankjobs | Kapitel Datenbankjobs |
|
Ausgabe von Bildfelder in Datenbankjobs $(TABELLE.Bildfeld:Breite:Hoehe:Textversatz) Höhe und Textversatz muessen nicht angegeben werden, dann wird das Bild automatisch angepasst. Ist das Bild nicht vorhanden, erfolgt auch keine leere Ausgabe.
|
| Topic Fontdatei für Schriftarten in Datenbankjobs | Kapitel Datenbankjobs |
|
Mittels dem Kommando Font können Schriftarten definiert werden. Beispiel: .FONT a10n = Arial, 10, n Es ist für die Entwicklung von Datenbankjobs hilfreich alle Fonts die benötigt werden in eine separate Textdatei abzulegen und diese mittels dem Include-Befehl als Textbaustein zu laden. Beispiel: INCLUDE FONTDEF.TXT Inhalt der Datei Fontdef.txt: ..Datei: fontdef.txt ..Definition von Standardfonts für Datenbankjobs .FONT a8n = Arial, 8, n .FONT a10n = Arial, 10, n .FONT a10i = Arial, 10, i .FONT a10b = Arial, 10, b .FONT a10u = Arial, 10, u .FONT a12b = Arial, 12, b .FONT a12n = Arial, 12, n .FONT a12bu = Arial, 12, bu .FONT a14n = Arial, 14, n .FONT a14b = Arial, 14, b .FONT a14bu = Arial, 14, bu .FONT a16b = Arial, 16, b .FONT a16bi = Arial, 16, bi .FONT a24bi = Arial, 24, bi
|
| Topic Druckziel festlegen | Kapitel Datenbankjobs |
|
Bei der Ausführung von Datenbankjobs können verschiedene Druckziele, wie Druckvorschau, Drucker oder Ausgabe in eine Datei, festgelegt werden. Bei der Entwicklung von Datenbankjobs, kann mittels STRG-F9, der Job kompiliert und ausgeführt werden. Das Druckziel ist in der Regel, die Druckvorschau. Es besteht aber auch dieMöglichkeit, die Ausgabe in eine Datei oder direkt auf dem Drucker zu steuern. Hierzu muß der Datenbankjob einmal vom Hauptformular mittels "Ausführen, Jobname, Druckzielangeben", ausgeführt werden.
|
| Topic Eine erste Seite ohne Kopf und Fuß definieren | Kapitel Datenbankjobs |
|
In einem Datenbankjob kann eine erste Seite ohne Kopf- (Header) und Fußzeile (Footer) definiert werden. Hierzu die Angaben vor dem .KOPF (.HEADING) und/oder .FUß (.FOOTER) setzen. Es können auch Punkbefehle, wie .PA (=Seitenumbruch) verwendet werden. Ebenso dieMöglichkeit von easy-Abschnitte, wie .Do Firstrec(TABELLE) .While .... $(TABELLE.Feld1) .Do NextRec(TABELLE) .End
|
| Topic Ausgabe in eine RTF-Datei | Kapitel Datenbankjobs |
|
Nachfolgend ein Beispiel wie aus ein Datenbankjob eine RTF-Ausgabe erfolgt. Das Beispiel stammt aus der VDP Anwendung KAL. .Report ..#Datei: TOPLJ001.JOB fuer Datenbank TOPICS.DAT ..#Beschreibung: ..#ausgabe des aktuellen topics in eine RTF-Datei ..#Historie: ..#24.03.1999 R.W.B.Linn Erstellt .. .Include \daten\vdp\vdp2\kal\jobfonts.inc .Prolog .. .PRIMTABLEIS TOPICS .ZUGRIFF TOPICS.ID .. ..lese aktuelles record .Var nLN = 0 .Var nRNo = 0 .Do nRNo := ReadRec(TOPICS, RecNr(TOPICS)) .If nRNo = 0 .Do Message("Kein Topic gefunden!", "Fehler") .ST .End .Do nLN := TOPICS.Laufende_Nummer .Selection TOPICS.Laufende_Nummer = nLN .. .Var nRNo = 0 .Do nRNo := ReadRec(SYSTEM, 1) .If nRNo = 0 .Do Message("Keine Systemvorgaben gefunden!", "Fehler") .End .. ..// R T F -P R O C E D U R E N .Var nRT = 0 .Var sFile = "topic.rtf" .Do T-Eingabe := sFile .Do nRT := Input("Bitte RTF-Dateiname eingeben", "Frage"); .If nRT = 0 .ST .End .If Upper(T-Eingabe) hat ".RTF" .Else .Do T-Eingabe := T-Eingabe + ".rtf" .End .Do sFile := KAPITEL.kThema.sHTMLVerzeichnis + T-Eingabe ..#tempdatei für memos .Var sMemoFile = KAPITEL.kThema.sHTMLVerzeichnis + "memo.tmp" .Var nFH = 0 .. .Procedure RTFFileCreate ..#legt die rtf-datei an .VarDef nFH : Real; .. .If nFH :=Rewrite(sFile) .Do WriteLn(nFH, "{\rtf1\ansi \deff0\deflang1024{\fonttbl{\f0\fmodernCourier New;}}") .Do WriteLn(nFH, "{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;}") .Do WriteLn(nFH, "{\info {\author r.w.b.linn}}") .Do WriteLn(nFH, "\paperw11906\paperh16838\margl1417\margr1417\margt1417\margb1134\gutter0") .Do Close(nFH) .Else .Do Message(sFile + " kann nicht erzeugt werden","Fehler",1) .End .Endproc .. .Procedure RTFFileAppend(sLine : String; nHdg : Real; nCRLF : Real) ..#hängt eine zeile oder zeichen an eine vorhandene rtf-datei .VarDef nFH : Real; .Do nFH := TAppend(sFile) .If nFH > 0 .If nHdg = 1 .Do WriteLn(nFH, "\f0\fs32\keepn \b " + sLine + " \b0 \par \pard\par\f0\fs20") .Else .If nCRLF = 0 .Do Write(nFH, sLine) .Else .Do WriteLn(nFH, sLine + "\par") .End .End .Do Close(nFH); .End .Endproc .. .Procedure RTFFileAppendMemo ..#liest eine memo datei die vorher mittels ..#copymemo angelegt wurde .Vardef nFH, nFHM : Real; .Vardef c : String; .. .If IsFile(sMemoFile) = 0 .Return .End .Do nFHM := Reset(sMemoFile) .Do nFH := TAppend(sFile) .If nFH > 0 .While Not Eot(nFHM) .Do c := Read(nFHM, 1) .If Asc(c) = 10 .Do Write(nFH, "\par ") .Else .If Asc(c) <> 13 .Do Write(nFH, c) .End .End .End .Do Close(nFH); .Do Close(nFHM); .End .Endproc .. .Procedure RTFFileClose .VarDef nFH : Real; .. .Do nFH := TAppend(sFile) .If nFH > 0 .Do WriteLn(nFH, "}") .Do Close(nFH); .End .Endproc .. ..// R T F -F I L E C R E A T E .Do RTFFileCreate ..// H E A DE R .Header .Do RTFFileAppend("Topic: " + TOPICS.tThema.sThema, 1, 1) .. .Footer ..Include \daten\vdp\vdp2\kal\jobftr.inc .. .Var x = 0 .Daten .Do ShowWait("Bitte warten...") .Do x := TOPICS.Laufende_Nummer .Do RTFFileAppend("Thema:" + TOPICS.tThema.sThema, 0, 1) .Do RTFFileAppend("Kapitel:" + TOPICS.tKapitel.kKapitel, 0, 1) .Do RTFFileAppend("Datum:" + DateStr(TOPICS.tDatum), 0, 1) .Do RTFFileAppend("", 0, 1) .Do RTFFileAppend("Inhalt", 0, 1) .Do CopyMemo(TOPICS.tInhalt, sMemoFile) .Do RTFFileAppendMemo .Do DelFile(sMemoFile) .Do RTFFileAppend("", 0, 1) .Do RTFFileAppend("Stichworte", 0, 1) .Sub .Do RTFFileAppend(TOPICS.tStichwort.wStichwort, 0, 1) .Endsub .. .Epilog .Do RTFFileClose .Do DelFile(sMemoFile) .Do HideWait .If IsFile(sFile) .Do Message(sFile + " erstellt.", "Hinweis") .Else .Do Message(sFile + " konnte nicht erstellt werden.", "Hinweis") .End .ST ..
|
| Topic Job-Vorlage: Überweisungsformular | Kapitel Datenbankjobs |
|
Beispiel eines Überweisungsformulars mit Vordrucken für Quicken/QuickenBooks. Mit Dank an Hr.Streibert (Konstanz) .REPORT ..Überweisungsformular drucken mit den Vordrucken fürQuicken/QuickenBooks .PROLOG .FONT a12n = Arial, 12, n .MM 10 $(@a12n) ..Überweisungsauftrag .Do GotoXY(70, 22) $(SYSTEM.Firma) .Do GotoXY(70, 31) $(SYSTEM.Kto:96 SYSTEM.BLZ) .Do GotoXY(70, 39) $SYSTEM.Bank .Do GotoXY(70, 48) $(" DM "+ISS.gpm) .Do GotoXY(70, 56) Verwendungszweck vom $heute, .Do GotoXY(70, 65) für $ISS.Name, $ISS.Vorname ..Beleg für Kontoinhaber .Do GotoXY(70, 130) $(SYSTEM.Firma) .Do GotoXY(70, 138) $(SYSTEM.Kto:96 SYSTEM.BLZ) .Do GotoXY(70, 146) $SYSTEM.Bank .Do GotoXY(70, 154) $(" DM "+ISS.gpm) .Do GotoXY(70, 163) Verwendungszweck vom $heute, .Do GotoXY(70, 171) für $ISS.Name, $ISS.Vorname ___
|
| Topic Job-Vorlage: Generelle Version mit Include-Beispiele | Kapitel Datenbankjobs |
|
.Report ..#Diese Vorlage verwendet drei Include-Befehle für die Fontdatei, den Header und Footer ..#Der Vorteil diese Methode ist, daß Sie nur Änderungen in den Include-Dateien ..#vornehmen müßen um alle Datenbankjobs anzupassen ..#Mittels eines easy-Moduls könne alle Jobs neu übersetzt werden. ..#Siehe <Job- und Module-Kompilierungsprozedure> ..#10.10.1999 R.W.B.Linn .Prolog .PRIMTABLEIS TABELLE .ZUGRIFF TABELLE.IND .Include \daten\vdp\projekt\jobfonts.inc .. ..Systemvorgaben lesen .Var nRNo = 0 .Do nRNo := ReadRec(SYSTEM, 1) .If nRNo = 0 .Do Message("Keine Systemvorgaben gefunden!", "Fehler") .ST .End .. ..#Seiteneinstellungen .DO SetPara(".MT "+STR(SYSTEM.JobMT)+", PO "+STR(SYSTEM.JobPO)+", MR"+STR(SYSTEM.JobMR)) .Selection Ihre Selection .. ..#Definition der Variabelen .Var ULine20 = xMal("_",20) .Var ULine40 = xMal("_",40) .Var i = 0 .Var j = 0 .. .HE 1 .Header .Include \daten\vdp\projekt\jobhdr.inc $(@a12b "Überschrift vom " + DateStr(ToDay) C_Form ToMargin) .. .Footer .Include \daten\vdp\projekt\jobftr.inc .. .Daten .. .. .Epilog ..
|
| Topic Prozeduren in Jobs definieren | Kapitel Datenbankjobs |
|
In Datenbankjobs können easy-Prozeduren definiert werden. Folgendes Beispiel zeigt eine easy Routine der in einem Array nach ein Artikel sucht. Der Rückgabewert ist die gefundene Artikelnummer oder 0 wenn nicht gefunden. .Procedure SearchArtikel(nNo : Real) : Real; ..#sucht ein Artikel .Vardef i : Real .Do i := 1 .While i <= nACnt + 1 .If anArtikel[i] = nNo .Return i .End .Do i := i + 1 .End .Return 0 .Endproc .. ..#Aufruf im Datenbereich ..#Es wird anhand eines Artikelnummers in ein Array gesucht. ..#Das Ergebnis wird in ein zweidiemensionales Array übertragen. .Daten .Sub .Do i := SearchArtikel(FSArtikel.Laufende_Nummer) ..If i > 0 And j > 0 .Do anKArtikel[i,j] := FSArtikel.VkPreis .Endsub .. .Epilog
|
| Topic Nummerierung bei Gruppenausgabe | Kapitel Datenbankjobs |
|
Folgenden Abschnitt zeigt, wie eine fortlaufende Nummerierung bei einer Gruppenausgabe erfolgen kann. Eine gruppierte Ausgabe mit fortlaufenden Nummerierung sieht wie folgt aus (Beispiel): Nr. Artikel Anzahl 1 Artikel 1 5 2 Artikel 2 8 3 Artikel 3 10 ..#Code im Datenbankjob ..#Tabelle POSTEN hält die Artikel. Die Artikel sind in eine TabelleARTSTAMM definiert ..# .GP 0 .Var nCnt = 0 .Var G_akt = "" .Var G_alt = "" .Var nSumArt = 0 .Do G_akt := G_alt .Group POSTEN.PArtikelNr.Artikel .. .If G_alt <> G_akt .Do G_akt := G_alt .Do nSumArt := 0 .End $(@a8n Str(nCnt := nCnt + 1, 1,0):10 + " " + "":20 + " " + G_alt:60! +" " + Str(ZSum(POSTEN.PMenge), 1, 2) r 20 + " " + "":20 + " " +Str(ZSum(POSTEN.PBrutto),1,2) r 20) .Do nSumArt := nSumArt + ZSum(POSTEN.PBrutto)
|
| Topic Ausgabe von Bitmaps die nicht in der Datenbank gespeichert sind | Kapitel Datenbankjobs |
|
Die Ausgabe mittels ein Datenbankjob von Bitmaps (GIF und BMP) die nicht in der Datenbank gespeichert sind ist wie folgt möglich: 1.In eine System-Tabelle muß ein Feld vom Typ Bild/Klang definiert werden. Beispiel: TempBMP 2.Im Datenbankjob nachfolgendes Programmfragment definieren. Es könnte auch mittels eine Prozedur im Job erfolgen. ..Variabelen definieren ..Dateiname des Bitmaps speichern .Var sBild1 = "" ..für Tempstrings .Var sTmp1 = "" ..Filehandle für Bitmap-Datei .Var nFH1 = 0 ..w1 = breite, h1 = höhe, t1 = textversatz .Var w1 = 0 .Var h1 = 0 .Var t1 = 0 .. ..hier die Übergabe des Bildes beschreiben .Do sBild1 := "meinbild.gif" .. ..GIF = Compuserve-Format .If Upper(sBild1) Hat ".GIF" .Do LinkBlob(SYSTEM.TmpBMP, sBild1, 5) ..öffne gif-Datei und ermittle Width (an Pos 7) und Heigth (an Pos 9) .Do nFH1 := Reset(sBild1) .If nFH1 > 0 .Do Read(nFH1, 6) .Do w1 := ASC(Read(nFH1, 1)) .Do Read(nFH1, 1) .Do h1 := ASC(Read(nFH1, 1)) .Do Close(nFH1) .End ..ende if bild ist GIF .End .. ..BMP = Bitmap .If Upper(sBild1) Hat ".BMP" .Do LinkBlob(SYSTEM.TmpBMP, sBild1, 1) ..öffne gif-Datei und ermittle Width (an Pos 19) und Heigth (an Pos 23) .Do nFH1 := Reset(sBild1) .If nFH1 > 0 .Do Read(nFH1, 18) .Do w1 := ASC(Read(nFH1, 1)) .Do Read(nFH1, 3) .Do h1 := ASC(Read(nFH1, 1)) .Do Close(nFH1) .End ..bitmap .End .. ..für Tests ..Do Message(GetLinkedFile(SYSTEM.TmpBMP),Str(BlobSize(SYSTEM.TmpBMP))) ..gebe erst mal text aus (nur als Beispiel) .Do Print("Mein Bild:" + " ") ..Bitmap ausgeben, dabei ist der Textversatz 0 ..die Ausgabe erfolgt dynamisch .Do _"Print(SYSTEM.TmpBMP:"+Str(w1)+":"+Str(h1)+":"+Str(t1)+ "' ')" ..berechne Anzahl Zeilenumbüche .Do sTmp1 := nTimes("/", h1 div 5) .Do _"Print("+sTmp1+")"
|
| Topic Datenbankjobausgabe in eine RTF-Datei | Kapitel Datenbankjobs |
|
Beispiel eines Datenbankjobs dessen Ausgabe in eine RTF-Datei umgeleitet wird. .Report ..#Datei: KAPLJ002.JOB fuer Datenbank KAPITEL.DAT ..#Beschreibung: ..#ausgabe des aktuellen kapitels+topics in eine rtf-datei ..#Historie: ..#06.06.1999 R.W.B.Linn Erstellt .. .Include \daten\vdp\vdp2\kal\jobfonts.inc .Prolog .. .PRIMTABLEIS KAPITEL .ZUGRIFF KAPITEL.ID .. ..lese aktuelles record .Var nLN = 0 .Var nRNo = 0 .Do nRNo := ReadRec(KAPITEL, RecNr(KAPITEL)) .If nRNo = 0 .Do Message("Kein Kapitel gefunden!", "Fehler") .ST .End .Do nLN := KAPITEL.Laufende_Nummer .Selection KAPITEL.Laufende_Nummer = nLN .. .Var nRNo = 0 .Do nRNo := ReadRec(SYSTEM, 1) .If nRNo = 0 .Do Message("Keine Systemvorgaben gefunden!", "Fehler") .End .. ..// R T F -P R O C E D U R E N .Var nRT = 0 .Var sFile = "kapitel.rtf" .Do T-Eingabe := sFile .Do nRT := Input("Bitte RTF-Dateiname eingeben", "Frage"); .If nRT = 0 .ST .End .If Upper(T-Eingabe) hat ".RTF" .Else .Do T-Eingabe := T-Eingabe + ".rtf" .End .Do sFile := KAPITEL.kThema.sHTMLVerzeichnis + T-Eingabe ..#tempdatei für memos .Var sMemoFile = KAPITEL.kThema.sHTMLVerzeichnis + "memo.tmp" .Var nFH = 0 .. .Procedure RTFFileCreate ..#legt die rtf-datei an .VarDef nFH : Real; .. .If nFH :=Rewrite(sFile) .Do WriteLn(nFH, "{\rtf1\ansi \deff0\deflang1024{\fonttbl{\f0\fmodernCourier New;}}") .Do WriteLn(nFH, "{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;}") .Do WriteLn(nFH, "{\info {\author r.w.b.linn}}") .Do WriteLn(nFH, "\paperw11906\paperh16838\margl1417\margr1417\margt1417\margb1134\gutter0") .Do Close(nFH) .Else .Do Message(sFile + " kann nicht erzeugt werden","Fehler",1) .End .Endproc .. .Procedure RTFFileAppend(sLine : String; nHdg : Real; nCRLF : Real) ..#hängt eine zeile oder zeichen an eine vorhandene rtf-datei .VarDef nFH : Real; .Do nFH := TAppend(sFile) .If nFH > 0 .If nHdg = 1 .Do WriteLn(nFH, "\f0\fs32\keepn \b " + sLine + " \b0 \par \pard\par\f0\fs20") .Else .If nCRLF = 0 .Do Write(nFH, sLine) .Else .Do WriteLn(nFH, sLine + "\par") .End .End .Do Close(nFH); .End .Endproc .. .Procedure RTFFileAppendMemo ..#liest eine memo datei die vorher mittels ..#copymemo angelegt wurde .Vardef nFH, nFHM : Real; .Vardef c : String; .. .If IsFile(sMemoFile) = 0 .Return .End .Do nFHM := Reset(sMemoFile) .Do nFH := TAppend(sFile) .If nFH > 0 .While Not Eot(nFHM) .Do c := Read(nFHM, 1) .If Asc(c) = 10 .Do Write(nFH, "\par ") .Else .If Asc(c) <> 13 .Do Write(nFH, c) .End .End .End .Do Close(nFH); .Do Close(nFHM); .End .Endproc .. .Procedure RTFFileClose .VarDef nFH : Real; .. .Do nFH := TAppend(sFile) .If nFH > 0 .Do WriteLn(nFH, "}") .Do Close(nFH); .End .Endproc .. ..// R T F -F I L E C R E A T E .Do RTFFileCreate ..// H E A DE R .Header ..Include \daten\vdp\vdp2\kal\jobhdr.inc .Do RTFFileAppend("Kapitel: " + KAPITEL.kKapitel, 1, 1) .. ..// F O O TE R .Footer ..Include \daten\vdp\vdp2\kal\jobftr.inc .. .Var x = 0 .Daten .Do ShowWait("Bitte warten...") .Do x := KAPITEL.Laufende_Nummer .Do RTFFileAppend("Thema:" + KAPITEL.kThema.sThema, 0, 1) .Do RTFFileAppend("Inhalt:" + KAPITEL.kKapitel, 0, 1) .Do RTFFileAppend("Datum:" + DateStr(KAPITEL.kDatum), 0, 1) .Do RTFFileAppend("Inhalt:", 0, 1) .Do RTFFileAppend(KAPITEL.kInhalt, 0, 1) .Do RTFFileAppend("", 0, 1) .Do RTFFileAppend("Topic(s)", 0, 1) .Sub TOPICS .Do RTFFileAppend(TOPICS.tTitel, 0, 1) .Do CopyMemo(TOPICS.tInhalt, sMemoFile) .Do RTFFileAppendMemo .Do DelFile(sMemoFile) .Endsub .. .Epilog .Do RTFFileClose .Do DelFile(sMemoFile) .Do HideWait .If IsFile(sFile) .Do Message(sFile + " erstellt.", "Hinweis") .Else .Do Message(sFile + " konnte nicht erstellt werden.", "Hinweis") .End .ST ..
|
| Topic Rahmen im Druckjobs | Kapitel Datenbankjobs |
|
Tip 1 $(@a8b "Rahmen") ..150 ist die breite. Der Rahmen enthällt 3 Leerzeilen. .VL 150, VL, HL $(@a10n "") $(@a10n "") $(@a10n "") .HL .EVL .. Tip 2 Folgender Druckjob zieht genau die gewünschten Linien zur Darstellung eines Rahmens. Im Datenbereich kann dann in die Rahmen hinein gedruckt werden. .REPORT .PROLOG .MM 1 .MT 200, PO 100, MR 50 .DEF Rahmenhöhe=450 .DEF Rahmenbreite=600 .PROCEDURE Rahmenziehen(x, y : REAL) .DO GotoXY(0,y) .Do SetPara("PO "+STR(150+x)) .Do SetPara("VL "+STR(Rahmenbreite)+",VL "+STR(Rahmenbreite)+",VL "+STR(Rahmenbreite)+",VL,HL") .REPEAT .DO GotoXY( x, WhereY +Rahmenhöhe) .HL .UNTIL WhereY > 2400 .EVL .ENDPROC .DO Rahmenziehen(0, 150) .DO Rahmenziehen(0, 152) .DO Rahmenziehen(0, 154) .DO Rahmenziehen(1, 150) .DO Rahmenziehen(2, 150) .DO Rahmenziehen(3, 150) .DATEN .EPILOG
|
| Topic Ja/Nein-Felder in Berichten grafisch darstellen | Kapitel Datenbankjobs |
|
Tipp 1 In Berichten: Ein Element vom Typ FORMEL definieren. Das Element den Font z.B. WINGDINGS zuweisen. Die Formel wie folgt aufbauen: CHOICE(Ja_Nein_Feld,CHAR(0254),"o") oder CHOICE(Ja_Nein_Feld,CHAR(0231),"o") Das Ergebnis ist einen Kasten mit Haken bzw. einen leeren Kasten. Tipp 2 In Datenbankjobs: Ein Font z.B. WINGDINGS erstellen. Ausgabe des Feldes: $(@myfont CHOICE(Ja_Nein_Feld,CHAR(0254),"o")) Das Ergebnis ist einen Kasten mit Haken bzw. einen leeren Kasten. Tipp 3 In Datenbankjobs oder Berichten: In eine Systemtabelle zwei Bild-Felder für ein JA- und ein NEIN-Bitmap definieren. Beispiel: BildJA und BildNEIN Die Bildfelder mit Bitmap-Dateien einbetten. Empfehlung für die Bitmap-Dateien ist: Grösse: 10*10 Pixel, VGA 16 Farben Beispiel Datenbankjob: Ausgabe des Bildfeldes: .Prolog ..System Satz lesen. Die Systemtabelle enthält nur ein Datensatz. .Do ReadRec(System,1) .Daten .If JA JA: $($SYSTEM.BildJA:2:1:0) .End .If NEIN NEIN: $($SYSTEM.BildNEIN:2:1:0) .End
|
| Topic Verknüpfung in SUB-Reports | Kapitel Datenbankjobs |
|
Bei geschaltelten SUB-Reports wird absolut nur der durch den SUB-Report vorgegebene Verknüpfung berücksichtigt. Wichtig ist allerdings, daß innerhalb des SUB-Report kein Zugriff auf eine andere Tabelle erfolgt, es sein denn über die Link-Notation. Verwende bei Feldzugriffen immer den vollen Pfad, also nicht Name sondern ADRESSEN.Name Oder nicht nur Betrag, sondern POSITION.Betrag Bei diesem Beispiel ist klar, welche Datensätze ausgegeben werden: ReadRec( ADRESSEN, RecNr(ADRESSEN)) SUB RECHNUNG Showwait(RECHNUNG.RechNr) SUB POSITION n := n+POSITION.Betrag ENDSUB ENDSUB Hier wird es schon sehr diffus: ReadRec( ADRESSEN, RecNr(ADRESSEN)) SUB RECHNUNG Showwait(RECHNUNG.RechNr) SUB POSITION n := n+POSITION.Betrag Showwait(KUNDEN.Rabatt) ENDSUB ENDSUB Hier erfolgt nämlich innerhalb des 2. SUP-Reports ein Zugriff auf eineexterne Tabelle und in diesem Fall können Positionen zurAusgabe kommen, die überhaupt nicht zur Rechnung gehören. VDP weißt in diesen Fällen auch die Sortierung der Datensätze beiSUB-Reports ab. So ist es richtig: ReadRec( ADRESSEN, RecNr(ADRESSEN)) SUB RECHNUNG Showwait(RECHNUNG.RechNr) SUB POSITION IF POSITION.Rechnung.Kunde.MwSt-Frei=0 n := POSITION.Betrag* 1.16 END n := n+POSITION.Betrag ENDSUB POSITION.Datum ENDSUB und so falsch: ReadRec( ADRESSEN, RecNr(ADRESSEN)) SUB RECHNUNG Showwait(RECHNUNG.RechNr) SUB POSITION IF ADRESSEN.MwSt-Frei=0 n := POSITION.Betrag* 1.16 END n := n+POSITION.Betrag ENDSUB POSITION.Datum ENDSUB VDP wird in diesem Fall die SUP-Report Ausgabe über die Positioneventuell nicht korrekt ausgeben und außerdem dieSortieranweisung nach ENDSUB mit einer Fehlermeldung quitieren.
|
| Topic Seitenumbruch bei Gruppierung in einem Bericht | Kapitel Datenbankjobs |
|
Problem: Wenn ein Datensatz kurz vor Seitenende beginnt, d.h. die Gruppierung kommt noch auf das Seitenende, aber die dazugehörigen Daten landen auf der nächsten Seite, ohne aber die Gruppierung zu wiederholen, oder ein Teil der Datensätze kommt noch auf das erste Blatt und der Rest wird ohne Gruppe auf der nächsten Seite gedruckt. Lösungsmöglichkeiten: Tip 1 In der Gruppendefinition den Punktbefehl .PA (neue Seite) verwenden .GP 1 .Gruppe Upper(Name[1]) .PA $(@a12b G_Neu Bold(0) ) .Daten Tip 2 In der Gruppendefinition den Punktbefehl .CP nn verwenden. Bei nn ist 10 findet ein Seitenumbruch wenn weniger als 10 Zeilen auf der Seite frei sind: .GP 1 .Gruppe Upper(Name[1]) .CP 10 $(@a12b G_Neu Bold(0) ) .Daten Tip 3 .GP 1 .Gruppe Upper(Name[1]) ..Anzeige Anzahl Datensätze nach der Ausgabe des Gruppenteiles .If ZCount(Name) > 0 $(@a12b + "Datensätze " + Str(ZCount(Name))) .End .CP 10 $(@a12b G_Neu Bold(0) ) .Daten Sie können auf mit dem VDP internen Befehl $Zeile arbeiten.
|
| Topic Zentrierter Text | Kapitel Datenbankjobs |
|
Die Funktion C_Form ermöglicht eine zentrierte Darstellung in eine Zeile. Beispiel: $("Mein Text" C_Form 50) ergibt eine zentrierte Ausgabe von Mein Text in einem 50 Zeichen breiten Bereich.
|
| Topic Aufruf Prozeduren im Datenbankjob | Kapitel Datenbankjobs |
|
Aufruf Prozeduren im Datenbankjob Frage: Kann eine Prozedur, die einen String zurückgibt, in einem Datenbankjob einsetzen werden, um den String ausgeben zu können? Antwort: Es funktioniert mit einem Aufrauf der externen Prozedur im Ausgabeformat: $(Procedur(Parameter):20) Prozeduren ohne Rückgabewert können mit .DO _"Procedur(Parameter)" aufgerufen werden.
|
| Topic Ausgabe Gruppensumme | Kapitel Datenbankjobs |
|
Um eine Gruppensumme auszugeben ist der Berichtsaufbau wie folgt: Header Prolog Gruppen-Definition Datenbereich Footer Im Prolog Bereich eine Variable definiren und diese direkt einen Wert zuweisen. Beispiel Variable: .Prolog .Def nGruppensumme = Sum(TABELLE.Feld1) Die Variable im Footer Bereich ausgeben. Beispiel: .Footer $("Summe: " + Str(nGruppensumme) Weitere summierungen etc. sind auch möglich. Beispiel: .Prolog .Def nGruppeneintraege = Count(TABELLE.Feld1) .Footer "Anzahl Gruppeneinträge: " + Str(nGruppeneintraege)
|
| Topic Zählen von angekoppelte Datensätze | Kapitel Datenbankjobs |
|
Beispiel: wobei BESTAND die angekoppelte Tabelle ist. Das Feld "material" der Haupttabelle ist ein Relationsfeld auf die Tabelle BESTAND $1 .Var nCnt = 0 .Sub BESTAND .Do nCnt := nCnt + 1 $material.1 .Endsub ========= Total: $nCnt
|
| Topic Moduldarstellung in der Makroliste | Kapitel easy Allgemeine Hinweise |
|
In der Makroliste werden deshalb nur die Makros des ersten Moduls dargestellt, damit Sie eine Auswahlmöglichkeit haben. Die Makros aus anderen Modulen können von den Makros des ersten Modulsaus aufgerufen werden.
|
| Topic Datensatz mittels Laufende Nummer suchen | Kapitel easy Allgemeine Hinweise |
|
Beispiel: Vardef nSatz : Real; nSatz := FindRec(TABELLE, Str(Laufende_Nummer), "TABELLE.INR", 1); Ist nSatz > 0 dann wurde der Datensatz gefunden. Diese kann dann mit ReadRec(TABELLE, nSatz) gelesen werden.
|
| Topic Bilder/Sounds einlesen | Kapitel easy Allgemeine Hinweise |
|
Vor allem bei Bilder ist es sehr schön, daß man sie statt über einen Button (der ein eigenes Bildfenster öffnet) direkt in das Formular integrieren kann. Der Nachteil besteht darin, daß sich Bilder nicht mehr so einfach einlesen lassen. Die einfachste Lösung: Plazieren Sie das Bildfeld einfach zwei mal indas Formular: einmal direkt und einmal als Button. Für eine noch elegantere Bild-Lesen-Funktion müssen Sie ein kleines Makro schreiben. Das könnte beispielsweise so aussehen: Procedure Bild_laden T-Eingabe:="*.BMP"; IF ChooseFile("Vogelbild laden") IF T-Eingabe LinkBlob(Foto,T-Eingabe,1); Attach END END Endproc Erklärung: Mit ChooseFile wird ein komfortabler Dateiauswahl-Dialog aufgerufen. Das Ergebnis der Dateiauswahl wird in die Systemvariable T-Eingabe geschrieben. Zuvor kann man diese Variable initialisieren, sinnvollerweise mit der gesuchten Extension. Die Funktion LinkBlob verknüpft das Bilddatenfeld mit der ausgewählten Datei. Der dritte Parameter (hier 1) gibt an, um welchen Dateityp es sichhandelt. Analog funktioniert das natürlich auch bei Sounddateien. Vor allem in VDP-Anwendungen ist es wichtig, daß in den Datenfeldern für verknüpfte Bilder- und Klangdateien nicht der absolute Pfad (also der komplette Pfadname mit Laufwerksangabe), sondern nur der relative Pfad zum Projektverzeichnis gespeichert wird. Damit bleibt der Endanwender flexibel und kann die Anwendung in jedes gewünschte Verzeichnis installieren. Um dies zu erreichen, ist es besser, die LinkBlob-Funktion ein wenig aufwendiger zu gestalten: LinkBlob(Foto, SubPath(DBDir(FileNo), T-Eingabe), 1)
|
| Topic Meldung "Falsche Programmversion" | Kapitel easy Allgemeine Hinweise |
|
Die Meldung bedeutet, daß das kompilierte Modul nicht zur Programmversion von WinTDB/VDP paßt. Aktion: Modul neu übersetzen (kompilieren).
|
| Topic Report mit Deckblatt | Kapitel easy Allgemeine Hinweise |
|
Bei grosse Reports ist es manchmal sinnvoll einen Deckblatt auszugeben. Folgender Abschnitt definiert einen Deckblatt: .Prolog .FONT a10a = Arial, 10, n .FONT a10b = Arial, 10, i .FONT a12a = Arial, 12, b .FONT a12b = Arial, 12, n .FONT a16a = Arial, 16, bi .FONT a24a = Arial, 24, bi.. .. Header und Footer werden nur ausgegeben wenn Seite ungleich 1 .HE 0 .Header .If Seite > 1 $(@a10a "TDBprov") $(@a16a PROJEKT.ProjektName C_Form ToMargin) .HL .End .Footer .HL .If Seite > 1 $(@a10a "Projektdetailbericht, ausgegeben am "+$heute+" um "+$jetzt)$("Seite "+$Seite R_Form ToMargin ) .Else $(@a10b "TDBprov - TDB Projektverwaltung (c)R.W.B.Linn" C_FormToMargin) .End .. .Daten .. Erste Seite Deckblatt $(/) $(@a16a "Projektdetailbericht" C_Form ToMargin/) $(@a16a "für" C_Form ToMargin/) $(@a24a PROJEKT.ProjektName C_Form ToMargin/) .PA Hinweise: Seite ist eine TDB-Systemvariable.
|
| Topic Prozeduren nicht im Werkzeugmenü (Makrofenster) | Kapitel easy Allgemeine Hinweise |
|
Sollen Prozeduren nicht im Werkzeugmenü (User Modus) oder im Makrofenster (Strg-O) erscheinen, dann Prozeduren mit einem Dummy-Parameter definieren. Beispiel: Procedure MyLokal (Dummy : Real); Endproc Aufruf: MyLokal(0);
|
| Topic Hinzufügen Primärdatei Datensatz an angekoppelte Datei | Kapitel easy Allgemeine Hinweise |
|
Die Lösung ist die laufende Nummer der Primärdatei direkt das Feld Kopplung der angekoppelte Datei zuzuordnen. Beispiel: ADRESSEN ist Primärdatei, LETZTADR angekoppelte Datei If RecNo(ADRESSEN) > 0 ReadRec(LETZTADR, 0); ..Kopplungsfeld bekommt ID Feld LETZTADR.Adresse := ADRESSEN.Nummer; WriteRec(LETZTADR, 1 + FileSize(LETZTADR)); Refresh; Message("LETZTADR angepaßt mit AdresseNr. " + Str(ADRESSEN.Nummer)); End
|
| Topic Hinzufügen Primärdatei Datensatz an Relationsdatei | Kapitel easy Allgemeine Hinweise |
|
WinTDB setzt zur Auflösung eine n:m-Verbindung eine dritte Datei, die sg. Relationsdatei, ein. Diese Datei (Dateiendung .REL) enthält die Laufende Nummern der verbundene Dateien. Mittels easy muß daher direkt die Relationsdatei bearbeitet werden. Hierzu ist es notwendig die Laufende_Nummern der Datensätze und der Name der Relationsdatei zu wissen. Name der Relationsdatei ist die Datei der das Relationsfeld enthält, allerdings mit der Endung .REL und ggf. eine Buchstabe am Ende des Dateinamens. Folgendes easy-Beispiel zeigt zwei Tabellen ADRESSEN und KORRESP. Eine Adresse kann mehrere Korrespondenzen enthalten, aber eine Korrespondenz kann auch an mehrere Adressen gerichtet sein. Das Relationsfeld befindet sich in der Tabelle KORRESP. Die Relationsdatei heißt KORRESPO.REL. Beim Öffnen des Projektes wird die Datei automatisch mit geöffnet. Es handelt sich wie gesagt um eine DAT-Datei. easy-Beispiel: ..adressen laufende nummer ermitteln ReadRec(ADRESSEN, RecNo(ADRESSEN) ); ..neues korrespondez record erstellen ReadRec(KORRESP, 0); ..setze vorgaben SetField(KORRESP,3,DateStr(ToDay)); ..speichere record WriteRec(KORRESP, 1 + FileSize(KORRESP)); ..zweiter schritt ..korresp record lesen um laufende nummer zu ermitteln ReadRec(KORRESP, FileSize(KORRESP) ); ..neues record in der relationsdatei erstellen ReadRec(KORRESPO, 0); ..laufende nummern zuordnen, hierbei ist feld 1 immer das feld mit den namen der ..tabelle der das relationsfeld enthält KORRESPO.1 := KORRESP.Nummer; KORRESPO.2 := ADRESSEN.Nummer; ..speichere record WriteRec(KORRESPO, 1 + FileSize(KORRESPO) );
|
| Topic Beim Programmstart eine Prozedur aufrufen (OnOpenProject) | Kapitel easy Allgemeine Hinweise |
|
Oft möchte man eine Prozedur direkt beim Start einer Anwendung aufrufen. Entweder weil gleich zu Beginn eine Anwenderkommunikation nötig ist (z.B. Name des Anwenderseingeben), oder weil man bestimmte Datenfenster öffnen möchte, oder um bestimmte globale Variablen (siehe nächster Abschnitt) initialisieren zu können. easy stellt Ihnen dazu die Prozedur OnOpenProjectzur Verfügung. Wenn das erste Modul einer Tabelle eine Prozedur mit dem Namen OnOpenProject enthält, wird diese beim Öffnen desProjektes ausgeführt. Dies gilt für jede Tabelle des Projektes. Beispiel: PROCEDURE OnOpenProject If Message("Möchten Sie die Standardeinstellung laden?", "Start", 3) =6 ActivateForm("KUNDEN.Kundenliste"); ActivateForm("RECHNUNG.Rechnung"); End ENDPROC Hinweise: Zu beachten sei, daß die WinTDB beim Start alle OnOpenProject-Prozeduren aufruft, d.h. wenn es mehrere Tabellen mit Modulen gibt, die eine OnOpenProject-Prozedur enthalten, dann werden diese ausgeführt. OnOpenProject erscheint im User-Modus im Werkzeugmenü. Um das zu vermeiden, könnte man OnOpenProject mit einem Parameter versehen. Ist im Modul auch möglich, aber beim Aufruf stürzt die WinTDB ab (WinTDB 1.02)!
|
| Topic Definition Globale Variablen | Kapitel easy Allgemeine Hinweise |
|
Auf den ersten Blick fehlen in easyVariablen, die ihreGültigkeit über eine Prozedur hinaus bewahren. Dabei übersieht man leicht, daß es ja Variablen gibt, die nicht nur in allen Prozeduren gelten, sondern sogar auch beim nächsten Startder Anwendung noch ihre alten Werte haben: Tabellen. Angenommen, Sie möchten in einer Anwendung den Namen des Benutzersspeichern sowie das Datum und Uhrzeit des Programmstarts. Dazu legen Sie mit "Datei/NeueTabelle..." eine Tabelle namens SYSTEM mit z.B. den Spalten Benutzername (Typ Alphanumerisch:40) Startdatum (Typ Datum) Startzeit (Typ Zeit) an. Durch eine OnOpenProject-Prozedur können Sie die Werte beim Programmstart ermitteln und eintragen. Anschließend sind diese Daten an jeder Stelle im Programm bekannt: PROCEDURE OnOpenProject ReadRec(SYSTEM, 1) Input(Geben Sie Ihren Namen an", Faktura"); GLOBVAR.BenutzerName := T-Eingabe; GLOBVAR.StartDatum := today; GLOBVAR.StartZeit := now WriteRec(SYSTEM, 1) ENDPROC Die Verwendung eine SYSTEM Tabelle sollte zum Standard für jedes Projekt werden. Zu der SYSTEM Tabelle kommen dann noch das SYSTEM Formular SYSTEMEINSTELLUNGEN (kann natürlich auch anders heißen) und das SYSTEM Modul. Alle Prozeduren die global in einem Modul eingesetzt werden, werden im SYSTEM Modul definiert. Das SYSTEM Formular kann den verschiedensten Aufgaben haben,z.B. Seite 1 Allgemeine Einstellungen Seite 2 Drucker Parameter Seite 3 Hilfeseite Die Tabellenstruktur der Tabelle SYSTEM kann aus sehr unterschiedlichen Felder bestehen, eben abhängig von den eingesetzten Werte der im Projekt benötigten Werte. Die Tabelle SYSTEM enthält genau einen Datensatz, wo immer wieder aufzugegriffen wird; ReadRec(SYSTEM, 1). Neue Werte werden dementsprechend mir WriteRec(SYSTEM, 1) gespeichert. In dieses Dokument sind verschiedenen Tipps, die von der Tabelle SYSTEM gebrauch machen.
|
| Topic Dialogfenster für die Anwender Kommunikation | Kapitel easy Allgemeine Hinweise |
|
Windows-Programme verwenden oft Dialogfenster zur Eingabe von Informationen durch den Anwender. Mit easy können auch Ihre Anwendungen diese komfortable Eingabemöglichkeit benutzen. Denn was sind Dialogfenster anderes als modale Formulare? Erstellen Sie also eine Hilfstabelle namens DLGTAB (nur ein Beispiel) in Ihrem Projekt, welche für jede einzugebende Informationseinheit die passende Spalteenthält. In diese Tabelle müssen Sie per Hand einen Datensatz mit den Vorbelegungen des Dialogfensterseintragen. Anschließend entwerfen Sie ein oder mehrere Formulare für diese Tabelle. Zum Ausführen des Dialogfensters gehen Sie folgendermaßen vor: Diese Prozedur führt einen Dialog aus und gibt 1 zurück, wenn er mit OK bestätigt wurde, sonst 0. Procedure DialogAusführen(Dialogname: String; Kommentar: String): Real; ..#Datenfenster öffnen OpenForm("DLGTAB."+Dialogname); ..#Formular modal ausführen und Ergebnis auswerten If EditRec(Kommentar) Schließen RETURN 1 Else Schließen RETURN 0 End ENDPROC Als Beispiel soll eine Anwendung dienen, in deren Verlauf zwei Dialogfenster benötigt werden. In dem einen werden Vor- und Nachname des Anwenders sowie sein Geburtsdatum abgefragt, in dem anderen kann er Sortierung und Datensatz-Auswahl eines Berichtesfestlegen. Die Hilfetabelle DLBTAB erhält nun die folgende Struktur: Benutzername (Typ Alphanumerisch:40) Benutzervorname (Typ Alphanumerisch:20) BenutzerGeburtsdatum (Typ Datum) BerichtSortierung (Typ Auswahl aus (Bezeichnung, Hersteller, Modelljahr) BerichtAuswahl (Typ Integer) Zu dieser Tabelle entwerfen Sie zwei verschiedene Formulare. Das eine heißt z.B. BenutzerDlg und enthält die ersten drei Felder der Tabelle, während das andere BerichtDlg heißen könnte und die Felder vier und fünf beinhaltet. Zur Eingabe der Benutzerdaten rufen Sie einfach die obenstehende Prozedur auf: IF DialogAusführen("BenutzerDlg", "Geben Sie Ihre Daten an") ... END Wo die drei Punkte sind, können Sie die eingegebenen Daten verwenden: Message("Hallo, " + DLGTAB.BenutzerVorname + " " + DLGTAB.BenutzerName+ ". Sie sind " + Str(Year(today) - Year(DLGTAB.BenutzerGeburtsdatum)) + " Jahre alt.");
|
| Topic Projektverzeichnis ermitteln | Kapitel easy Allgemeine Hinweise |
|
Die WinTDB bietet keine Möglichkeit das Projektverzeichnis eines Projektes direkt zu ermitteln. Eine kleine easy-Abfrage schafft Hilfe: ?MaxFile > 0 / sProjektverzeichnis := DBDir(1); 1 steht für die erste Tabelle im Projekt. MaxFile prüft ob es überhauptTabellen im Projekt gibt. Einsatzgebiet diese Möglichkeit ist das aufrufen von Prozeduren mittels ExecMacro, wobei das Modul in einem anderen Verzeichnis liegt.
|
| Topic Debugging Möglichkeit | Kapitel easy Allgemeine Hinweise |
|
Während der Entwicklung von easy-Module ist es manchmal sinnvoll, Ergebnisse zwischen zu speichern (Debug-Informationen). Folgende Prozedur ermöglicht es Informationen ineine Logdatei (Textdatei) zu schreiben, welche dann z.B. mit dem Windows NotePadangezeigt werdenkann. PROCEDURE WriteToLog(sLogFile: STRING; s : STRING; nLogNeu : REAL) .. schreibt string s in einemlogdatei .. parameter: .. sLogFile - logdatei .. s - eintrag in der logdatei .. nLogNeu - 0 erstelle neue logdatei .. Beispiel: .. WriteToLog("Projekt.log", "START p.MyProc um " + DateStr(Today) + "" + TimeStr(Now), 0); DEF HEADING = "Debug"; VARDEF nFH : Real; .. neue logdatei erstellen, wenn nLogFirst = 1 IF nLogNeu = 1 ?IsFile(sLogFile) = 1 / DelFile(sLogFile); END .. logdatei öffnen, erst prüfen ob logdatei vorhanden ist. IF IsFile(sLogFile) = 0 .. logdatei nicht da, erstelle neu IF nFH:=Rewrite(sLogFile) < 1 Message("Kann Logdatei " + sLogFile + " nicht neu erstellen.",HEADING); Halt; END WriteLn(nFH,"Logstart um " + DateStr(ToDay) + " " + TimeStr(Now)); Close(nFH); END .. logfile schon da? IF IsFile(sLogFile) = 1 IF nFH:=TAppend(sLogFile) < Message("Kann Logdatei " + sLogFile + " nicht öffnen...", HEADING); Halt; END END WriteLn(nFH,TimeStr(Now) + " : " + s); CLOSE(nFH); ENDPROC ..Beispiel: Eintragung in der Logdatei Procedur Test WriteToLog("Projekt.log", "Starte p. Test", 1); .. neue logdatei .. Schritt 1 WriteToLog("Projekt.log", "Ende Schritt 1...", 0); .. hinzufügen .. Schritt 2 WriteToLog("Projekt.log", "Ende Schritt 2...", 0); Endproc ..Aufruf Logdatei mittels Windows NotePad Procedure ZeigeLogDatei Execute("NotePad.exe Projekt.Log); Endproc
|
| Topic Datensätze aus Tabelle löschen | Kapitel easy Allgemeine Hinweise |
|
Die sicherste Methode alle Datensätze einer Tabelle zu löschen, zeigen folgende Modulfragmenten: Mögichkeit 1 ..lösche alle Einträge der Tabelle FAX VARDEF nCount : Real; nCount := FileSize(FAX); IF nCount > 0 nRNo:=LastRec(FAX); REPEAT DelRec(FAX, RecNo(FAX)); nRNo:=PrevRec(FAX); UNTIL FileSize(FAX) = 0 END Mögichkeit 2 ..alle markierte Datensätze löschen ..die Markierung kann mittels SetMark erfolgen Access(TERMLIST, "Markierung"); While ReadRec(TERMLIST, FirstRec(TERMLIST) ) DelRec(TERMLIST, RecNr(TERMLIST) ) End Möglichkeit 3 Bei größeren Datenbanken (z.B. Größen zwischen 10.000 und 80.000 Datensätze) haben Möglichkeit 1 und 2 den entscheidenden Nachteil, daß das Löschen viele Minuten bzw. bei entsprechend kleinem Rechner sogar Stunden dauert. Besser geeignet ist i.d.F. die eingebaute Funktion "ClearDat(Tabelle:Real)". Hiermit werden schlagartig alle Datensätze ohne Rückfrage gelöscht. Eine Sicherheits-Rückfrage ließe sich problemlos über eine Prozedur einbauen: Procedure LöscheRecords If Message("Wirklich alle Datensätze löschen?", "Frage", 3) = 6 ClearDat(TABELLE); End Endproc
|
| Topic Modul-Vorlage | Kapitel easy Allgemeine Hinweise |
|
..Modul für Tabelle TABELLE ..Datei: ..TABELLE.MOD ..Beschreibung: .. ..Historie: ..tt.mm.jjjj Autor INCLUDE ... Procedure OnOpenProject ..wird beim starten eines Projektes ausgeführt Endproc
|
| Topic Arrays | Kapitel easy Allgemeine Hinweise |
|
Verschiedenes zu Arrays Speicherplatz: Ein Array kann maximal 64 KB groß werden. Ein REAL benötigt 6 Bytes. Dadurch sind maximal 65536 / 6 = 10922 Einträge möglich. Ein String belegt übrigens nur 4 Byte (Es wird ein Zeiger auf denString gespeichert). Definition: Vardef aFeld : String[5]; Erzeugt wird ein ein-dimensionales Array mit 5 Elementen vom TypString. Array-Element mit einem Wert belegen: aFeld[1] := "Triathlon"; Array-Element ausgeben: Message(aFeld[1]); Vardef aFeld : String[5, 5]; Erzeugt wird ein zwei-dimensionales Array mit 5 mal 5 Elementen vom TypString. Array-Element mit einem Wert belegen: aFeld[1,1] := "Triathlon"; Array-Element ausgeben: Message(aFeld[1,1]); Arrays und Prozeduren: Arrays werden als sogenannte Referenzparameter definiert. Procedure Test(Var aFeld : String[5] ); Message(aFeld[1]); Endproc Procedure Test(Var aFeld : String[5, 5] ); Message(aFeld[1,1]); Endproc falls die Arraydimensionen nicht bekannt sind, kann auch 0 übergebenwerden. Procedure Test(Var aFeld : String[0, 0] ); Endproc Besondere Arrays: Ein String ist nichts anderes als Array von max. 255 Zeichen. Innerhalbdieses Arrays können Zeichen teil ausgebenen werden. Beispiel: Vardef sStr : String; sStr := "Triathlon ist cool"; sStr[1, 9] liefert "Triathlon"
|
| Topic Umwandlung in Kleinbuchstaben | Kapitel easy Allgemeine Hinweise |
|
Das Problem kann mit Hilfe der selbstdefinierten Funktion Lower gelößt werden. Diese nachstehend aufgeführte Funktion ist das Gegenstück zur vorh. Funktion UPPER: Hinweis: Lower ist ab VDP 3 als easy-Funktion standard enthalten. Procedure Lower(Wort:String):String Vardef Le, P : Real; Vardef W1 : String; Le:=Length(Wort); P:=1; W1:=""; WHILE P <= Le IF ASC(Wort[P,1] >= 65 and ASC(Wort[P,1] <= 90 W1:= W1+CHR(ASC(Wort[P,1])+32) ELSIF Wort[P,1]="Ä" W1:= W1+"ä" ELSIF Wort[P,1]="Ö" W1:=W1+"ö" ELSIF Wort[P,1]="Ü" W1:= W1+"ü" ELSE W1:=W1+Wort[P,1] END P:= P+1 END Return W1 EndProc Soll die Funktion in einem Datenbankjob aufgerufen werden, muß das Modul in dem sich diese Funktion befindet, mit dem Befehl USES eingebunden werden. Wennein Eingabefeld in einem Formular in Kleinbuchstaben umgewandelt werden soll, so istbei dem betreffenden Feld bei Eingabekontrolle/Ausführen beim Verlassenfolgendes einzugeben: EXECMACRO(<Modulname>,Feld := Lower(Feld); Refresh;
|
| Topic Word Importdatei aus einem Modul/Datenbankjob | Kapitel easy Allgemeine Hinweise |
|
Frage: Eine Datei "adrliste.doc" soll als Quelldatei für Word 97 benutztwerden. Die erste Zeile soll eine Titelzeile in folgender Form sein: "Name ;Vorname ; Adresse ; PLZ ; Telefon" danach die Daten. Antwort: In ein Modul: WriteLn (T,"Name;Vorname;Adresse;PLZ;Telefon"), dann die Daten ausgeben. Entweder mittels firstrec und nextrec Prinzip oder als Subreport. In ein Datenbankjob: .DATEN $("Name;Vorname...) .SUB $(Name, Vornaame...) .ENDSUB
|
| Topic Zwischenablage verwenden | Kapitel easy Allgemeine Hinweise |
| Topic Zeichenumsetzung DOS <> Windows | Kapitel easy Allgemeine Hinweise |
|
Immer wieder gibt es Probleme mit der Zeichenumsetzung zwischen DOS und Windows. DOS verwendet den sogenannten ASCII-Zeichensatz, Windows dagegen den ANSI-Zeichensatz. Da Beide nicht gleich sind, ist eine Umsetzung von Zeichen von DOS nach Windows undumgekehrt notwendig. Hierzu gibt es folgende Funktionen: 1.Für die Umwandlung von DOS (=OEM) nach Windows: Windows-Zeichenkette := OEMToANSI(DOS-Zeichenkette) 2.Für die Umwandlung von Windows nach DOS (=OEM): DOS-Zeichenkette := ANSIToOEM(Windows-Zeichenkette) Eine Zeichenkette kann auch ein einzelnes Zeichen sein. Um exportierte Daten aus der DOS-TDB in ein WinTDB- oder VDP-Projekt einlesen zu können, sollte die Funktion OEMToANSI verwendet werden.
|
| Topic Fehlerbehandlung für Datumseingabe etc. | Kapitel easy Allgemeine Hinweise |
|
Eingabe eines Datums auf Gültigkeit prüfen: Vardef nTag : Real; T-Eingabe := Input("Bitte Datum eingeben!", "Frage"); ?T-Eingabe = "" / Return nTag := Val(T-Eingabe) ..datestr wandelt eine Zahl in ein Datumstr mm.tt.jjjj um T-Eingabe := DateStr(nTag)) .EC 1 If Val(T-Eingabe[7,2]) < 19 Or $Fehler > 0 Message("Ungültiges Datum eingegeben (" + T-Eingabe + ").", "Fehler"); Return End ..Fehlercheck wieder an VDP übergeben .EC 0
|
| Topic Datensatz mit Relations-Felder duplizieren | Kapitel easy Allgemeine Hinweise |
|
Diese easy-Prozedur dupliziert ein Datensatz welches ein Relationsfeld enthält. Eine Relationsdatei, REL-Datei, enthält zwei Felder die auf Auto-Nummer Felder der zwei angekoppelte Tabellen verweisen. Die hier vorgeschlage Lösung verwendet ein Array zur Ablage der Koppelfelder. Procedure RELDuplizieren(nDummy : Real); ..Haupttabelle TABELLE enthält ein Relations-Feld Artikel welches ..auf die Tabelle ARTIKEL verweist. Die REL-Datei ist FSARTIKE Vardef i, nRNo, nLN, nCnt : Real; Vardef sFeld1, sFeld2 : String; ..die beiden staring felder der tabelleTABELLE Vardef anArtikel : Real[10000]; ..artikel array, speichert zeiger auf das auto-nummerfeld ..lese aktuellen datansatz nRNo := ReadRec(TABELLE, RecNr(TABELLE)); ..kein gefunden, dann stoppe ?nRNo = 0 / Return ..speichere daten des aktuellen datensatzes in variabele sFeld1 := TABELLE.Feld1; sFeld2 := TABELLE.Feld2; .. ..speichere die zeiger auf die artikel im array anArtikel i := 0; Sub ARTSTAMM anArtikel[i] := TABELLE.Artikel.Laufende_Nummer; i := i + 1 Endsub nCnt := i; .. ..neuen datensatz der tabelle TABELLE anlegen Readrec(TABELLE, 0); TABELLE.Feld1 := sFeld1; TABELLE.Feld2 := sFeld2; ..speichere datensatz WriteRec(TABELLE, 1 + FileSize(TABELLE)); ..rufe den datansatz wieder auf um die Auto-Nummer zu ermitteln nLN := TABELLE.Laufende_Nummer; ..suche satz nRNo := FindRec(TABELLE, Str(nLN), "TABELLE.INR", 1); .. ..jetzt durch das array loopen und in der REL-Datei neue Datensätzehinzufügen. i := 0; While i <= nCnt ..neuen satz anlegen ReadRec(FSARTIKE, 0); FSARTIKE.R-TABELLE := nLN; FSARTIKE.R-ARTSTAMM := anArtikel[i]; ..übergabe der zeiger ..Message("Artikel: " + Str(nLN) + "/" + Str(anFSArtikel[i]), Str(i)); ..speichere satz WriteRec(FSARTIKE, 1 + FileSize(FSARTIKE)); i := i + 1; End .. ..ok das wars Return Endproc
|
| Topic Mittelteil eines Strings bearbeiten | Kapitel easy Allgemeine Hinweise |
|
Es gibt in easy kann Befehl wie midstr bzw. substr um einen Mittelteileines Strings herauszufilten, aber in VDP besteht ein String aus eine Zeichenfolgevon max. 255 Zeichen. Es können Teile aus einem String herausgefiltert werden, indem dieStartpositionun Mittels Pos kann die Position eines Zeichens bzw. Zeichenketteermittelt werden. Beispiel easy-Prozedur: Procedure Test Vardef sStr : String; Vardef i : Real; sStr := "fools garden ist toll"; Message("Es wird garden ausgegeben: " + sStr[7, 6], "Test 1"); Message("Es wird garden und der rest ausgegeben: " + sStr[7, 255],"Test 2"); i := Pos("garden", sStr); Message("Es wird garden und der rest ausgegeben: " + sStr[i, 255],"Test 3"); Message("Es wird garden ausgegeben: " + sStr[i, Length("garden")],"Test 4"); Endproc
|
| Topic Definition von Zwischenvariablen | Kapitel easy Allgemeine Hinweise |
|
Es gibt folgende VDP interne Möglichkeit Variablen zwischen zuspeichern: 1.NOTE Funktion: Note(Zeichenkette: String) oder Note Legt die Zeichenkette in einem internen Speicher ab. Note ohne Parameter liefert den Inhalt des internen Speichers. Damit können Berichte oder Datenbankjobs vonMakros aus mit Informationen versorgt werden. 2.T-Eingabe Die Funktionen Input und ChooseFile verwenden diese systemweite Variable vom Typ String. 3.Windows Zwischenablage verwenden Funktion: Text2Clip Kopiert den Inhalt der Speicher-Datei in die Zwischenablage. Funktion: Clip2Text Kopiert den Inhalt der Zwischenablage in die Speicher-Datei, wenn es sich um einen Text handelt. 4.VDP Zwischenspeicher RAMTEXT verwenden Beispiel Text aus der Windows Zwischenablage holen: Procedure AusZwischenablage : String; VarDef nFH : REAL VarDef sStr : STRING Clip2Text nFH := Reset("RAMTEXT"); sStr := ReadLn( nFH); Close(nFH) Return sStr Endproc
|
| Topic Meldungssystem für Anwendungen | Kapitel easy Allgemeine Hinweise |
| Topic DLL Programmierung und Nutzung in easy | Kapitel easy Allgemeine Hinweise |
| Topic Bearbeitung angekoppelte Datensätze | Kapitel easy Allgemeine Hinweise |
| Topic eMail per DLL senden | Kapitel easy Allgemeine Hinweise |
|
Eine Mail lässt sich per DLL verschicken. Im VDP3 Beispielprojekt Mailer ist eine DLL enthalten, der Mail-Funktionen enthält: ppweb.dll Die eMail-Funktionen werden im Header des Moduls so eingebunden: DLLPROC SendMail(Host : String; Sender : String; UserId : String; Receiver : String; Subject : String; Body : String; Attachment : String) : INTEGER LIBRARY "ppweb.dll"; DLLPROC SendPgpMail(KeyRing : String; CommentStr : String; VersionStr : String; Host : String; Sender : String; UserId : String; Receiver : String; Subject : String; Body : String; Attachment : String) : INTEGER LIBRARY "ppweb.dll"; DLLPROC GetMailError(VAR Msg : String; MaxLen : INTEGER) LIBRARY "ppweb.dll"; Der Aufruf erfolgt dann fast genauso wie bei einer eingebauten Funktion.
|
| Topic HTML-Form Analyse (Wissen) | Kapitel Internet (HTML, Formulare, Wissen, ISAPI) |
|
HTML-Formulare generieren mittels Action= GET oder POST Dateien, die ausgewertet werden können. Alle Felder und Inhalte werden mittels & und sonstige Zeichen in der URL-Zeile dargestellt. Das passiert wenn der Benutzer den SUBMIT oder SENDEN - Button druckt. Auf dem Internet-Server läuft ein CGI-Programm der mit diese Zeichen umgehen muss. Hierzu gibt es eine Reihe von Moeglichkeiten. Ich habe die ersten Erfahrungen mit eine Programmiersprache PERL gemacht. PERL kann die Zeile analysieren und dann in eine lesbare Form ausgeben. Beispiel: Name=Linn Vorname=Robert Kommentar=Nette Homepage Im Formular steht hinter ACTION= welches Skript auf dem Serverausgefuehrt wird. URL koennte so aussehen: http://../meinskript?Name=Linn&Vorname=Robert&Kommentar=Nette+Homepage Es gelten folgende Regeln: o Name/Werte werden durch Ampersandzeichen & getrennt o Name/Werte durch Gleichheitszeichen = getrennt o Alle nicht 7-bit Zeichen werden durch Hex-Zeichen mit Prozent %vorweg ersetzt (%NN) o Leerzeichen durch Pluszeichen + In PERL geht die Konvertierung sehr einfach, darum habe ich mich nicht drum gekummert, d.h. einmal einen Parser in PERL geschrieben und fertig war die Sache. C-Beispiel in http://www.hyperion.com/~koreth/uncgi.htm Vorgang: o Wertepaare trennen (&) o Trennung Name vom Wert (=) o Ersetzen + durch Leerzeichen o Ersetzen %NN durch ASCII Wert
|
| Topic Tipps zu ISAPI | Kapitel Internet (HTML, Formulare, Wissen, ISAPI) |
|
Einfach ein paar Tipps und freie Gedanken. Tip 1 easy-Routine der vorhandensein der isa-Datei (.isa) prüft: If IsFile("myisa.isa") = 0 Message("Sorry, die Anwendung wurde nicht gefunden!", "Fehler"); Return oder Halt End Tip 2 Check ob Programmpfad für Webbrowser in der vdp32.ini eingetragen ist: [Werkzeuge] WWW-Browser= Tip 3 Wenn die Anwendung mittels localisa.exe getestet wird, sollten die DLLs, wie owl...dllentweder ins Projekt- oder Windows-System Verzeichnis liegen. Tip 4 Wird eine WWW-Anwendung erstellt, dann werden folgende Dateien generiert: anwendung.isa anwendungE.dll anwendungH.dll Das Programm anwendung.isa benötigt: owl52f.dll anwendunge.dll bds52f.dll kernel32.dll winspool.drv gdi32.dll user32.dll winmm.dll cw3230.dll vdp32cgi.dll Gilt für VDP 2.x
|
| Topic Web Server Anwendung testen | Kapitel Internet (HTML, Formulare, Wissen, ISAPI) |
|
Wenn Sie eine VDP Web Server Anwendung erstellt haben, dann hat sich folgende Testmethode bewährt (VDP 2.03): 1.VDP starten 2.Applikationstyp setzen mittels Menüpunkt Programm | Eigenschaften, als Applikationstyp Web Server (ISAPI) setzen 3.Programm testen mittels Menüpunkt Programm | Programm testen In der Dialogbox z.B. folgende Werte eingeben: Abfrage (Query): Pruefaktion=Neu&AuftragNr=89 Daten (Content): AuftragNr=89 Hinweis: Es muß nicht eingegeben werden. 4.Browser starten In der Dialogbox Schalten Browser starten klicken Hinweis: der Browser kann aber auch aktiv bleiben. Wichtig: Bei Updates auf Tabellen nur der Browser LOCALISE aktiv halten. VDP schließen. Die Daten werden sonst nicht in den Tabelle übernommen.
|
| Topic Ein Wort lesen welches durch die Zeichen blank, ( und ; abgegrenzt ist | Kapitel easy Funktionsbibliothek |
|
Beschreibung: liest ein Wort welches durch die Zeichen blank, ( und ; abgegrenzt ist Procedure pReadWord(nPos : Real; sLine : String) : String; ..#liest ein Wort welches durch die Zeichen blank, ( und ; abgegrenztist ..#Returnwert: ..#Wort als String Vardef sTmp : String; Vardef i : Real; sTmp := ""; ?i < 1 Or i > 255 / i := 1; ..gibt es Zeichen vor der Prozedur, dann haben wird mit Beispiel 2 zutun If i > 1 And Not sLine[i - 1] in ["=", ",", " ", "(", ")", ";", ":"] Return "" End i := nPos; ..setze anfangswert ?sLine = "" / Return "" Repeat sTmp := sTmp + sLine[i]; i := i + 1; Until sLine[i] In [" ", "(", "=", ",", ":", ";"] Or i > Length(sLine) Return sTmp[1, i - 1] Endproc
|
| Topic HTML-Form Analyse (easy-Modul) | Kapitel easy Funktionsbibliothek |
|
Beschreibung: verschiedene hilfreiche Routinen die immer wieder gebraucht werden für Internet Operationen sowohl in easy-Modulen als auch in Formulare Procedure pHexToStr(sHex : String) : String; ..#Umwandlung eines Hex-Wertes in ein String ..#Parameter: ..#sHex = Hex-Wert als String Vardef x : Real; x := xWert(Asc(sHex[2]) -48,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,0,10,11,12,13,14,15) * 16 ; x := x + xWert(Asc(sHex[3]) -48,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,0,10,11,12,13,14,15); Return AnsiToOEM( Chr(x) ) Endproc Procedure pInetFormanalyse ..#einlesen der datei fb.txt. Diese Datei enthält den Output eineshtml-formulars ..#fb.txt analysieren und felder in eine datei ausgeben. ..# Var CRLF = Chr(13) + Chr(10); Var FIELDDELBEGIN = "&"; Var FIELDDELEND = "="; Var BLANK = "+"; Var HEXDEL = "%"; Vardef nRT,i : Real; ..returncode versch. operationen Vardef nFHin, nFHout : Real; ..filehandle input- und outputdatei Vardef sInDatei, sOutDatei : String; ..dateinamen für in undoutputdatei Vardef sTmp : String; Vardef nFieldFound : Real; Vardef nFieldContentFound : Real; Vardef sFieldName : String; Vardef sFieldContent : String; ..Inputdatei abfragen ..checken ob datei schon existiert T-Eingabe:="fb.txt"; REPEAT nRT := Input("Name der Formulardatei?", "InetFormanalyse"); ?nRT=0/Return UNTIL IsFile(T-Eingabe) sInDatei := T-Eingabe; ..checken ob ausgabedatei schon existiert T-Eingabe:="x.txt"; REPEAT nRT := Input("Name der Analysedatei", "InetFormanalyse"); ?nRT=0/Return UNTIL NOT IsFile(T-Eingabe) OR nRT:=Message("Datei existiert bereits! Überschreiben?","Achtung",3)=6 ?nRT=2/RETURN sOutDatei := T-Eingabe; ..als erste neue datei erstellen IF nFHout := Rewrite(sOutDatei) = 0 Message("Kann Analysedatei " + sOutDatei + " nicht erstellen.","Fehler"); Return End ..formdatei öffnen IF nFHin := Reset(sInDatei) = 0 Message("Kann Formdatei " + sInDatei + " nicht erstellen.", "Fehler"); Close(nFHout); Delfile(sOutDatei); Return End ..analyse durchführen i:=0; nFieldFound := 0; nFieldContentFound := 0; sFieldName := ""; sFieldContent := ""; WHILE NOT Eot(nFHin) sTmp := Read(nFHin, 1); i := i + 1; ..ersetze blank ?sTmp = BLANK / sTmp := " "; ..EOL abfangen und durch "" ersetzen ?Asc(sTmp) = 13 / sTmp := ""; ?Asc(sTmp) = 10 / sTmp := ""; ..hexzahl gefunden If sTmp = HEXDEL sTmp := sTmp + Read(nFHin, 2); sTmp := pHexToStr(sTmp); End ..feld gefunden? If sTmp = FIELDDELBEGIN nFieldFound := 1; ..setze flag on ?nFieldContentFound = 1/WriteLn(nFHout, "Inhalt: " + sFielContent); nFieldContentFound := 0; ..setze flag off sFieldName := ""; ..init felder End ..feldende gefunden If sTmp = FIELDDELEND And nFieldFound = 1 nFieldFound := 0; ..setze flag off nFieldContentFound := 1; ..setze flag on sFieldContent := ""; WriteLn(nFHout, "Feld: " + sFieldName); End ..erweitere feldname If nFieldFound = 1 ?sTmp <> FIELDDELBEGIN And sTmp <> FIELDDELEND/sFieldName:=sFieldName+sTmp; End ..erweitere feldinhalt If nFieldContentFound = 1 ?sTmp <> FIELDDELBEGINAndsTmp<>FIELDDELEND/sFieldContent:=sFieldContent+sTmp; End ShowWait("Feld " + sFieldName + CRLF + "Inhalt: " + sFieldContent); END ?nFieldContentFound = 1/WriteLn(nFHout, "Inhalt: " + sFieldContent); ..schliessen Close(nFHin); Close(nFHout); Message("Bin fertig..."); Endproc
|
| Topic Datensatz bearbeiten beenden | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Abfangen der beiden Möglichkeiten Datensätzeändern (ModifyRecords) und Neuedatensätze (AppendNewRecords) eingeben, ab: Procedure EndeBearbeiten ..#umschalten der Bearbeitungsmodi ?GetMode = 1/Datensätzeändern ?GetMode = 2/NeueDatensätzeEingeben Endproc
|
| Topic Alternative Message-Funktion für Meldungen | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Ein eigenes Meldungsfenster als Alternative für die Funktion Message. Warum: o Fenstergrösse Message ist begrenzt, o Anzahl Textzeichen begrenzt, o Vordefinierte Makros nur für Ja, Nein und Abbruch Vorgehensweise: In eine globale Tabelle SYSTEM zwei Felder definieren (siehe auch Topic Globale Variablen): MeldungsHeader (String 40) und Meldungstext (String 255). Weiterhin wird ein Formular SYSTEM.Systemmeldung erstellt. Es enthält die beiden Felder und ein OK Makro (führt CloseWnd aus). In der Objekt Reihenfolge den OK Button an erste Stelle. Im System Modul wird folgende Prozedur definiert: Procedure SystemMeldung(sText, sHdg : String); ..#Ausgabe eine Systemmeldung ReadRec(SYSTEM, 1); ?$SYSTEM.MeldungsHeading <> "" / $SYSTEM.MeldungsHeading := sHdg; ?$SYSTEM.MeldungsText <> "" / $SYSTEM.MeldungsText := sText; WriteRec(SYSTEM,1); ActivateForm("SYSTEM.Systemmeldung"); Endproc Aufruf der Prozedur in Makros, Module etc.: ExecMacro(System, SystemMeldung("Keinen Speicherplatz","Fehler") ); Noch folgenden Tip: Es ist nicht möglich Variablen zu übergeben: Var sMsg = "Hallo, wie geht"s..." ExecMacro(System, SystemMeldung(sMsg,"Fehler") ); WinEASY laßt diese Möglichkeit nicht zu. Es gibt ein Ausweg, in dem der Meldungstext und Heading erst in der Tabelle SYSTEM geschrieben werden. Var sPanaMod = "\daten\wintdb\utils\uti-pana.prg" ReadRec(SYSTEM, 1); $SYSTEM.MeldungsHeading := "Hinweis"; $SYSTEM.MeldungsText := "Projektanalysemodule " + sPanaMod + " nichtgefunden."; WriteRec(SYSTEM, 1); ExecMacro(System, SystemMeldung("","") ); Prozedur SystemMeldung mit leeren Felder übergeben, da diese schonvorher geschrieben wurden. Hinweis: Sind in eine Tabelle mehrere Formulare definiert und ist schon eine aktiv (z.B. TAB.Form1), dann wird beim Aufruf von ActivateForm("TAB.Form2") TAB.Form1 aktiviert, anstatt von TAB.Form2. (Fehler in WinTDB 1.02?)
|
| Topic Umsetzung Memo- in String-Feld | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Die Memo-Voranzeige unter WinTDB ist nicht so elegant, wie unter DOS-TDB. Ich habe daher ein zusätzliches Feld aufgebaut, was das Memo-Feld ersetzen soll. Wenn Memos verwendet werden die kleiner 256 Zeichen sind, dann ist es sinnvoller diese in einem mehrzeiligem String-Feld zu setzen. Folgende Routine setzt ein Memo-Feld in ein Stringfeld um. PROCEDURE BemerkungToNotiz VARDEF nCount : Real VARDEF nRNo : Real VARDEF I : Real VARDEF sTmpFile : STRING; VARDEF nHandle : Real; VARDEF sTmp : String; VARDEF sNotiz : String; sTmpFile := "TEMP.TXT"; IF Access(ADRESSEN,"ADR_NR.IND") > 0 Message("Ich arbeite..."); ..gehe zum ersten record nRNo:=FirstRec(ADRESSEN); I:=0; WHILE nRNo>0 .. record lesen ReadRec(ADRESSEN,nRNo); ..If IsFile(sTmpFile) = 1 DelFile(sTmpFile) .. memo in texfileschreiben CopyMemo($ADRESSEN.Bemerkung,sTmpFile); .. textfile in string kopieren sNotiz := ""; IF nHandle := Reset(sTmpFile) > 0 While not eot(nHandle) sTmp := ReadLn(nHandle); sNotiz := sNotiz + sTmp; End Close(nHandle) SetField(ADRESSEN,LabelNr(ADRESSEN,"Notiz"), sNotiz); WriteRec(ADRESSEN,nRNo); ELSE Message(sTmpFile+" kann nicht erzeugt werden","Fehler",1) END .. nächstes record nRNo:=NextRec(ADRESSEN); I := I + 1; END END ENDPROC Hinweis: Ab der Version 1.04 gibt es eine Easy-Funktion HTML2STR.
|
| Topic Ein einfachen Datenbankjob generieren | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Generiert ein einfachen Datenbankjob. Procedure JobGen ..#generiert einen einfachen job. ideal für die erstellung eines ersten jobs VAR nDatenbank = 1; ..erster datenbank oder VAR nDatenbank = FileNr; ..aktuelle datenbank VAR sDBName = DBName(nDatenbank); VAR sJobname = sDBName[1,Pos(".",sDBName)] + "JOB"; VAR sAutor = "R.W.B.Linn"; VARDEF nRT,i : Real; ..returncode versch. operationen VARDEF nHandle : Real; ..filehandle VARDEF nAusgabe : Real; ..ausgabedatei ..checken ob datei schon existiert T-Eingabe:=sJobname; REPEAT nRT := Input("Name des Datenbankjobs","JobGen"); ?nRT=0/Return UNTIL NOT IsFile(T-Eingabe) OR nRT:=Message("Datei existiert bereits! Überschreiben?","Achtung",3)=6 ?nRT=2/RETURN sJobname := T-Eingabe; ..als erste datei öffnen IF nAusgabe:=Rewrite(sJobname) ..jetzt wird der job erstellt WriteLn(nAusgabe,".Report"); WriteLn(nAusgabe,"..Datei: "+sJobname+" fuer Datenbank"+DBName(nDatenbank)); WriteLn(nAusgabe,"..Erstellt: "+DateStr(ToDay)+" "+sAutor); WriteLn(nAusgabe,".."); WriteLn(nAusgabe,".var Linie=XMal('_',72)"); WriteLn(nAusgabe,".Prolog"); WriteLn(nAusgabe,".Header"); WriteLn(nAusgabe,"Liste von $heute"); WriteLn(nAusgabe,"$Linie"); WriteLn(nAusgabe,".Footer"); WriteLn(nAusgabe,"$Linie"); WriteLn(nAusgabe,"Seite -$(Seite)- Report: "+sJobname); WriteLn(nAusgabe,".Daten"); ..ausgabe der datenfelder WHILE i:=i+1 <= MaxLabel(nDatenbank) WriteLn(nAusgabe,"$"+Label(nDatenbank,i)) END WriteLn(nAusgabe,"..Jobende"); Close(nAusgabe); .. Message("Job "+sJobname+" generiert..."); ELSE Message(sJobname+" kann nicht erzeugt werden","Fehler",1); END Endproc
|
| Topic Ein Wert aus eine Windows Ini-Datei lesen | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Die Prozedur LeseIniWert liest aus eine Windows Ini-Datei (z.B.win.ini) eine Wert. Einsatzgebiete diese Prozedur können z.B. sein: o aktueller Drucker ermitteln (Datei: win.ini, Sektion: Windows,Eintrag: Device) o eigene Projekt Ini-Datei erstellen, um dann Werte auszulesen: definierte Meldungen, Auswahlmöglichkeiten Diese Möglichkeit kann auch in einem Formelfeld verwendet werden. Prozeduraufruf: Der Aufruf erfolgt via der Funktion ExecMacro. Beispiel für einen Formelfeld in einem Formular: Standard Drucker ermitteln ExecMacro(SYSTEM, LeseIniWert("c:\windows\win.ini", "windows","device") ) Procedure LeseIniWert (sIniDatei, sSektion, sEintrag : String) : String ..#liest einen wert aus eine windows ini-datei und liefert diese zurück. ..#ini-datei aufbau ..#[sektion] ..#eintrag=wert Vardef sWert : String;..wert der zurückgeliefert wird Vardef nFH : REAL;.. filehandle Vardef sLine : String;.. ini-zeile Vardef sTempLine : String;.. tempzeile Vardef nFound : Real;.. sektion gefunden? ..init ?sSektion[1] <> "["/sSektion := "[" + sSektion + "]"; sSektion := Upper(sSektion); sEintrag := Upper(sEintrag); nFound := 0; ..inidatei vorhanden IF IsFile(sIniDatei) = 0 Message(sIniDatei + " nicht gefunden.", "Fehler", 1); Return END ..öffne inidatei IF nFH := Reset(sIniDatei) > 0 WHILE NOT Eot(nFH) sLine := ReadLn(nFH) sTempLine := sLine; sLine := Upper(sLine); ?sLine = sSektion / nFound := 1 IF nFound = 1 IF sLine[1, Pos("=", sLine) - 1] = sEintrag Close(nFH) Return sTempLine[Pos("=", sLine) + 1, Length(sTempLine) - Pos("=", sLine) ] END END END ELSE Message(sIniDatei + " nicht gefunden.", "Fehler", 1); END Close(nFH); Endproc Beispielaufruf: Procedure ATest ..#test, gibt der aktuelle Drucker. aus. Message(LeseIniWert ("c:\windows\win.ini", "Windows", "Device") ); Endproc
|
| Topic Ein Wert in eine Windows Ini-Datei schreiben | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Die Prozedur SchreibeIniWert schreibt in eine Windows Ini-Datei (z.B.win.ini) eine Wert. Einsatzgebiete diese Prozedur können z.B. sein: o eigene Projekt Ini-Datei erstellen, um dann Werte auszulesen: o definierte Meldungen, Auswahlmöglichkeiten Procedure SchreibeIniWert (sIniDatei, sSektion, sEintrag, sWert : String) : Real ..#schreibt einen wert aus eine windows ini-datei und liefert diese zurück. ..#ini-datei aufbau ..#[sektion] ..#eintrag=wert Vardef nFHin, nFHout : REAL;.. filehandle Vardef sLine : String;.. ini-zeile Vardef sTempLine : String;.. tempzeile Vardef nFound : Real;.. sektion gefunden? Vardef nChanged : Real; .. wert geändert Vardef sIniDateiNeu : String; Vardef sOrgSektion, sOrgEintrag : String; ..init ?sSektion[1] <> "["/sSektion := "[" + sSektion + "]"; ..speichere originalwerte sOrgSektion := sSektion; sOrgEintrag := sEintrag; sSektion := Upper(sSektion); sEintrag := Upper(sEintrag); nFound := 0; nChanged := 0; ..inidatei vorhanden? IF IsFile(sIniDatei) = 0 Message(sIniDatei + " nicht gefunden.", "Fehler", 1); Return 0 END ..öffne inidatei IF nFHin := Reset(sIniDatei) > 0 ..erstelle neue inidatei sIniDateiNeu := sIniDatei[1, pos(".", sIniDatei) - 1] + ".rob"; ..tempinidatei löschen ?IsFile(sIniDateiNeu) = 1/ DelFile(sIniDateiNeu); IF nFHout := Rewrite(sIniDateiNeu) < 1 Message(sIniDatei + " kann nicht erstellt werden.", "Fehler", 1); Return 0 END .. inidatei lesen bis ende WHILE NOT Eot(nFHin) sLine := ReadLn(nFHin); sTempLine := sLine;.. original zeile zwischenspeichern sLine := Upper(sLine); ?sLine = sSektion / nFound := 1.. sektion gefunden ..noch nicht gefunden, schreibe originalzeile ?nFound = 0 / WriteLn(nFHout, sTempLine); ..sektion gefunden, aber eintrag nicht, schreibe originalzeile ?nFound = 1 AND sLine[1, Pos("=", sLine) - 1] <> sEintrag / WriteLn(nFHout, sTempLine); ..sektion und eintrag gefunden, wert ändern IF nFound = 1 AND sLine[1, Pos("=", sLine) - 1] = sEintrag WriteLn(nFHout, sOrgEintrag + "=" + sWert); nChanged := 1; nFound := 0; END .. if ..neue sektion erreicht? IF nFound = 1 AND sLine[1] = "[" AND sLine <> sSektion ..eintrag nicht gefunden, schreibe einen neuen IF nChanged = 0 ..schreibe neuen eintrag WriteLn(nFHout, sOrgEintrag + "=" + sWert); nChanged := 1; nFound := 0; ..nicht vergessen, die gelesene zeile zu schreiben WriteLn(nFHout, sTempLine); END .. if END .. if END .. while not eot ..dateiende erreicht, wurde der wert geändert? ..sektion gefunden, aber eintrag nicht (dh sektion ist am dateiende): eintrag neu IF nFound = 1 AND nChanged = 0 WriteLn(nFHout, sOrgEintrag + "=" + sWert); nChanged := 1; END .. sektion und eintrag nicht gefunden: neue sektion IF nChanged = 0 WriteLn(nFHout, ""); WriteLn(nFHout, sOrgSektion); WriteLn(nFHout, sOrgEintrag + "=" + sWert); END .. if ELSE Message(sIniDatei + " nicht gefunden.", "Fehler", 1); Return 0 END Close(nFHin); Close(nFHout); .. .. dateien umbenennen ?IsFile(sIniDateiNeu) = 1/ DelFile(sIniDatei); IF Rename(sIniDateiNeu, sIniDatei) = 0 Message("Kann Datei nicht umbennen."); Return 1 ELSE Return 0 END EndProc Beispielaufruf: Procedure ATest ..#schreibt Werte in eine test.ini SchreibeIniWert ("c:\daten\wintdb\test.ini", "Linn", "Sport", "Triathlon"); SchreibeIniWert ("c:\daten\wintdb\testini", "Kim", "Sport", "Tennis"); Execute("notepad x.ini"); Endproc
|
| Topic Projektanalyse Modul | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Projektanalyse Prozeduren Prozeduren in Projekten einbinden durch hinzufügen folgende Prozeduren: ProjektAnalyse Erstellt die Datei projektname.ana, der eine komplettenProjektbeschreibung liefert, d.h. Tabellenname, Felder, Indices etc. Zeige_ProjektAnalyseReport Run den Windows Notepad auf und zeigt die Analyse Dateiprojektname.ana. Procedure ProjektAnalyse ..#Erstellt die Datei projektname.ana, der eine komplettenProjektbeschreibung liefert, d.h. ..#Tabellenname, Felder, Indices etc. Var CRLF = Chr(13) + Chr(10) Var HEADING = "Projektanalyse"; Var BLANK = " "; Vardef sRepName : String; Vardef nFH : Real; Vardef i, j, k, l, nRT : REAL Vardef s : String; Vardef asFelder : String[100]; .. max 100 felder lesen Vardef sProjektName : String; Vardef nAnzahlTabellen : Real; Vardef nAnzahlIndices : Real; ..sind db's vorhanden If MaxFile = 0 Message("Fehler - Keine Tabellen gefunden.", HEADING); Return End ..ermittle projektdatei, projektverzeichnis angeben, weil uti-panaprojektverzeichnis ..unabhängig ist ..hier wird einen trick verwendet IF MaxFile < 1 Message("Keine Tabellen gefunden, Prozedur wird abgebrochen.",HEADING); Return END ..hole projektverzeichnis, verwender dbdir(1), erste tabelle, fürprojektdir If s := FirstDir(DBDir(1) + "*.TDB", "") sProjektName := DBDir(1) + s[1, Pos(".", s) - 1] End sRepName := sProjektName + ".ANA" ; DelFile(sRepName); ..loesche analysereport i:=j:= 0; nAnzahlTabellen:=nAnzahlIndices:=0; .. öffne reportdatei If nFH := Rewrite(sRepName) > 0 ShowWait("Bitte warten..." + CRLF + "analysiere Projekt " +sProjektName); WriteLn(nFH, "WinTDB - Projektanalyse fuer Projekt " + sProjektName); WriteLn(nFH, ""); WriteLn(nFH, "analysiert am " + DateStr(Today) + " um " + TimeStr(Now) ); While j:=j+1 <= MaxFile i:=0; Writeln(nFH, ""); WriteLn(nFH, "*** Tabelle " + Str(j) +" : " + DBName(j) ); nAnzahlTabellen := nAnzahlTabellen + 1; Writeln(nFH, "Felder:"); ..liste label auf WHILE i:=i+1 <= MaxLabel(j) asFelder[i] := Label(j, i) + nTimes(" ", 40 - Length(Label(j,i) ) ) + GetType(j, i) ; END StrSort(asFelder, MaxLabel(j)); NLoop(i, MaxLabel(j), WriteLn(nFH, BLANK + asFelder[i] ) ); Writeln(nFH, "Anzahl Felder: " + Str(MaxLabel(j)) ); ..liste index auf Writeln(nFH, "Indizes:"); k:=l:=0; Repeat k:=k+1 ..MaxIndex ..Message(Str(MaxFile) + "/" + Str(j) + ": Tabelle " + DBName(j) ); ?IndName(j, k) <> ""/WriteLn(nFH, BLANK + "Index " + Str(k) + ": " + IndName(j, k) + nTimes(" ", 20 - Length(IndName(j,k) ) ) + IndDef(j, k) ); nAnzahlIndices:=nAnzahlIndices+1; Until IndName(j,k) = "" WriteLn(nFH, "Statistik:"); WriteLn(nFH, BLANK + "Anzahl Records: " + Str(FileSize(j)) ); W i e n nFH,BLANK+"Dateiinfos(Name,Groesse,Datum,Zeit,Attribut,Verzeichnis):"); WriteLn(nFH, BLANK + FirstDir(DBDir(j) + DBName(j), "") ); End WriteLn(nFH, ""); WriteLn(nFH, "Gesamt Statistik:"); WriteLn(nFH, "Insgesamt besteht dieses Projekt aus "); WriteLn(nFH, Str(nAnzahlTabellen)+" Tabellen und " +Str(nAnzahlIndices)+" Indices."); WriteLn(nFH, ""); WriteLn(nFH, "Hinweise:"); WriteLn(nFH, "Feldtypen: S)tring xx, N)umerisch, M)emo, A)uswahl...") WriteLn(nFH, "mehr Info siehe TDB - Hilfe oder Handbuch.") Close(nFH) HideWait; ?IsFile(sRepName) = 1/Message("Projektanalysereport " + sRepName + " erstellt.", "Utility"); HideWait; End Endproc Procedure Zeige_ProjektAnalyseReport Vardef sRepName : String; Vardef s : String; ..ermittle projektdatei If s := FirstDir(DBDir(1) + "*.TDB", "") <> "" sRepName := DBDir(1) + s[1, Pos(".", s) - 1] + ".ANA" ; End Execute("NotePad " + sRepName); Endproc
|
| Topic Datum- und Zeitfunktionen | Kapitel easy Funktionsbibliothek |
|
Beschreibung: In den folgenden Prozeduren sind eine Reihe von Möglichkeiten im Bezug auf Datum und Zeit aufgeführt. In der Prozedur DatumsInfo sind ein paar Spielereien mit dem Datum und Zeit zu sehen. Sind viele Berechnungen nötig, dann können einzelnen Berechnungen als easy-Funktion definiert werden. Procedure WoTagNr (sDatum : String) : Real; ..#Wochentagnr. ermitteln ..#Parameter: ..#sDatum = Datum als String Return (Pos(DayOfWeek(Val(sDatum))[1, 2],"MoDiMiDoFrSaSo") + 1) / 2 ; Endproc Procedure MonatsName(nMnt : Real): String; ..#Monatsname ermitteln ..#Paramter: ..#nMnt = Monatsnummer Vardef nTmp : String; nTmp := ""; ?(nMnt > 0) AND (nMnt < 13) / nTmp := Choice(nMnt, "Januar","Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November","Dezember") Return nTmp Endproc Procedure MonatsNameAusDatum(sDatum : String) : String; ..#Monat als String Jan, Feb .. ..#Parameter: ..#sDatum = Datum als String Vardef nTmp : String; Return Choice(Month(Val(sDatum)), "Jan", "Feb", "Mär", "Apr", "Mai","Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"); Endproc Procedure Date2Real(sDatum : String) : Real ..#Umwandlung Datum als String in Real ..#Parameter: ..#sDatum = Datum als String Return Val(sDatum) Endproc Procedure Time2Real(sTime : String) : Real ..#Umwandlung Zeit als String in Real ..#Parameter: ..#sTime = Zeit als String Return Val(sTime) Endproc Procedure DatumsInfo ..#Beispiel mit oben beschriebene Prozeduren und vieles mehr DEF CRLF = Chr(13) + Chr(10) Vardef nTotZeit : Real; Vardef nTmp : String; Vardef nWoTagNr : Real; Vardef nNoMntTage : Real; Vardef nJahresTagNr : Real; Vardef sDatum : String; Vardef sMonat : String; Vardef nKalWoche : Real; Vardef nSchaltJahr, nTageImJahr : Real; Var sInfo = ""; .. datum speichern, ermöglicht flexibele berechnungen sDatum := DateStr(Today); .. oder z.B. "09.8.1996" ..wochentagnummer nWoTagNr := (Pos(DayOfWeek(Val(sDatum))[1, 2],"MoDiMiDoFrSaSo") + 1) /2 ; ..jahrestagnummer nJahresTagNr := (Week(Val(sDatum)) * 7) - (7 - nWoTagNr); ..anzahl tage im Jahr nTmp := (Pos(DayOfWeek(Val("31.12." +sDatum[7,4]))[1,2],"MoDiMiDoFrSaSo") + 1) / 2 ; nTageImJahr := (Week(Val("31.12." + sDatum[7,4])) * 7) - (7 - nTmp); ..anzahl monatstage nNoMntTage := 31; IF sDatum[4,2]<>"12" nNoMntTage :=Val(DateSt(Val("01."+Str(VAL(sDatum[4,2])+1)+"."+sDatum[7,4])-1)[1,2] ); END .. schaltjahr ? nSchaltJahr := 0; .. nein oder doch IF DateStr( VAL("01.03." + sDatum[7,4]) - 1)[1,2] = "29" ..eb 29 dannschaltjahr nSchaltJahr := 1; .. ja END .. monat als string Jan, Feb .. sMonat := Choice(Month(Val(sDatum)), "Jan", "Feb", "Mär", "Apr","Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"); .. welche kalenderwoche nKalWoche := Week(Val(sDatum)); .. info zum test ausgeben sInfo := sInfo + "Tag: " + DayOfWeek(Val(sDatum)) + " Nr: " +Str(nWoTagNr) + " JTagNr: " + Str(nJahresTagNr) + CRLF; sInfo := sInfo + "Monat: " + sMonat + " Nr:" + Str(Month(Val(sDatum)))+ " Tage: " + Str(nNoMntTage) + CRLF; sInfo := sInfo + "Woche Nr:" + Str(nKalWoche); Message(sInfo, "Heute ist " + DateStr(Val(sDatum)) ); ..zeit addieren nTotZeit := Val("05:22") + Val("58:44"); Message("Totale Spieldaur: " + Str(nTotZeit DIV 60) + ":" + Str(nTotZeit MOD 60)); Endproc Procedure Monate_Seit_Heute Vardef nDatum, nMonthCount : Integer; T-Eingabe := DateStr(Today); Input("Datum"); SetPara('ec 1'); nDatum := VAL(T-Eingabe); SetPara('ec 0') IF nDatum >= 1.1.1900 And nDatum <= 31.12.2099 nMonthCount := Month(today)-Month(nDatum)+((Year(today)-Year(nDatum))*12) Message("Monate seit '" + T-Eingabe + "' = " + Str(nMonthCount)); ELSE Message("Datum '" + T-Eingabe + "' ist NICHT gültig...") END EndProc;
|
| Topic Tabelleninhalt löschen und Autonummer zurücksetzen | Kapitel easy Funktionsbibliothek |
|
Beschreibung: aktuelle Datenbank komplett löschen und anschließen die Autonummer(=Laufende_Nummer) auf 1 setzen. Procedure ResetDat ..#aktuelle Datenbank komplet löschen und die Autonummer auf 1 setzen ClearDat(FileNr) SetAuto(Filenr,1) Endproc ..#zweite variante mit parameter Procedure ResetDat(nFileNr : Real); ..#Datenbank komplet löschen und die Autonummer auf 1 setzen ..#Parameter: ..#nFileNr = Datenbanknummer ClearDat(nFileNr) SetAuto(nFilenr,1) Endproc
|
| Topic Taschenrechner | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Eine kleine Spielerei mit VAL Procedure Taschenrechner : Real; Vardef sFrage : String; sFrage := ""; Input(sFrage, "Taschenrechner"); Return Val(T-Eingabe) Endproc Eine kleine Rechenspielerei. Procedure Taschenrechner(A, B : Real) Vardef sFrage : String; sFrage := Str(A) + " mal " + Str(B) + " ist?"; Input(sFrage, "Rechentest"); If Val(T-Eingabe) ist A * B Message("Sehr gut!") Else Message("Ist leider nicht richtig!"); End Endproc
|
| Topic Fortschreitungsanzeige (Progessbar) | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Ausgabe eine Fortschreitungsanzeige Procedure UProgressbar(nArt : Real; sMeldung : String; nMax : Real; nAct : Real); ..#Darstellung ein Fortschreitungsanzeige ..#Parameter: ..#nArt: 1 = balken, 2 = % DEF CRLF = Chr(13) + Chr(10); DEF nPMax = 100; DEF sDEL = Chr(219) Vardef sTmp : String; Vardef i, k, f : Real; f := nMax / nPMax; ?f = 0 / f := 1; k := Int(nAct / f); If nArt = 1 sTmp := ""; nLoop(i, k, sTmp := sTmp + Chr(219)); ShowWait(sMeldung + CRLF + sTmp); End ?nArt = 2/ShowWait(sMeldung + CRLF + Str(k,1,0) + "%"); Endproc
|
| Topic Direkte Bearbeitung von Datensätze einer angekoppelte Tabelle in einem Formular | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Folgende 3 Prozeduren ermöglichen eine direkte Bearbeitung von Datensätze einer eingebettete Tabelle. Die Prozeduren können mittels Makro-Schalter aus einem Formular aufgerufen werden. Procedure DatensatzLöschen(nAktRec : Real); ..#Datensatz löschen ..#Parameter: ..#nAktRec = aktueller Datensatz If nAktRec > 0 ?Message("Satz wirklich löschen?", "Satz löschen", 3) = 6 /DelRec(TABELLE, nAktRec); End Endproc Procedure DatensatzBearbeiten(nAktRec : Real) : Real; ..#Datensatz bearbeiten ..#Parameter: ..#nAktRec = aktueller Datensatz Vardef nRT : Real; If nAktRec = 0 / Return 0 DatensätzeBearbeiten("TABELLE.Formular"); Readrec(TABELLE, nAktRec); nRT := EditRec("Ändern Sie die Angaben. Abbruch mit ESC."); CloseWnd; Return nRT Endproc Procedure DatensatzNeu(nDummy : Real); ..#Neuer Satz anlegen ..#Parameter: ..#nDummy = damit die Prozedur nicht in der Makroliste erscheint Vardef nRNo, nAktRec : Real; nAktRec := ReadRec(PRIMTABELLE, RecNr(PRIMTABELLE)); If nAktRec > 0 ReadRec(TABELLE, 0); TABELLE.tFeld1 := "<Neu>"; Writerec(TABELLE, 1 + FileSize(TABELLE)); End nRNo := FindRec(TABELLE, Str(TABELLE.Laufende_Nummer), "TABELLE.INR",1); If nRNo > 0 ?EditSatz(nRNo) = 0 / DelSatz(nRNo); End Endproc
|
| Topic Verschiedene Prozeduren die Dateioperationen durchführen | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Verschiedene Prozeduren die Dateioperationen durchführen. Procedure pAskForFile(sFrage, sHeading, sVorgabe : String) : String; ..#Datei abfragen ..#Parameter: ..#sFrage = Fragenstellung, welche Datei ..#sHeading = Fensterüberschrift ..#sVorgabe = Vorgabe Dateiname ..#Returnwert: ..#Dateiname Vardef nRT : Real; T-Eingabe:= sVorgabe; REPEAT nRT := Input(sFrage, sHeading); If nRT = 0 .. abbruch im input fenster Return "" End If IsFile(T-Eingabe) = 1 .. datei vorhanden nRT := Message("Datei existiert bereits! Überschreiben?","Achtung",4) ?nRT = 6 / nRT := 0 .. Ja If nRT = 2 .. Abbruch Return "" End End ?IsFile(T-Eingabe) = 0 / nRT := 0; .. datei nicht vorhanden UNTIL nRT = 0 Return T-Eingabe Endproc Procedure pSelectTDBFile(nDummy : Real) : String; ..#Auswahl eines tdb-Projektes ..#Parameter: ..#nDummy = 0 damit diese Prozedur nicht in der Liste der Prozedurenerscheint. ..#Returnwert: ..#TDB-Projektdateiname T-Eingabe := "*.TDB"; If ChooseFile("TDB-Projekt auswählen") = 1 Return T-Eingabe; Else Return ""; End Endproc Procedure pFileOfDir(sPath:STRING) : STRING; ..#Dateiname aus dem kompletten Pfad auslesen ..#Parameter: ..#sPath = Pfadangabe ..#Returnwert: ..#Dateiname Vardef sSep : STRING; sSep:=Choice(Sel(sPath:=Exchange(sPath," ","") HAT "\"),"\",":") Repeat Until Not sPath:=Right(sPath,Length(sPath) - POS(sSep,sPath)) Hat sSep Return sPath Endproc Procedure pDirOfPath(sPath:String) : String; ..#Verzeichnis aus dem kompletten Pfad auslesen ..#Parameter: ..#sPath = Pfadangabe ..#Returnwert: ..#Verzeichnisname Return sPath[1, Length(sPath) - Length(pFileOfDir(sPath)) ] ; Endproc Procedure pFileFromPath(sPath:String):String ..#Dateiname aus dem kompletten Pfad auslesen ..#Parameter: ..#sPath = Pfadangabe ..#Returnwert: ..#Dateiname aus Pfadangabe Vardef sSep : String; sSep:=Xwert(Sel(sPath:=Exchange(sPath," ","") Hat "\"),"\",":") Repeat Until Nicht sPath:=Right(sPath,Length(sPath) - Pos(sSep, sPath)) HatsSep Return sPath Endproc Procedure pCurDrive(nDummy : Real) : String; ..#Dateiname aus dem kompletten Pfad auslesen ..#Parameter: ..#nDummy = 0 damit diese Prozedur nicht in der Liste der Prozedurenerscheint. ..#Returnwert: ..#aktuellen Laufwerks Return GetDir(0)[1,2] Endproc Procedure pDrivePath(sDrive : String) : String; ..#gesetzen Pfades für Laufwerk sDrive ..#Parameter: ..#sDrive = Laufwerk A, B, C ... ..#Returnwert: ..#gesetzen Pfades für Laufwerk sDrive Vardef nDrive : Real; Xwert(Sel(nDrive:=ASC(GROß(LTRIM(sDrive)[1])) VON 65 BIS90),nDrive:=nDrive - 64,nDrive:=0) sDrive := GetDir(nDrive); Return XWERT(Sel(RECHTS(sDrive,1)="\"), sDrive, XWERT(SEL(sDrive),sDrive + "\","")) Endproc Procedure pFileDate(sFile : String) : String; ..#Dateidatum und Zeit ermitteln ..#Parameter: ..#sFile = Dateiname ..#Returnwert: ..#Dateidatum und Zeit Return FirstDir(sFile, "")[27, 17] Endproc Procedure pCheckPath(sPath : String) : String; ..#Pfades mit \ abgeschlossen zurückgeben ..#Parameter: ..#sPath = Pfadangabe ..#Returnwert: ..#Pfades mit \ abgeschlossen If sPath[Length(sPath)] <> "\" Return sPath + "\" Else Return sPath End Endproc
|
| Topic Hex-Wert in ein String umwandeln | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Hex-Wert in ein String umwandeln. Procedure pHexToStr(sHex : String) : String; ..#Umwandlung eines Hex-Wertes in ein String ..#Parameter: ..#sHex = Hex-Wert als String ..#Returnwert: ..#Hex-Wert als String Vardef x : Real; x := xWert(Asc(sHex[2]) -48,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,0,10,11,12,13,14,15) * 16 ; x := x + xWert(Asc(sHex[3]) -48,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,0,10,11,12,13,14,15); Return AnsiToOEM( Chr(x) ) Endproc
|
| Topic Projektanalyseprozeduren | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Die Prozeduren erstellen eine komplette Projektanalyse. Die Prozedureneinbinden in Projekten durch hinzufügen derProzeduren: ProjektAnalyse: Erstellt die Datei projektname.ana, der einekompletten Projektbeschreibung liefert, d.h. Tabellenname, Felder, Indices etc. Zeige_ProjektAnalyseReport: Zeigt Analyse Datei projektname.ana imNotepad Procedure ProjektAnalyse ..#analysiert ein bestehendes projekt Var CRLF = Chr(13) + Chr(10) Var HEADING = "Projektanalyse" Var BLANK = " " Vardef sRepName : String; Vardef nFH : Real; Vardef i, j, k, l, nRT : REAL Vardef s : String; Vardef asFelder : String[100];.. max 100 felder koennen gelesen werden Vardef sProjektName : String; Vardef nAnzahlTabellen : Real; Vardef nAnzahlIndices : Real; ..sind db´s vorhanden If MaxFile = 0 Message("Fehler - Keine Tabellen gefunden.", HEADING); Return End ..ermittle projektdatei ..projektverzeichnis angeben, weil uti-pana projektverzeichnisunabhängig ist ..hier wird ein trick verwendet IF MaxFile < 1 Message("Keine Tabellen gefunden, Prozedur wird abgebrochen.",HEADING) Return END ..hole projektverzeichnis, verwender dbdir(1), erste tabelle, fürprojektdir If s := FirstDir(DBDir(1) + "*.TDB", "") sProjektName := DBDir(1) + s[1, Pos(".", s) - 1] End sRepName := sProjektName + ".ANA" ; DelFile(sRepName); ..loesche analysereport i:=j:= 0; nAnzahlTabellen:=nAnzahlIndices:=0; ..öffne reportdatei If nFH := Rewrite(sRepName) > 0 ShowWait("Bitte warten..." + CRLF + "analysiere Projekt " +sProjektName); WriteLn(nFH, "WinTDB - Projektanalyse fuer Projekt " + sProjektName); WriteLn(nFH, ""); WriteLn(nFH, "analysiert am " + DateStr(Today) + " um " +TimeStr(Now) ); While j:=j+1 <= MaxFile i:=0; ..Message(Str(MaxFile) + "/" + Str(j) + ": Tabelle " + DBName(j) ); Writeln(nFH, ""); WriteLn(nFH, "*** Tabelle " + Str(j) +" : " + DBName(j) ); nAnzahlTabellen := nAnzahlTabellen + 1; Writeln(nFH, "Felder:"); ..liste label auf WHILE i:=i+1 <= MaxLabel(j) asFelder[i] := Label(j, i) + nTimes(" ", 40 - Length(Label(j,i) ) )+ GetType(j, i) ; END StrSort(asFelder, MaxLabel(j)); NLoop(i, MaxLabel(j), WriteLn(nFH, BLANK + asFelder[i] ) ); Writeln(nFH, "Anzahl Felder: " + Str(MaxLabel(j)) ); ..Liste index auf Writeln(nFH, "Indizes:"); k:=l:=0; Repeat k:=k+1 .. MaxIndex ..Message(Str(MaxFile) + "/" + Str(j) + ": Tabelle " + DBName(j)); If IndName(j, k) <> "" WriteLn(nFH,BLANK + "Index " + Str(k) + ": " + IndName(j, k) +nTimes(" ", 20 - Length(IndName(j,k) ) ) + IndDef(j, k) ); End nAnzahlIndices:=nAnzahlIndices+1; Until IndName(j,k) = "" WriteLn(nFH, "Statistik:"); WriteLn(nFH, BLANK + "Anzahl Records: " + Str(FileSize(j)) ); WriteLn(nFH, BLANK + "Dateiinformationen (Name, Groesse, Datum,Zeit, Attribut, Verzeichnis):"); WriteLn(nFH, BLANK + FirstDir(DBDir(j) + DBName(j), "") ); End WriteLn(nFH, ""); WriteLn(nFH, "Gesamt Statistik:"); WriteLn(nFH, "Insgesamt besteht dieses Projekt aus: "); WriteLn(nFH, Str(nAnzahlTabellen) + " Tabellen und " +Str(nAnzahlIndices) + " Indices."); WriteLn(nFH, ""); WriteLn(nFH, "Hinweise:"); WriteLn(nFH, "Feldtypen: S)tring xx, N)umerisch, M)emo, A)uswahl...") WriteLn(nFH, "mehr Info siehe TDB - Hilfe oder Handbuch.") Close(nFH) HideWait; If IsFile(sRepName) = 1 Message("Projektanalysereport " + sRepName + " erstellt.","Utility"); End HideWait; End Endproc Procedure Zeige_ProjektAnalyseReport ..#zeigt die erastellte Datei mittels Notepad Vardef sRepName : String; Vardef s : String; ..ermittle projektdatei If s := FirstDir(DBDir(1) + "*.TDB", "") <> "" sRepName := DBDir(1) + s[1, Pos(".", s) - 1] + ".ANA" ; End Execute("NotePad " + sRepName); Endproc
|
| Topic E-Mail-Adresse auf Richtigkeit hin überprüfen | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Diese Funktion stammt aus dem Beispiel WEBGAST, welches dem Produkt VDP 2.0 beiliegt. Der Funktion ValidEmail wird ein String mit der zu überprüfenden Mailadresse übergeben. Die Funktion liefert 0 (null) zurück, wenn die Minimalanforderungen erfüllt sind. Ansonsten werden je nach Problem die Werte 1 bis 4 zurückgegeben (nähere Erläuterung siehe "Rückgabewerte"). PROCEDURE ValidEmail(EMAIL:String):REAL ..#Beschreibung: ..#Test auf gültige E-Mail Adresse ..#Es wird dazu die Minimalanforderung geprüft. ..#1. nur ein @-Zeichen und dieses nicht als erstes Zeichen ..#2. es ist mindestens ein Punkt nach dem @-Zeichen, wobei der erste ..#Punkt nicht direkt nach dem @ folgen darf ..#Rückgabewerte: ..#0 - Adresse gültig ..#1 - kein @ oder an erster Stelle ..#2 - zweites @ im String ..#3 - kein Punkt oder direkt nach dem @ ..#4 - letztes Zeichen ist @ oder Punkt VARDEF AT:REAL; AT:= Pos("@", EMAIL); IF AT << 2 .. Kein @ oder an erster Stelle RETURN 1 END .. Teilstring nach dem @ EMAIL:= RightStr(EMAIL, Length(EMAIL) - AT); IF Pos("@", EMAIL) <> 0 .. Zweites @ vorhanden RETURN 2 END IF Pos(".", EMAIL) << 2 .. Kein Punkt oder an erster Stelle RETURN 3 END EMAIL:= RightStr(EMAIL, 1); IF EMAIL = "." or EMAIL ="@" .. letztes Zeichen ist Punkt oder @ RETURN 4 END .. Minimalanforderung erfüllt RETURN 0 ENDPROC
|
| Topic Debug-Prozedur für Module | Kapitel easy Funktionsbibliothek |
|
Beschreibung: die Prozedur WriteToLog in Module einbinden. Es wird eine Datei erstellt, welche dann mit Strings beschrieben werden kann. PROCEDURE WriteToLog(sLogFile: STRING; sStr : STRING; nLogNeu : REAL); ..#schreibt String sStr in eine Logdatei sLogFile ..#Parameter: ..#sLogFile = Logdatei ..#sStr = Eintrag in der Logdatei ..#nLogNeu: 0 = erstelle neue Logdatei ..#Beispielaufruf: ..# WriteToLog("Projekt.log", "START p.MyProc um " + DateStr(Today) + "" + TimeStr(Now), 0); DEF HEADING = "Debug"; VARDEF nFH : Real; ..#neue logdatei erstellen, wenn nLogFirst = 1 IF nLogNeu = 1 ?IsFile(sLogFile) = 1 / DelFile(sLogFile); END ..#logdatei öffnen, erst prüfen ob logdatei vorhanden ist. IF IsFile(sLogFile) = 0 .. logdatei nicht da, erstelle neu IF nFH:=Rewrite(sLogFile) < 1 Message("Logdatei " + sLogFile + " kann nicht neu erstellt werden.",HEADING); Halt; END WriteLn(nFH,"Logstart um " + DateStr(ToDay) + " " + TimeStr(Now)); Close(nFH); END ..#logfile schon da? IF IsFile(sLogFile) = 1 IF nFH:=TAppend(sLogFile) < 1 Message("Kann Logdatei " + sLogFile + " nicht öffnen...", HEADING); Halt; END END WriteLn(nFH,TimeStr(Now) + " : " + sStr); CLOSE(nFH); ENDPROC PROCEDURE BeispielWriteToLog(nDummy : Real); ..#Beispiel: Eintragung in der Logdatei WriteToLog("Projekt.log", "Starte p. Test", 1); .. neue logdatei ..#Schritt 1 WriteToLog("Projekt.log", "Ende Schritt 1...", 0); .. hinzufügen ..#Schritt 2 WriteToLog("Projekt.log", "Ende Schritt 2...", 0); ENDPROC PROCEDURE ZeigeLogDatei(nDummy : Real); ..#Aufruf Logdatei mittels Windows NotePad Execute("NotePad.exe Projekt.Log"); ENDPROC
|
| Topic Paßwort Abfrage | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Es gibt eine Reihe von Möglichkeiten Passworte abzufragen. Nachfolgend eine einfache Lösung. Die Benutzernamen und Passworte sind in der Tabelle SYSUSER gespeichert. Felder sUsername und sPasswort. Procedure BenutzerZulassen(nAktRNo : Real) : Real; ..#Benutzer zulassen ..#Parameter: ..#nAktRNo = aktueller Datensatz ..#Returnwert: ..#liefert 1 wenn Ok, sonst 0 ..#Aufrufbeispiel: ..#BenutzerZulassen(RecNo(KASSE)) Vardef nRT, nRNo : Real; Vardef nUsername, nPasswort : String; nRT := INPUT("Geben Sie Ihre Benutzername ein.","Benutzername", 0); ?nRT = 0 / Return 0 nUsername := T-Eingabe; nRT := INPUT("Geben Sie Ihr Passwort ein.","Passwort", 1); ?nRT = 0 / Return 0 nPasswort := T-Eingabe; nRNo := FindRec(SYSUSER, nUsername + "," + nPasswort,"SYSUSER.IND",1); If nRNo = 0 Message("Passwort oder Benutzername nicht richtig!", "FehlerAnmeldung"); Return 0 End nRNo := ReadRec(SYSUSER, nRNo); If nRNo > 0 nName := SYSUSER.sUsername; ReadRec(KASSE, nAktRNo); KASSE.Einnehmer := nName Writerec(KASSE, nAktRNo); Attach Return 1 Else Message("Falscher Code", "Fehler"); Return 0 End Endproc
|
| Topic Beispiel zu MitBedingung | Kapitel easy Funktionsbibliothek |
|
Beschreibung: ein Beispiel für kombinierte MitBedingung-Suche PROCEDURE Starte_Suchassistent ..#ein Beispiel für kombinierte MitBedingung-Suche ..#Parameter: ..#keine ..#Returnwert: ..#keine VarDef nCount : REAL; IF EXECDIALOG("DIALOG.Suchassistent")=1 SetSortOrder("ADRESSEN.ID") ReadRec( DIALOG,1) If DIALOG.ID-Name#"" DIALOG.ID-Name := UPPER(DIALOG.ID-Name) IF MitBedingung("UPPER(ADRESSEN.ID-Name) "+CHOICE(DIALOG.A-ID-Name,"=","hat","wie","ungleich")+" '"+DIALOG.ID-Name+"'",1,2)>0 SetSortOrder("ADRESSEN.ID",2) ELSE Message("Keine passenden Einträge gefunden", "ID-Name"+DIALOG.ID-Name) END END If DIALOG.Firma#"" DIALOG.Firma := UPPER(DIALOG.Firma) IF MitBedingung("UPPER(ADRESSEN.Firma) "+CHOICE(DIALOG.A-Firma,"=","hat","wie","ungleich")+" '"+DIALOG.Firma+"'",1,2)>0 SetSortOrder("ADRESSEN.ID",2) ELSE Message("Keine passenden Einträge gefunden","Firma "+DIALOG.Firma) END END If DIALOG.Name#"" DIALOG.Name := UPPER(DIALOG.Name) IF MitBedingung("UPPER(ADRESSEN.Name) "+CHOICE(DIALOG.A-Name,"=","hat","wie","ungleich")+" '"+DIALOG.Name+"'",1,2)>0 SetSortOrder("ADRESSEN.ID",2) ELSE Message("Keine passenden Einträge gefunden","Name "+DIALOG.Name) END END If DIALOG.Straße#"" DIALOG.Straße := UPPER(DIALOG.Straße) IF MitBedingung("UPPER(ADRESSEN.Straße) "+CHOICE(DIALOG.A-Straße,"=","hat","wie","ungleich")+" '"+DIALOG.Straße+"'",1,2)>0 SetSortOrder("ADRESSEN.ID",2) ELSE Message("Keine passenden Einträge gefunden","Straße"+DIALOG.Straße) END END If DIALOG.Ort#"" DIALOG.Ort := UPPER(DIALOG.Ort) IF MitBedingung("UPPER(ADRESSEN.Ort) "+CHOICE(DIALOG.A-Ort,"=","hat","wie","ungleich")+"'"+DIALOG.Ort+"'",1,2)>0 SetSortOrder("ADRESSEN.ID",2) ELSE Message("Keine passenden Einträge gefunden","Ort "+DIALOG.Ort) END END If DIALOG.Land#"" DIALOG.Land := UPPER(DIALOG.Land) IF MitBedingung("UPPER(ADRESSEN.Land) "+CHOICE(DIALOG.A-Land,"=","hat","wie","ungleich")+" "+DIALOG.Land+"'",1,2)>0 SetSortOrder("ADRESSEN.ID",2) ELSE Message("Keine passenden Einträge gefunden","Land "+DIALOG.Land) END END If DIALOG.Branche#"" DIALOG.Branche := UPPER(DIALOG.Branche) IF MitBedingung("UPPER(ADRESSEN.Branche) "+CHOIE(DIALG.A-Branche,"=","hat","wie","ungleich")+"'"+DIALOG.Branche+"'",1,2)>0 SetSortOrder("ADRESSEN.ID",2) ELSE Message("Keine passenden Einträge gefunden","Branche"+DIALOG.Branche) END END IF nMarks(FileNr)=0 Message("Keine passenden Einträge gefunden") END END ENDPROC
|
| Topic Felder von Tabelle zu Tabelle kopieren | Kapitel easy Funktionsbibliothek |
|
procedure CopyMemoTab2Tab ..#kopiert ein Memofeld von Tabelle1 zu Tabelle2 ..#Tabelle 2 ist mittels ein Koppelfeld (Tabelle2.Koppelfeld) mit Tabelle 1 verbunden. ..#es könne auch andere Felder kopiert werden. dann die suchroutineanpassen. DEF TMPMEMO = DBDir(TABELLE1) + "memo.tmp"; vardef nRNoT1, nRNoT2 : real; vardef nLNT1, nLNT2 : real; ..aufende_nummer der tabelle ..zugriff tab1 auf laufende_nummer setzen Access(TABELLE1, "TABELLE1.INR"); ..loope durch die tabelle1 nRNoT1 := FirstRec(TABELLE1); WHILE nRNoT1 > 0 ..lese record und speichere laufende_nummer der tabelle 1 ReadRec(TABELLE1, nRNoT1) nLNT1 := TABELLE1.Laufende_Nummer; ..suche zugehörige record in tab2 ..möglichkeit 1: ..hierbei wird als der index mit koppeldfeld information verwendet nRNoT2 := FindRec(TABELLE2, Str(nLNT1), "TABELLE2.IN1", 1); If nRNoT2 > 0 ReadRec(TABELLE2, nRNoT2); ?IsFile(TMPMEMO) / DelFile(TMPMEMO); CopyMemo(TABELLE2.Tab2Memo, TMPMEMO); ReadMemo(TABELLE1.Tab1Memo, TMPMEMO, 0) WriteRec(TABELLE1, nRNoT1) ?IsFile(TMPMEMO) / DelFile(TMPMEMO); End ..möglichkeit 2: ..hierbei wird durch die tabelle 2 gelooped nRNoT2 := FirstRec(TABELLE2); WHILE nRNoT2 > 0 ReadRec(TABELLE2, nRNoT2); If TABELLE2.Koppelfeld = nLNT1 ?IsFile(TMPMEMO) / DelFile(TMPMEMO); CopyMemo(TABELLE2.Tab2Memo, TMPMEMO); ReadMemo(TABELLE1.Tab1Memo, TMPMEMO, 0) WriteRec(TABELLE1, nRNoT1) nRNoT2 := NextRec(TABELLE2); ?IsFile(TMPMEMO) / DelFile(TMPMEMO); End End nRNoT1 := NextRec(TABELLE1); END .. WHILE Stamm endproc
|
| Topic Job- und Module-Kompilierungsprozeduren | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Verschiedene Prozeduren um Module und Jobs neu zu übersetzen (kompilieren). Procedure XCompile(sMod : String); ..#kompiliert ein Module ..#Parameter: ..#sMod = Modulname Vardef nRT : Real; ?IsFile(sMod) = 0 / Return ShowWait( "Compiliere " + sMod + "..."); IF nRT := Compile( sMod) <> 0 IF Message( 'Fehler ' + Str(nRT,1,0) + "/" + Str($Fehler) + ' inModul/Job: ' + sMod, 'Compile', 2) = 2 HideWait; Return END Else ..Message(sMod+ ' erfolgreich übersetzt.', "Hinweis"); Return END; Endproc Procedure DoCompileAllMods ..#kompiliert alle Module im aktuellen Projektverzeichnis Vardef sTmp: String; sTmp := FirstDir("*.MOD", ""); WHILE sTmp <> "" XCompile(sTmp[1, 12]); sTmp := NextDir; END Endproc Procedure DoCompileAllJobs ..#kompiliert alle Jobs im aktuellen Projektverzeichnis Vardef sTmp: String; sTmp := FirstDir("*.JOB", ""); WHILE sTmp <> "" XCompile(sTmp[1, 12]); sTmp := NextDir; END Endproc ..#die beiden module können auch in ein zusammengefaßt werden Procedure DoCompileAll(sPath : String) ..#kompiliert alle Jobs im aktuellen Projektverzeichnis ..#Parameter: ..#sPath = Pfadangabe, zB *.JOB oder *.MOD Vardef sTmp: String; sTmp := FirstDir(sPath, ""); WHILE sTmp <> "" XCompile(sTmp[1, 12]); sTmp := NextDir; END Endproc
|
| Topic Updates mit Strukturänderung durchführen | Kapitel easy Funktionsbibliothek |
|
..Info ..für alle, die beim Kunden Projekte laufen haben und Updates mit Strukturänderung ..durchführen wollen: ..Diese Routine geht davon aus, daß im Unterverzeichnis eine komplette Kopie aller ..Dateien liegen. Ob das Update durchgeführt wird, entscheidet die Existenz einer Datei ..namens UPDATE.INI ..Update.ini beinhaltet in der 2. Zeile die Revisionsnummer des Updates ..Aufbau UPDATE.INI ..[Update] ..Rev=1 ..Update.ini wird noach dem Update umbenannt. ..Importiert werden alle Felder, auch die Memofelder, auch kaputte Quelldateien mit ..Laufende_Nummer=0 werden dabei korrigiert. ..viel Spaß H. Götz ..Modul für Tabelle EINSATZ ..01.12.1999 ..procedure Daten_einlesen ..falls die Quelldatei Laufende_Nummer=0 enthält muß ..mit einer vereinfachten Importroutine gearbeitet werden ..ob die Importroutine korrekt arbeitet, wenn man nur über dieRecord-Nummer ..geht anstelle der Lfd weiß ich derzeit nicht sicher. ..Bei einfacheren Strukturen sicherlich, bei komplexen Verknüpfungenmuß ..noch getestet werden .NB 1 PROCEDURE Datensatz_anhängen(nDat, nDB : REAL) VarDef c : STRING VarDef j, nF : REAL ReadRec( nDat,0) j := 1 REPEAT c := Label( nDat,j) IF LabelNo( nDB, c)>0 IF GetType( nDat, j)[1] # "M" SetField( nDat, j, GetField( nDB, LabelNo( nDB,c))) END END j := j+1 UNTIL j > MaxLabel(nDat) nF := FileSize( nDat)+1 WriteRec( nDat, nF) ReadRec( nDat, nF) j := 1 REPEAT c := Label( nDat,j) IF LabelNo( nDB, c)>0 IF GetType( nDat, j)[1] = "M" PrimFile( nDB) DO _'CopyMemo('+c+' ,"RAMTEXT")' PrimFile( nDat) DO _'ReadMemo( '+c+',"RAMTEXT",1)' PrimFile( nDB) END END j := j+1 UNTIL j > MaxLabel(nDat) ENDPROC PROCEDURE Daten_einlesen( nDat : REAL; cDat : STRING) ..01.12.1999 / Götz VarDef nF, nDB, nRec, nFI,j,i : REAL VarDef aLfd : REAL[5000] VarDef c : STRING Showwait("Programmupdate wird durchgeführt"+CHR(13)+DBNAME(nDat) +"wird zurückgelesen") nDB := OpenDB(cDat,"",0,0) IF nDB >0 PrimFile( nDB) ACCESS( nDB, IndName( nDB,0)) ReadRec( nDB, FirstRec( nDB)) ..falls die Quelldatei Laufende_Nummer=0 enthält muß ..mit einer vereinfachten Importroutine gearbeitet werden ..ob die Importroutine nicht korrekt arbeitet, ..wenn man nur über die Record-Nummer geht anstelle der Lfd weiß ich ..derzeit nicht sicher. ..Bei einfacheren Strukturen sicherlich, bei komplexen ..Verknüpfungen muß noch getestet werden IF FileSize( nDB)>0, GetField( nDB, LabelNo( nDB,"Laufende_Nummer"))="0" Message("Die Backupdatei erhält einen Eintrag mit Laufender_Nummer=0"+CHR(13)+"Die Einträge werdenkorrigiert","Warnhinweis zu "+DBNAME(nDB)) nRec := FirstRec( nDB) WHILE nRec >0 ReadRec( nDB, nRec) Datensatz_anhängen(nDat, nDB) nRec := NextRec( nDB) END ELSE nRec := FirstRec( nDB) i := 0 WHILE nRec >0 ReadRec( nDB, nRec) aLfd[i] := VAL( GetField( nDB, LabelNo( nDB, "Laufende_Nummer"))) i := i+1 nRec := NextRec( nDB) END aLfd[i] := 0 i := 0 WHILE aLfd[i] >0 ReadRec( nDB, FindRec(nDB, STR( aLfd[i]),IndName( nDB, 0))) Datensatz_anhängen(nDat, nDB) i := i+1 END CloseDB(nDB) END ELSE Message("kann Datei nicht öffnen",cDat) END ENDPROC PROCEDURE Alte_Einträge_löschen( nDat : REAL) ..01.12.1999 / Götz Showwait("Alte Einträge werden entfernt") ClearDat( nDat ) WHILE FileSize( nDat )>0 Delrec( nDat , FirstRec( nDat )) END SetAuto( nDat ,1) ENDPROC procedure Programm_aktuallisieren ..01.12.1999 / Götz VarDef nRev, nDatei, nRec, nFI,j : REAL VarDef nMaxFile : REAL VarDef aLfd : REAL[5000] VarDef c : STRING nMaxFile := Maxfile IF ISFILE("UPDATE.INI")=0 HALT Message("UPDATE.~NI wird zurück in UPDATE.INI umbenannt","Update wird fortgesetzt") Rename("UPDATE.~NI","UPDATE.INI") END nFI := Reset("UPDATE.INI") c := ReadLn(nFI) c := LTRIM(RTRIM( c[5,10] )) nRev := VAL(c) Close(nFI) Showwait("Ihr Programm wird aktuallisiert"+CHR(13)+"Revision"+STR(nRev)) nDatei := 1 REPEAT Showwait("Aktuallisiere "+DBNAME( nDatei)) IF ISFILE(BaseDir+"BACKUP\"+DBNAME(nDatei))=1 Alte_Einträge_löschen(nDatei) Daten_einlesen( nDatei, BaseDir+"BACKUP\"+DBNAME(nDatei)) END nDatei := nDatei+1 UNTIL nDatei > nMaxFile Rename("UPDATE.INI","UPDATE.~NI") Hidewait endproc PROCEDURE Editieren( cField : STRING) ..01.12.1999 / Götz ..ermöglicht die Bearbeitung des Datenfeldes, welches als cFieldübergeben wird ReadRec( FileNr, RecNr(FileNr)) T-Eingabe := GetField(FileNr, LabelNo( FileNr,cField)) IF Input(cField)=1 SetField(FileNr, LabelNo( FileNr,cField),T-Eingabe) WriteRec( FileNr, RecNr(FileNr)) ATTACH END ENDPROC PROCEDURE Neueingabe ..01.12.1999 / Götz VarDef nRec : REAL T-Eingabe := "" VarDef cField, cLfd : STRING cField := IndDef(FileNr,1) cField := cField[1,POS(":",cField) -1] ReadRec( FileNr, 0) IF Input( cField,"Neueingabe")=1 SetField( FileNr, LabelNo( FileNr, cField),T-Eingabe) IF GetField( FileNr,LabelNo( FileNr, cField))#"" nRec := FileSize( FileNr)+1 WriteRec( FileNr, nRec) SetSortOrder( IndName( FileNr,1)) ShowRec( nRec) END END ENDPROC PROCEDURE Datensatz_Löschen ..01.12.1999 / Götz ..Löscht den aktuellen Datensatz nach Rückfrage ..als Feldinhalt wird der Inhalt des ersten Feldes aus den ID-Indexangezeigt VarDef nRec : REAL VarDef cField, cLfd : STRING ReadRec( FileNr, RecNr( FileNr)) nRec := RecNr( FileNr) cField := IndDef(FileNr,1) cField := cField[1,POS(":",cField) -1] cLfd := GetField( FileNr, LabelNo( FileNr, "Laufende_Nummer")) IF Message(cField+" : "+GetField(FileNr,LabelNo(FileNr,cField)),"Eintrag wird unwiderruflich entfernt!",3)=6 DelRec( FileNr, FindRec( FileNr,cLfd, IndName( FileNr, 0))) SetSortOrder( IndName( FileNr,1)) ShowRec( nRec) END ENDPROC
|
| Topic Verzeichnis mit Unterverzeichniss erstellen | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Ein Verzeichnis mit Unterverzeichniss wird in in Zwischenschritte erstellt. Procedure MakeNewDir(sDir : String) : Real; ..#erstellt ein Verzeichnis mit Unterverzeichniss in Zwischenschritte ..#Parameter: ..#sDir : Verzeichnis welches erstellt werden soll ..#Returnwert: ..#0 = Ok, 1 = Fehler ..#Bespielaufruf: ..#Message(Str(MakeNewDir("D:\XXX\YYY\Z\123"))); Vardef nRT, i : Real; Vardef sTmpDir : String; ..keine angabe ?sDir = "" / Return 1 ?sDir[Length(sDir)] <> "\"/ sDir := sDir + "\"; sTmpDir := ""; i := 1; While i <= Length(sDir) ..Zwischenverzeichnis erstellen If sDir[i] = "\" nRT := MakeDir(sTmpDir); sTmpDir := sTmpDir + sDir[i]; Else sTmpDir := sTmpDir + sDir[i]; End i := i + 1; End If IsFile(sTmpDir + "NUL") ..Message(sTmpDir + " ist da."); Return 0 Else ..Message(sTmpDir + " ist NICHT da."); Return 1 End Endproc
|
| Topic Löschen angekoppeler Daten | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Löschen angekoppelte Datensätze. Procedure LöscheKoppeldaten; ..# Link(TABELLE, SetMark(TABELLE, RecNr(TABELLE))); If NMarks(TABELLE) > 0 Access(TABELLE, "Markierung"); While ReadRec(TABELLE, RecNr(TABELLE)) DelRec(TABELLE, RecNr(TABELLE)); End End Endproc
|
| Topic EURO Kalkulator | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Ein einfachen Euroumrechner. Hierzu muß in eine System-Tabelle das Feld UmrechnungsfaktorZuEURO definiert sein. Procedure EUROKalk ..#ein einfachen euro <> dm Umrechner Vardef nRT, nWertEin : Real; Vardef sStr : String; ReadRec(SYSTEM, 1); T-Eingabe := ""; nRT := Input("Zahl eingeben. Beenden mit EUR oder DM","EUROKalk"); ?nRT = 0 / Return ?T-Eingabe = "" / Return T-Eingabe := Upper(T-Eingabe) ..#euro zu dm If T-Eingabe hat "EUR" sStr := T-Eingabe[1, Pos("EUR", T-Eingabe) - 1]; sStr := RTrim(sStr); nWertEin := Val(sStr) * SYSTEM.UmrechnungsfaktorZuEURO; Message(T-Eingabe + " = " + Str(nWertEin, 1,5) + " DM", "EUROKalk"); Return End ..#dm zu euro If T-Eingabe hat "DM" sStr := T-Eingabe[1, Pos("DM", T-Eingabe) - 1]; sStr := RTrim(sStr); nWertEin := Val(sStr) / SYSTEM.UmrechnungsfaktorZuEURO; Message(T-Eingabe + " = " + Str(nWertEin, 1, 5) + " EUR","EUROKalk"); Return End ..#dm zu euro wenn keine währung angegeben sStr := RTrim(T-Eingabe); nWertEin := Val(sStr) / SYSTEM.UmrechnungsfaktorZuEURO; Message(T-Eingabe + " = " + Str(nWertEin, 1, 5) + " EUR", "EUROKalk"); Return Endproc
|
| Topic Zeile in Worte trennen und als Parameter zurückgeben | Kapitel easy Funktionsbibliothek |
|
..# ..#Prozedur "ParseInWords" ..#ersten Parameter den String aufnimmt, der analysiert werden soll ..#zweiten Paramter einen String mit all den Zeichen, die als Worttrenner gewertet werden sollen ..#dritten Parameter einen Array von Strings, der mit den gefundenen Wörtern gefüllt wird. ..#(c)Lüko Willms PROCEDURE ParseInWords(zuAnalysieren, Trennzeichen : STRING; VAR Wörter : STRING[]) : REAL VARDEF nWords, nChars : REAL VARDEF Ist_im_Wort : REAL ClrArray(Wörter) nWords := 0 nChars := 1 Ist_im_Wort := Falsch WHILE nChars 0 IF Ist_im_Wort Ist_im_Wort := Falsch END IF ELSE IF NOT Ist_im_Wort Ist_im_Wort := Wahr nWords := nWords + 1 END IF Wörter[nWords] := Wörter[nWords] + zuAnalysieren[nChars] END IF nChars := nChars + 1 END WHILE RETURN nWords ENDPROC
|
| Topic Strings bearbeiten | Kapitel easy Funktionsbibliothek |
| Topic Verzeichnis erstellen | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Verzeichnis erstellen. Diese Prozedure bietet die Möglichkeit Unterverzeichnisse zu erstellen, wo bei das Rootverzeichnis nicht vorhanden sein muß. Das im Gegensatz zu der Standardfunktion MakeDir. Procedure MakeNewDir(sDir : String) : Real; ..#erstellt ein Verzeichnis in Zwischenschritte ..#Parameter: ..#sDir : Verzeichnis welches erstellt werden soll ..#Rückgabe: ..#1 = Ok, 0 = Fehler Vardef nRT, i : Real; Vardef sTmpDir : String; ..keine angabe ?sDir = "" / Return 1 ?sDir[Length(sDir)] <> "\"/ sDir := sDir + "\"; sTmpDir := ""; i := 1; While i <= Length(sDir) ..Zwischenverzeichnis erstellen If sDir[i] = "\" nRT := MakeDir(sTmpDir); sTmpDir := sTmpDir + sDir[i]; Else sTmpDir := sTmpDir + sDir[i]; End i := i + 1; End If IsFile(sTmpDir + "NUL") ..Message(sTmpDir + " ist da."); Return 1 Else ..Message(sTmpDir + " ist NICHT da."); Return 0 End Endproc
|
| Topic Prüfen ob eine Tabelle schon geöffnet wurde | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Prüft ob eine Tabelle schon geöffnet wurde. PROCEDURE IsDBOpen(sDBName : STRING) : REAL; ..#check ob eine Tabelle schon geöffnet ist, wenn ja Rückgabe desfilenr ..#Parameter: ..#sDBName = Verzeichnis und Name der Tabellendatei ..#Retrunwert: ..#0 = DB ist nicht geöffnet, sonst FileNr des DBs VARDEF i, nIsOpen : REAL; i:=0; nIsOpen := 0; While i:=i+1 <= MaxFile ?Upper(sDBName) hat Upper(DBDir(i) + DBName(i)) / nIsOpen := i End RETURN nIsOpen ENDPROC
|
| Topic Alle Einträge einer Tabelle mit angekoppelter Tabelle(n) löschen | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Löscht alle Einträge einer Tabelle mit angekoppelter Tabelle. Procedure DeleteAllEntries ..#alle Einträge einer Tabelle löschen ..#Parameter: ..#Returnwert: ..erst mal alle demarkieren DelMarks(TABELLE); ..Beispiel: alle Felder Link(TABELLE , SetMark(TABELLE, RecNr(TABELLE) ) ); ..Beispiel:markiere alle angekoppelte Datensätze Link(TABELLE.koppelfeld = TABELLE2.Laufende_Nummer , SetMark(TABELLE, RecNr(TABELLE) ) ); nCnt := NMarks(TABELLE); ..setze zugriff auf markierung If nCnt > 0 Access(TABELLE, "Markierung") WHILE ReadRec(TABELLE, FirstRec(TABELLE) ) DelRec(TABELLE, RecNr(TABELLE) ); END If NMarks(TABELLE) = 0 Message("Alle Prozeduren vom Modul " + TABELLE.Modulname.Dateiname +" gelöscht.", "Hinweis"); End End Endproc
|
| Topic Tempverzeichnis auf das Windowsverzeichnis setzen | Kapitel easy Funktionsbibliothek |
|
Beschreibung: setzt das Tempverzeichnis auf das Windowsverzeichnis. Procedure pSetTMPDir(nDummy : Real) : String; ..#setzt ein Tempverzeichnis auf dem Windowsverzeichnis. ..#Ist WINDIR nicht vorhanden, dann auf BaseDir, welches ..#das Homeverzeichnis des Projektes ist ..#Beispiel: DEF TMPFILE = pSetTMPDir(0) + "tempfile.txt"; ..#Returnwert: ..#Windows oder Projektverzeichnis ?GetEnv("WINDIR") <> "" / Return GetEnv("WINDIR") ?GetEnv("WINDIR") = "" / Return BaseDir Endproc
|
| Topic Ein links abgeschnittenen String in ShowWait zeigen | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Zeigt ein links abgeschnittenen String. Wird für Showwait verwendet. Abgeschnittener Teil wird als ... gezeigt. Procedure pShowLine(sLine : String; nMaxLength : Real) : String; ..#Zeigt ein links abgeschnittenen String. Wird für Showwait verwendet. ..#Abgeschnittener Teil wird als ... gezeigt. ..#Parameter: ..#sLine = dargestellte Information ..#nMaxLength = max. Länge des Strings ..#Returnwert ..#angepasster String ?nMaxLength < 0 Or nMaxLength > 255 / nMaxLength := 255 If Length(sLine) > nMaxLength Return "..." + sLine[Length(sLine) - nMaxLength, 255] Else Return sLine End Endproc
|
| Topic Eine Dateiname in den Teilen Pfad, Name und Erweiterung aufsplitten | Kapitel easy Funktionsbibliothek |
|
Beschreibung: Eine Dateiname in den Teilen Pfad, Name und Erweiterung aufsplitten Procedure SplitFilename(sFilename : String; Var sPath, sName, sExt :String); ..#Dateiname in den Teilen Pfad, Name und Erweiterung aufsplitten ..#Parameter: ..#sFilename = kompletter Dateiname ..#Returnwert: ..#sPath = Pfad ..#sName = Dateiname ..#sExt = Dateierweiterung Vardef i, j : Real; nLoop(i, Length(sFilename) - 1, Sel(sFilename[i + 1] = "\", j := i+1)) sPath := sFilename[1, j]; sName := sFilename[j + 1, 255]; sExt := "" j := Pos(" |