Gerade eben fand ich ein interessantes undokumentiertes Feature:
Wenn der Cursor in einer Registerkarte ist und man F2 drückt,
dann wird in der oberen rechten Ecke ein kleines List-Item angezeigt mit den Namen aller Registerseiten. Hier kann man mit den Cursortasten navigieren und dann Enter oder Return drücken.
Dies lässt einen WHEN-TAB-PAGE-CHANGED-Trigger starten. Hier würde man nun z.B. eine Navigation in einen anderen Block einbauen.
Viel Spass damit
Gerd
17. Dezember 2008
20. November 2008
Neues Statement of Direction, Oktober 2008
Dies ist das neue Statement of Direction vom Oktober 2008. (Hier ist der Link zu meinem letzten SoD-Post)
Was hat sich geändert?
Die graphische Darstellung der Timeline wurde entfernt. Ansonsten wurde in dem Dokument nichts verändert. Warum dann eine neue Version herausgegeben wurde ist auf den ersten Blick nicht nachvollziehbar.
Hier sind einige Links zu älteren Statement of Directions:
SoD 2008 / 07
SoD 2007 / 11
SoD 2005 / 09
SoD 2005 / 05
SoD 2005 / 03
SoD 2004 / 06
Was hat sich geändert?
Die graphische Darstellung der Timeline wurde entfernt. Ansonsten wurde in dem Dokument nichts verändert. Warum dann eine neue Version herausgegeben wurde ist auf den ersten Blick nicht nachvollziehbar.
Hier sind einige Links zu älteren Statement of Directions:
SoD 2008 / 07
SoD 2007 / 11
SoD 2005 / 09
SoD 2005 / 05
SoD 2005 / 03
SoD 2004 / 06
16. Oktober 2008
SQL Developer Data Modeling
Die Beta-Version ist draussen! Und hier sind schon die ersten Screenshots, die ich auf meinem Notebook generieren konnte.
Dies wird also der Nachfolger vom guten alten Oracle Designer werden. Der Name ist: Oracle SQL Developer Data Modeling (OSDM) und wird im SQL Developer enthalten sein.
Als Erstes habe ich den Datenmodell-Capture getestet. Ein paar Klicks im Menü und schon hatte ich die ersten Tabellen im OSDM drin. Gespeichert wurden die Tabellen im relationalen Bereich
Über ein "Engineer to Logical Model" kann man das Datenmodell ins ER-Modell überführen. Das funktionierte genauso einfach und ohne Probleme
Der Link zum OTN-Download-Bereich des OSDM: Oracle SQL Developer Data Modeling
In den nächsten Tagen werde ich weitere Tests machen und ich hoffe, dass der gute erste Eindruck weiter so bleibt!
Gerd
Dies wird also der Nachfolger vom guten alten Oracle Designer werden. Der Name ist: Oracle SQL Developer Data Modeling (OSDM) und wird im SQL Developer enthalten sein.
Als Erstes habe ich den Datenmodell-Capture getestet. Ein paar Klicks im Menü und schon hatte ich die ersten Tabellen im OSDM drin. Gespeichert wurden die Tabellen im relationalen Bereich
Über ein "Engineer to Logical Model" kann man das Datenmodell ins ER-Modell überführen. Das funktionierte genauso einfach und ohne Probleme
Der Link zum OTN-Download-Bereich des OSDM: Oracle SQL Developer Data Modeling
In den nächsten Tagen werde ich weitere Tests machen und ich hoffe, dass der gute erste Eindruck weiter so bleibt!
Gerd
15. Oktober 2008
Views, die auf Jahr, Monat und Tag basieren
Bei der Applikations-Entwicklung braucht man häufig Wertelisten, die einem Jahre, Monate oder Tage zurückgeben.
Man könnte dort natürlich jedes Mal ein Select-Statement fest in einer LOV verdrahten und diese Daten dann anzeigen.
Eleganter geht's aber mit einer View, die man zur Datenselektion benutzt. Hier sind 3 Beispiele für solche Views :
Diese Views ermöglichen nun den einfachen Select auf
In einer Record-Group verwendet man diese Views dann so:
Werteliste der nächsten 10 Jahre
Werteliste der letzten 30 Tage und der nächsten 10 Tage
Einfacher geht es kaum noch
Gerd
Man könnte dort natürlich jedes Mal ein Select-Statement fest in einer LOV verdrahten und diese Daten dann anzeigen.
Eleganter geht's aber mit einer View, die man zur Datenselektion benutzt. Hier sind 3 Beispiele für solche Views :
CREATE OR REPLACE FORCE VIEW JAHRE_V
(DATUM) AS
SELECT add_months (trunc (sysdate, 'YYYY'), 12 * (50 - Level))
FROM Dual
CONNECT BY Level <= 100;
CREATE OR REPLACE FORCE VIEW MONATE_V
(DATUM) AS
SELECT add_months (trunc (sysdate, 'MM'), 500 - Level)
FROM Dual
CONNECT BY Level <= 1000;
CREATE OR REPLACE FORCE VIEW TAGE_V
(DATUM) AS
SELECT trunc (sysdate) + 15000 - Level
FROM Dual
CONNECT BY Level <= 30000;
Diese Views ermöglichen nun den einfachen Select auf
- Aktuelles Jahr +/- 50 Jahre
- Aktueller Monat +/- 500 Monate
- Aktueller Tag +/- 15000 Tage
In einer Record-Group verwendet man diese Views dann so:
Werteliste der nächsten 10 Jahre
SELECT Datum
FROM Jahre_V
WHERE Datum BETWEEN trunc (sysdate, 'YYYY')
AND add_months (trunc (sysdate, 'YYYY'), 10*12);
Werteliste der letzten 30 Tage und der nächsten 10 Tage
SELECT Datum
FROM Tage_V
WHERE Datum BETWEEN trunc (sysdate-30) AND trunc (sysdate+10);
Einfacher geht es kaum noch
Gerd
26. September 2008
Neuer Oracle Designer ? Teil 2
Gerade eben fand ich einen interessanten Link zu den ersten Bilder des neuen "Oracle Designer".
Das Datenmodell kann demnächst im SQL Developer editiert werden.
Viel Spass beim Lesen von Jared's Artikel: Daten Modellierung mit SQL Developer
Das Datenmodell kann demnächst im SQL Developer editiert werden.
Viel Spass beim Lesen von Jared's Artikel: Daten Modellierung mit SQL Developer
5. August 2008
Neues Statement of Direction, Juli 2008
Vor einigen Tagen veröffentlichte Oracle sein neuestes Statement of Direction.
Was ist neu?
1) Ein Link zum Oracle Lifetime-Support Dokument. Intern wird dann weitergeleitet zu einer neuen URL
2) und 4 Jahre erweiterten Support (mindestens). Im letzten Statement of Direction war 2013 als Mindest-Supportdatum angegeben. Nun ist es 2017!
Was ist neu?
1) Ein Link zum Oracle Lifetime-Support Dokument. Intern wird dann weitergeleitet zu einer neuen URL
2) und 4 Jahre erweiterten Support (mindestens). Im letzten Statement of Direction war 2013 als Mindest-Supportdatum angegeben. Nun ist es 2017!
21. Juli 2008
Alle Objekte des Layout-Editors markieren
Falls man auf der Suche nach Objekten ist, die im Layout-Editor nur schwer zu finden sind, kann man den "Markiere Alle" - Trick benutzen. Danach werden dann alle Objekte des Layout-Editors im Objekt-Navigator markiert angezeigt.
Nach dem Ctrl+A sind alle Objekte im Navigator markiert und geöffnet
Viel Spass damit
Gerd
Nach dem Ctrl+A sind alle Objekte im Navigator markiert und geöffnet
Viel Spass damit
Gerd
2. Juli 2008
Neuer Oracle Designer ?
Ich kann's noch gar nicht glauben...
Oracle SQL-Developer unterstützt die DB-Modellierung in einem der nächsten Releases.
Hier die wichtigsten Features:
da kann man sich ja mal ehrlich drauf freuen. Der Designer ist nun doch schon ein wenig in die Jahre gekommen, seit er nicht mehr weiterentwickelt wird
Gerd
Oracle SQL-Developer unterstützt die DB-Modellierung in einem der nächsten Releases.
Hier die wichtigsten Features:
Database Data Modeling to support:
* Designing logical Entity Relation Diagrams
* Building physical schema designs
* Generating and executing DDL scripts
* Reverse and forward engineering of existing relational data structures
* Data domain administration
* Naming standardization
* Model formatting (font, colors)
* Importing data models from CA Erwin and Oracle Designer
* Compare and merge facilities
* Multiple database support
o Oracle Database
o DB2 (Mainframe & UDB)
o Microsoft SQL Server
* Logical and physical multi-dimensional modeling
* Object relational Data Types
* Spatial Modeling
* Multi-level logical and physical design environments
* Model validation rules
* Offline (file based) and Repository based modeling
da kann man sich ja mal ehrlich drauf freuen. Der Designer ist nun doch schon ein wenig in die Jahre gekommen, seit er nicht mehr weiterentwickelt wird
Gerd
1. Juli 2008
Talk2Gerd im neuen Look
26. Juni 2008
Schneller Kompilieren im Forms Builder
Die Geschwindigkeit des "Compile All" im Forms Builder kann dramatisch erhöht werden, wenn man vor dem Kompilieren alle Knoten schliesst und nur den obersten Knoten im Object-Navigator offen lässt und von dort aus den Kompiliervorgang startet:
Kompilierzeit einer normalen PL/SQL-Library mit 70 Program Units
Kompilierzeit einer grossen PL/SQL-Library mit 130 Program Units
Kompilierzeit einer normalen Maske mit 14 Blöcken
Kompilierzeit einer grossen Maske mit 24 Blöcken und sehr viel Sourcecode
Mit diesem kleinen Trick kann man unglaublich viel Zeit sparen!
Viel Spass damit
Gerd
Kompilierzeit einer normalen PL/SQL-Library mit 70 Program Units
geschlossene Knoten : 2 sec
geöffnete Knoten : 18 sec
Kompilierzeit einer grossen PL/SQL-Library mit 130 Program Units
geschlossene Knoten : 2 sec
geöffnete Knoten : 34 sec
Kompilierzeit einer normalen Maske mit 14 Blöcken
geschlossene Knoten : 3 sec
geöffnete Knoten : 12 sec
Kompilierzeit einer grossen Maske mit 24 Blöcken und sehr viel Sourcecode
geschlossene Knoten : 6 sec
geöffnete Knoten : 37 sec
Mit diesem kleinen Trick kann man unglaublich viel Zeit sparen!
Viel Spass damit
Gerd
19. Juni 2008
Compile oder Compile All ?
Wie sollte man eine Maske am besten kompilieren? Bevor ich die Problematik dieses Themas erläutere, hier erst ein paar Erklärungen:
In den älteren Versionen von Forms war Compile Module als Generate bekannt. Das bevorzuge ich auch heute noch, da die Tastenkombination Ctrl+T das FMX generiert.
Bei der täglichen Arbeit werde ich ab und zu mit einem nicht reproduzierbaren Problem konfrontiert. Nachdem Änderungen in einer Maske gemacht wurden startet man den Generate. Nun wird automatisch intern ein Compile Incremental durchgeführt und danach das FMX erzeugt.
Und das ist das Problem. In 9 von 10 Fällen läuft das FMX ohne Probleme, aber ab und zu arbeitet das Compile Incremental nicht zuverlässig. Dies erkennt man aber erst zur Laufzeit durch merkwürdige nicht reproduzierbare Fehlermeldungen.
Meine Lösung für dieses Problem ist:
Nach dem Öffnen einer Maske wird sofort ein Compile All gestartet. Jeder Incremental Compile und jeder Generate, der von nun an gestartet wird läuft ohne Probleme. D.h. wenn die Maske einmal gründlich kompiliert wurde kann man ab diesem Zeitpunkt ohne Bedenken Generates starten.
Try it
Gerd
Compile Incremental : Ctrl + K
Compile All : Shift + Ctrl + K
Compile Module (Generate): Ctrl + T
Run : Ctrl + R
In den älteren Versionen von Forms war Compile Module als Generate bekannt. Das bevorzuge ich auch heute noch, da die Tastenkombination Ctrl+T das FMX generiert.
Bei der täglichen Arbeit werde ich ab und zu mit einem nicht reproduzierbaren Problem konfrontiert. Nachdem Änderungen in einer Maske gemacht wurden startet man den Generate. Nun wird automatisch intern ein Compile Incremental durchgeführt und danach das FMX erzeugt.
Und das ist das Problem. In 9 von 10 Fällen läuft das FMX ohne Probleme, aber ab und zu arbeitet das Compile Incremental nicht zuverlässig. Dies erkennt man aber erst zur Laufzeit durch merkwürdige nicht reproduzierbare Fehlermeldungen.
Meine Lösung für dieses Problem ist:
Nach dem Öffnen einer Maske wird sofort ein Compile All gestartet. Jeder Incremental Compile und jeder Generate, der von nun an gestartet wird läuft ohne Probleme. D.h. wenn die Maske einmal gründlich kompiliert wurde kann man ab diesem Zeitpunkt ohne Bedenken Generates starten.
Try it
Gerd
5. Juni 2008
Forms Shut-Down
Letztes Jahr schrieb ich einen Artikel Forms Start-Up in dem ich demonstrierte, wie man ein Browser-Fenster beim Applikationsstart verstecken kann. Eine ähnliche Fragestellung kommt beim Schliessen auf uns zu: Wie schliesse ich das Browser-Fenster, wenn ich die Applikation beende? Dies ist meine aktuelle Lieblingsmethode:
1) Erzeuge eine HTML-Datei z.B. close.html im html-Verzeichnis. Dieser Befehl schliesst das Browser-Fenster.
2) Setze den formsweb.cfg Parameter HTMLbeforeForm im server-Verzeichnis. Damit wird die Sicherheits-Abfrage "Möchten Sie das Fenster schliessen" unterdrückt.
3) Die Maske, die die Gesamt-Applikation beendet, benötigt einen POST-FORM-Trigger. /forms/html ist ein virtuelles Verzeichnis, welches auf die close.html zeigt.
Verzeichnisse:
Vielen Dank an Duncan Mills, Frank Nimphius und Richard Squires, die diese Ideen vor einigen Jahren im OTN veröffentlichten.
Pro) Diese Technik arbeitet auf IE 6 und IE 7, getestet mit dem JInitiator und dem Sun-Plugin.
Kontra) Keine Firefox-Unterstützung. Seit Firefox 2.0 ist es nicht mehr erlaubt, ein Fenster per JavaSript zu schliessen.
Wichtig: Die Restriktionen dieses Blogs zwangen mich, nach jedem "<" und vor jedem ">" ein Leerzeichen zu schreiben. Bitte entfernen vor dem Einsatz.
viel Spass
Gerd
1) Erzeuge eine HTML-Datei z.B. close.html im html-Verzeichnis. Dieser Befehl schliesst das Browser-Fenster.
< BODY onLoad="window.close();" >
2) Setze den formsweb.cfg Parameter HTMLbeforeForm im server-Verzeichnis. Damit wird die Sicherheits-Abfrage "Möchten Sie das Fenster schliessen" unterdrückt.
HTMLbeforeForm=< SCRIPT LANGUAGE="JavaScript" >window.opener = top;< /SCRIPT >
3) Die Maske, die die Gesamt-Applikation beendet, benötigt einen POST-FORM-Trigger. /forms/html ist ein virtuelles Verzeichnis, welches auf die close.html zeigt.
web.show_document ('/forms/html/close.html', '_self');
Verzeichnisse:
< DevSuite-Home > : Developer-Suite Home Verzeichnis
html-Verzeichnis : < DevSuite-Home >\tools\web\html
server-Verzeichnis : < DevSuite-Home >\forms\server
virtual-html-Verzeichnis : /forms/html definiert in forms.conf
Vielen Dank an Duncan Mills, Frank Nimphius und Richard Squires, die diese Ideen vor einigen Jahren im OTN veröffentlichten.
Pro) Diese Technik arbeitet auf IE 6 und IE 7, getestet mit dem JInitiator und dem Sun-Plugin.
Kontra) Keine Firefox-Unterstützung. Seit Firefox 2.0 ist es nicht mehr erlaubt, ein Fenster per JavaSript zu schliessen.
Wichtig: Die Restriktionen dieses Blogs zwangen mich, nach jedem "<" und vor jedem ">" ein Leerzeichen zu schreiben. Bitte entfernen vor dem Einsatz.
viel Spass
Gerd
3. Juni 2008
Sourcecode-Formatierung im OTN-Forum
Fast jeden Tag sehe ich im OTN-Forum unformatierte Sourcecodes. Warum?
Das Problem ist, dass viele User gar nicht wissen, wie man Sourcecode formatieren kann. Beispiel:
Wer kann das lesen? Ich löse zwar gerne Rätsel, aber nicht, wenn es sich um Sourcecodes handelt. Wie können wir das Problem lösen?
Benutze [pre] vor dem Sourcecode und [/pre] am Ende. Dann ist es lesbar wie im Original:
und so sieht der vorformatierte Text dann aus, nachdem die preformat-tags genutzt wurden:
Besser kann der Sourcecode kaum aussehen!
Viel Spass damit
Gerd
Das Problem ist, dass viele User gar nicht wissen, wie man Sourcecode formatieren kann. Beispiel:
/*
|| Summierung aller Sub-Aufträge
*/
if :control.sub_order_id is not null then
select sum (value)
into :control.sum
from sum_orders
where order_id in (select order_id
from sub_orders
where sub_order_id = :control.sub_order_id
and sub_order_type = 'ONLINE');
else
:control.sum := 0;
end if;
/*
|| Diese Summe benötigen wir nun für ...
*/
Wer kann das lesen? Ich löse zwar gerne Rätsel, aber nicht, wenn es sich um Sourcecodes handelt. Wie können wir das Problem lösen?
Benutze [pre] vor dem Sourcecode und [/pre] am Ende. Dann ist es lesbar wie im Original:
[pre]
...
if :control.sub_order_id is not null then
select sum (value)
into :control.sum
...
[/pre]
und so sieht der vorformatierte Text dann aus, nachdem die preformat-tags genutzt wurden:
/*
|| Summierung aller Sub-Aufträge
*/
if :control.sub_order_id is not null then
select sum (value)
into :control.sum
from sum_orders
where order_id in (select order_id
from sub_orders
where sub_order_id = :control.sub_order_id
and sub_order_type = 'ONLINE');
else
:control.sum := 0;
end if;
/*
|| Diese Summe benötigen wir nun für ...
*/
Besser kann der Sourcecode kaum aussehen!
Viel Spass damit
Gerd
2. Juni 2008
Open-Form und die Exit-Form-Strategie (2)
Manchmal benutzt man Sourcecodes schon seit vielen Jahren und denkt, dass es keinen einfacheren und besseren Weg gibt um ein bestimmtes Problem zu lösen als durch den Einsatz genau dieses Stück Codes.
So auch hier. Nachdem ich den letzten Artikel geschrieben hatte lief alles so wie immer und war bestens!
Nachdem ich heute den Code ein wenig refaktorieren wollte, entwarf ich eine viel einfachere und wirkungsvollere Methode (was normalerweise nicht das Ziel eines Refactorings sein sollte!):
Alles was man nun noch benötigt ist ein
KEY-EXIT in der Startmaske:
und ein WHEN-FORM-NAVIGATE in allen anderen Masken
Diese Technik arbeitet mit einer Kettenreaktion. Jede geschlossene Maske lässt den Fokus auf eine noch geöffnete Maske überspringen, in der dann der WHEN-FORM-VNAVIGATE ausgeführt wird. Diese Maske wird dann auch wieder geschlossen usw... Dies geschieht, da die globale Variable AUTOCLOSE auf TRUE gesetzt wurde.
Nach der letzten Maske ist somit die gesamte Applikation beendet und wir haben das Ziel erreicht, dass wir zu Beginn beabsichtigten.
Wenn einige dieser Masken weitere Masken per Call_Form starten, dann benötigt man hier dem WHEN-WINDOW-ACTIVATED als Event, da der WHEN-FORM-NAVIGATE nicht zündet, wenn der Fokus an die Maske zurückübermittelt wird.
Das ist nun mit Abstand die einfachste Lösung dieses Problems, die ich kenne?
Viel Spass damit
Gerd
So auch hier. Nachdem ich den letzten Artikel geschrieben hatte lief alles so wie immer und war bestens!
Nachdem ich heute den Code ein wenig refaktorieren wollte, entwarf ich eine viel einfachere und wirkungsvollere Methode (was normalerweise nicht das Ziel eines Refactorings sein sollte!):
Alles was man nun noch benötigt ist ein
KEY-EXIT in der Startmaske:
COPY ('TRUE', 'GLOBAL.EXIT_IMMEDIATE');
EXIT_FORM (no_validate);
und ein WHEN-FORM-NAVIGATE in allen anderen Masken
DEFAULT_VALUE ('FALSE', 'GLOBAL.EXIT_IMMEDIATE');
IF :GLOBAL.EXIT_IMMEDIATE = 'TRUE' THEN
EXIT_FORM (no_validate);
END IF;
Diese Technik arbeitet mit einer Kettenreaktion. Jede geschlossene Maske lässt den Fokus auf eine noch geöffnete Maske überspringen, in der dann der WHEN-FORM-VNAVIGATE ausgeführt wird. Diese Maske wird dann auch wieder geschlossen usw... Dies geschieht, da die globale Variable AUTOCLOSE auf TRUE gesetzt wurde.
Nach der letzten Maske ist somit die gesamte Applikation beendet und wir haben das Ziel erreicht, dass wir zu Beginn beabsichtigten.
Wenn einige dieser Masken weitere Masken per Call_Form starten, dann benötigt man hier dem WHEN-WINDOW-ACTIVATED als Event, da der WHEN-FORM-NAVIGATE nicht zündet, wenn der Fokus an die Maske zurückübermittelt wird.
Das ist nun mit Abstand die einfachste Lösung dieses Problems, die ich kenne?
Viel Spass damit
Gerd
26. Mai 2008
Open-Form benötigt eine Exit-Form-Strategie
Dieser Artikel soll all jenen weiterhelfen, die mit OPEN_FORM statt CALL_FORM arbeiten.
OPEN_FORM hat Vorteile aber auch ein paar Probleme. Der Anwender kann zwischen allen offenen Masken hin und herspringen, beendet er jedoch eine Maske, wird immer nur die aktuelle Maske geschlossen.
Lösung: Gehen wir einmal von einer normalen Applikation aus, in der es eine Startmaske gibt, von der aus alle anderen Masken per OPEN_FORM geöffnet werden. Wenn die Startmaske den Fokus hat und man klickt auf Beenden, dann möchte man die gesamte Applikation beenden und nicht nur die Maske in der man sich befindet. Wir brauchen an der Stelle eine Funktionalität, die zuerst einmal in einer Schleife durch alle geöffneten Masken läuft, die schliesst und am Ende die Startmaske beendet.
Alle geöffneten Masken zu finden ist nicht einfach. Am besten speichert man diese Daten in einer globalen Liste namens GLOBAL.OPEN_FORMS. Die Werte werden durch Semikolon getrennt gespeichert, z.B. ;STARTFORM;EMP;DEPT;
Wir brauchen nun einen PRE-FORM und einen POST-FORM-Trigger für alle Masken, außer der Startmaske. Der Pre-Form hängt einen neuen Eintrag ans Ende der Liste und der Post-Form löscht entsprechende Einträge wieder raus.
PRE-FORM :
POST-FORM :
Nun haben wir die Namen aller geöffneten Masken in der globalen Liste gespeichert.
Der KEY-EXIT Trigger in der Startmaske arbeitet in einer Schleife nun alle Listeneinträge ab und schliesst diese Masken.
KEY-EXIT der Startmaske :
Die Startmaske wird durch einen WHEN-TIMER-EXPIRED beendet:
Alle anderen Masken benötigen noch einen WHEN-FORM-NAVIGATE Trigger:
Nun haben wir eine gut funktionierende AutoClose-Methode für alle unsere Applikationen.
Viel Spass damit
Gerd
Hier ist der One-Time-Timer Artikel. Der Einfachheit halber hier direkt der Code für die Startmaske:
OPEN_FORM hat Vorteile aber auch ein paar Probleme. Der Anwender kann zwischen allen offenen Masken hin und herspringen, beendet er jedoch eine Maske, wird immer nur die aktuelle Maske geschlossen.
Lösung: Gehen wir einmal von einer normalen Applikation aus, in der es eine Startmaske gibt, von der aus alle anderen Masken per OPEN_FORM geöffnet werden. Wenn die Startmaske den Fokus hat und man klickt auf Beenden, dann möchte man die gesamte Applikation beenden und nicht nur die Maske in der man sich befindet. Wir brauchen an der Stelle eine Funktionalität, die zuerst einmal in einer Schleife durch alle geöffneten Masken läuft, die schliesst und am Ende die Startmaske beendet.
Alle geöffneten Masken zu finden ist nicht einfach. Am besten speichert man diese Daten in einer globalen Liste namens GLOBAL.OPEN_FORMS. Die Werte werden durch Semikolon getrennt gespeichert, z.B. ;STARTFORM;EMP;DEPT;
Wir brauchen nun einen PRE-FORM und einen POST-FORM-Trigger für alle Masken, außer der Startmaske. Der Pre-Form hängt einen neuen Eintrag ans Ende der Liste und der Post-Form löscht entsprechende Einträge wieder raus.
PRE-FORM :
DEFAULT_VALUE (';', 'GLOBAL.OPEN_FORMS');
:GLOBAL.OPEN_FORMS := :GLOBAL.OPEN_FORMS ||
:SYSTEM.CURRENT_FORM || ';';
POST-FORM :
:GLOBAL.OPEN_FORMS := REPLACE (:GLOBAL.OPEN_FORMS,
';' || :SYSTEM.CURRENT_FORM || ';',
';');
Nun haben wir die Namen aller geöffneten Masken in der globalen Liste gespeichert.
Der KEY-EXIT Trigger in der Startmaske arbeitet in einer Schleife nun alle Listeneinträge ab und schliesst diese Masken.
KEY-EXIT der Startmaske :
DECLARE
V_Form VARCHAR2 (30);
BEGIN
One_Time_Timer.Initialize ('EXIT_STARTFORM');
DEFAULT_VALUE (';', 'GLOBAL.OPEN_FORMS');
WHILE :GLOBAL.OPEN_FORMS != ';'
LOOP
V_Form := Substr (:GLOBAL.OPEN_FORMS,
2,
InStr (:GLOBAL.OPEN_FORMS, ';', 1, 2) - 2);
COPY ('J', 'GLOBAL.EXIT_IMMEDIATE');
GO_FORM (V_Form);
END LOOP;
END;
Die Startmaske wird durch einen WHEN-TIMER-EXPIRED beendet:
IF One_Time_Timer.Get_Value = 'EXIT_STARTFORM' THEN
EXIT_FORM (no_validate);
END IF;
Alle anderen Masken benötigen noch einen WHEN-FORM-NAVIGATE Trigger:
DEFAULT_VALUE ('N', 'GLOBAL.EXIT_IMMEDIATE');
IF :GLOBAL.EXIT_IMMEDIATE = 'J' THEN
EXIT_FORM (no_validate);
END IF;
Nun haben wir eine gut funktionierende AutoClose-Methode für alle unsere Applikationen.
Viel Spass damit
Gerd
Hier ist der One-Time-Timer Artikel. Der Einfachheit halber hier direkt der Code für die Startmaske:
PACKAGE Const IS
gbl_One_Time_Timer CONSTANT VARCHAR2 (61) :=
upper ('global.One_Time_Timer');
END;
PACKAGE One_Time_Timer IS
FUNCTION Get_Value RETURN VARCHAR2;
PROCEDURE Initialize (P_Event IN VARCHAR2);
END;
PACKAGE BODY One_Time_Timer IS
FUNCTION Get_Value RETURN VARCHAR2 IS
BEGIN
Default_Value (NULL, Const.gbl_One_Time_Timer);
RETURN (NAME_IN (Const.gbl_One_Time_Timer));
END;
PROCEDURE Initialize (P_Event IN VARCHAR2) IS
tm_id timer;
tm_name VARCHAR2 (30) := 'ONE_TIME_TIMER';
BEGIN
tm_id := Find_Timer (tm_name);
IF ID_Null (tm_id) THEN
tm_id := Create_Timer (tm_name, 10, NO_REPEAT);
COPY (p_Event, Const.gbl_One_Time_Timer);
END IF;
END;
END One_Time_Timer;
14. April 2008
Forms 11g - Umfrage
Nachdem ich nun die letzten Artikel über Forms 11g und die neuen Features geschrieben habe, interessiert mich nun, welches Features davon in der täglichen Arbeit direkt eingesetzt werden wird.
Desweiteren würde mich interessieren, welche anderen Features in den nächsten Patches und Releases integriert werden.
Antworten bitte direkt als Kommentare zu diesem Post.
Danke
Gerd
Desweiteren würde mich interessieren, welche anderen Features in den nächsten Patches und Releases integriert werden.
Antworten bitte direkt als Kommentare zu diesem Post.
Danke
Gerd
26. März 2008
Forms 11g New Features: Javascript-API
Forms 11g erlaubt erstmals eine direkte Kommunikation zwischen dem generischen Java-Applet des Browsers und der umgebenden Welt. Das neue JavaScript-API ermöglicht dies.
In der neuen Version gibt es zur Kommunikation mit dem JavaScript-API einen neuen Forms-Trigger, neue Systemvariablen und neue Built-Ins.
Der Trigger WHEN-CUSTOM-JAVASCRIPT-EVENT reagiert auf alle Events, die per JavaScript von außen an Oracle Forms herangetragen werden. Innerhalb dieses Triggers kann man die Payload aus zwei neuen Systemvariablen auslesen. system.javascript_event_name und :system.javascript_event_value.
Informationen, die von einer HTML-Seite an Forms weitergereicht werden, kann man nun ganz einfach auslesen:
In diesem kleinen Beispiel wird in der Payload als Event-Name der Befehl „NewForm“ übergeben und im Event-Value der Name der Maske. Die Daten werden zum Beispiel wie folgt aus der Internetseite übergeben:
Benutzt wird hier die Methode raiseEvent der Klasse forms_applet. Dieses Applet muss zuvor im OAS in der Konfigurationsdatei formsweb.cfg dem Systemparameter applet_name zugewiesen worden sein.
Forms ist in der Lage bidirektional mit dieser Internetseite zu kommunizieren. Dazu nutzt man die neuen Built-Ins web.javascript_eval_expr und web.javascript_eval_function.
Dieser Sourcecode befüllt in der Internetseite ein Feld namens „outside_field_id“ mithilfe der Built-In web.javascript_eval_expr. Zwei Techniken können hierbei genutzt werden. Die direkte Zuweisung oder der Aufruf einer JavaScript-Funktion, z.B. „set_field“.
Felder können ausgelesen werden durch die Nutzung der Built-In web.javascript_eval_function. Der Returnwert ist der Wert des entsprechenden Feldes in der HTML-Seite, hier wieder exemplarisch „outside_field_id“.
Dies ist ein weiteres Beispiel dafür, wie wichtig die Neuerungen in Forms 11g sind. Endlich kann Forms –aus dem Korsett des generischen Java-Applets heraus – mit der umgebenden Welt kommunizieren!
In der neuen Version gibt es zur Kommunikation mit dem JavaScript-API einen neuen Forms-Trigger, neue Systemvariablen und neue Built-Ins.
Der Trigger WHEN-CUSTOM-JAVASCRIPT-EVENT reagiert auf alle Events, die per JavaScript von außen an Oracle Forms herangetragen werden. Innerhalb dieses Triggers kann man die Payload aus zwei neuen Systemvariablen auslesen. system.javascript_event_name und :system.javascript_event_value.
Informationen, die von einer HTML-Seite an Forms weitergereicht werden, kann man nun ganz einfach auslesen:
In diesem kleinen Beispiel wird in der Payload als Event-Name der Befehl „NewForm“ übergeben und im Event-Value der Name der Maske. Die Daten werden zum Beispiel wie folgt aus der Internetseite übergeben:
< INPUT id="outside_field_id">
< SCRIPT>
function set_field (field_id, myValue) {
document.getElementById(field_id).value=myValue;
};
function clickEvent1()
{
document.forms_applet.raiseEvent("NewForm", "payload");
}
< /SCRIPT>
< INPUT id="button1" type="button" onClick="void clickEvent1();" value="NewForm">
Benutzt wird hier die Methode raiseEvent der Klasse forms_applet. Dieses Applet muss zuvor im OAS in der Konfigurationsdatei formsweb.cfg dem Systemparameter applet_name zugewiesen worden sein.
applet_name=forms_applet
Forms ist in der Lage bidirektional mit dieser Internetseite zu kommunizieren. Dazu nutzt man die neuen Built-Ins web.javascript_eval_expr und web.javascript_eval_function.
web.javascript_eval_expr
('document.getElementById("outside_field_id").value="' ||
:control.ti_inside || '";');
web.javascript_eval_expr
('set_field("outside_field_id", "' || :control.ti_inside
|| '")');
:control.ti_get_value := web.javascript_eval_function
('document.etElementById("outside_field_id").value');
Dieser Sourcecode befüllt in der Internetseite ein Feld namens „outside_field_id“ mithilfe der Built-In web.javascript_eval_expr. Zwei Techniken können hierbei genutzt werden. Die direkte Zuweisung oder der Aufruf einer JavaScript-Funktion, z.B. „set_field“.
Felder können ausgelesen werden durch die Nutzung der Built-In web.javascript_eval_function. Der Returnwert ist der Wert des entsprechenden Feldes in der HTML-Seite, hier wieder exemplarisch „outside_field_id“.
Dies ist ein weiteres Beispiel dafür, wie wichtig die Neuerungen in Forms 11g sind. Endlich kann Forms –aus dem Korsett des generischen Java-Applets heraus – mit der umgebenden Welt kommunizieren!
8. Februar 2008
LOV mit gesplitteten Daten
Eine interessante Art und Weise um LOV-Daten zu visualisieren ist diese hier:
Benutze so viele UNION ALL's wie nötig um die Daten zu konkatinieren:
Viel Spass damit
Gerd
Benutze so viele UNION ALL's wie nötig um die Daten zu konkatinieren:
select '---new colleagues---' ename, NULL job, NULL hiredate
from dual
UNION ALL
select ename, job, to_char (hiredate, 'DD.MM.YYYY')
from emp where hiredate >= to_date ('01.07.1981', 'DD.MM.YYYY')
UNION ALL
select '---before 07/81---' ename, NULL job, NULL hiredate
from dual
UNION ALL
select ename, job, to_char (hiredate, 'DD.MM.YYYY')
from emp where hiredate < to_date ('01.07.1981', 'DD.MM.YYYY')
Viel Spass damit
Gerd
11. Januar 2008
Hotkey F1 in Forms 10g
Seit der Forms-Version 10g ist der Hotkey F1 ein wenig problematisch. Er funktioniert so ohne weiteres nicht mehr.
Im Hotkey-Mapping für KEY-HELP zum Beispiel wurde nun Ctrl+H genommen statt dem guten alten F1.
Wenn man dies wieder auf den gleichen Stand wie unter Forms 6i bringen möchte, kann man die fmrweb.res und fmrwebd.res anpassen :
Die interne ID des Hotekeys F1 ist 112, die interne ID des KEY-HELP-Trigger ist 30:
viel Spass damit
Gerd
Im Hotkey-Mapping für KEY-HELP zum Beispiel wurde nun Ctrl+H genommen statt dem guten alten F1.
Wenn man dies wieder auf den gleichen Stand wie unter Forms 6i bringen möchte, kann man die fmrweb.res und fmrwebd.res anpassen :
Die interne ID des Hotekeys F1 ist 112, die interne ID des KEY-HELP-Trigger ist 30:
...
113 : 0 : "F2" : 95 : "List Tab Pages"
112 : 0 : "F1" : 30 : "Help"
72 : 2 : "Ctrl+H" : 30 : "Help"
viel Spass damit
Gerd
Abonnieren
Posts (Atom)