Mittwoch, 28. November 2018

APEX 18.1 - Dynamic Action Beispiel - set value

Business case:

Ich erfasse "Mitglieder" meine Vereins mit Vorname, Nachname und muss auch immer noch den Namen als Kontoinhaber für die Bankverbindung erfassen... blöd.

Ich möchte nun den Vornamen, Nachnamen mit einer Dynamic Action in das Feld Kontoinhaber "kopieren"...

Here we go:

Kurz:  Eingabe P18_VORNAME, P18_NACHNAME... - wird in P18_KONTOINHABER gesetzt

Im APEX Designer by Dynamic Action auf "CHANGE" klicken --> "create Dynamic Action"

Identification: Name vergeben - im Beispiel: "Set_kontoinhaber"


Selection Type: Item(s)


Dann linker Hand im Dynamic Action Pane auf das rote SHOW klicken und es erscheint rechts:

Action: von SHOW ändern in "Set Value"
Set Type: JavaScript expression
JavaScript expression (code):

$x("P18_VORNAME").value + ' ' +$x("P18_NACHNAME").value;

Suppress Change Event: No
Affected elements:
Selection Type : Item(s)

Execution Options
Fire when event Result is : True
Fire on initialization  : No
Stop execution: Yes

Viel Spaß und Erfolg damit !

Montag, 10. September 2018

EMAIL_TEMPLATE - how it works

an interesting feature of APEX 18.2 (and before...) is the EMAIL_TEMPLATE; it can be found under "Shared components" --> "other components"

The Email_template consists of 2 parts:

Part 1) The template details
divided into:
- header
- body
- footer
with HTML code content.

By means of a smart click (right hand side region) using "Sample Templates"
--> Get started by loading sample email Templates...
- you can load the HTML code data for the generation of an invoice... :

The hashtags like  #CUSTOMER_NAME# are substitions we know from other places within APEX.

Once we have defined the Email_template and adjusted the HTML for formatting we like to use it.... How ?

Part 2) pl/sql procedure

On the template_details page (as above) we will find a TAB called: "Sample API Usage" which shows the pl/sql we have to use to map the fields from a page to the hashtag substitions:

    apex_mail.send (
        p_to                 => email_address_of_user,
        p_template_static_id => 'EXAMPLE01',
        p_placeholders       => '{' ||
        '    "CUSTOMER_NAME":'           || apex_json.stringify( :P1_CUST_NAME ) ||
        '   ,"ITEMS_ORDERED":'           || apex_json.stringify( :P1_ITEMS_ORD ) ||
        '   ,"MY_APPLICATION_LINK":'     || apex_json.stringify( some_value ) ||
        '   ,"ORDER_DATE":'              || apex_json.stringify( some_value ) ||
        '   ,"ORDER_NUMBER":'            || apex_json.stringify( some_value ) ||
        '   ,"ORDER_TOTAL":'             || apex_json.stringify( some_value ) ||
        '   ,"ORDER_URL":'               || apex_json.stringify( some_value ) ||
        '   ,"SHIPPING_ADDRESS_LINE_1":' || apex_json.stringify( some_value ) ||
        '   ,"SHIPPING_ADDRESS_LINE_2":' || apex_json.stringify( some_value ) ||
        '   ,"SHIP_TO":'                 || apex_json.stringify( some_value ) ||
        '}' );

You just have to apply your fields from the page to "some_value".... as above.

So on your page you have to create a region of type pl/sql and insert above code... Create a Button and run the process by means of clicking the button.

The output is an HTML formatted email.

I did it even in way: The customer enters his data and clicks on "CREATE" (order or and the data is stored in the database AND in parallel an order confirmation - email is sent to the customer.

that's it!

APEX 4.2, 5.1, 18,2 - send email from an APEX application

again and again the question is asked: how to send an email from an APEX application ?

sorry - english, because this is an answer to a question in the APEX community forum.

I answered:

1: Pls kindly read the user guide...:

(The whole functionality is based on the APEX_MAIL API)

2. in short:

A) from within a page/form - add procedure of type "Send_email" and use substitutions/placeholders like  &P1_NAME. or  &P1_EMAIL. in the UI properties... - this is one email as per page/data

B) loop thru records of a table and send emails to those records like: - this is: several emails in a row....

  2.             FROM TABLE  
  3. Where email is not null  
  4.           and status = 'Aktiv'  
  5. and ABTEILUNG like '%'||:P3_ABTEILUNG  
  6.           )  
  7. LOOP  
  8.   apex_mail.send( p_to => m.EMAIL,  
  9.                   p_from => '',  
  10.                   p_bcc => '',  
  11.                   p_body => 'Hallo '||m.vorname||','||chr(10)||chr(10)||:P3_TEXT||chr(10)||  
  12.                 :P3_SIGNATURE                 
  13.                 ,  
  14.                   p_subj => :P3_SUBJECT  
  15.                 );  
  16. end loop;  

:P3_TEXT, :P3_SIGNATURE, :P3_SUBJECT and :P3_ABTEILUNG are names of fields in page 3 - in SQL and pl/sql these types of substitutions are used... in the Procedure re A) "Send_email" UI we use substitutions of type: &P3_NAME.

APEX 5.1/18.2 - Update several rows in a tabular form / GRID

APEX 5.1 - 18.2

this is to answer a thread from the APEX community forum, therefore in English - sorry:

Question: How to update several rows in a tabular form:

I answered:

In 18.2 recommend to use the interactive grid... (tabular form is legacy...)

the grid has an inbuilt row-selector - even select-/deselect-all....

Create a region of type "interactive grid" and enable it to edit. - then...
1) create a button and name it "update STATUS rows"
2) create a dynamic action and name it "update_status_rows_DA" of type (WHEN...) Event: click - type: Button -
3) add a true action - action: Execute Javascript code
4) settings/code:

  1. var record;  
  2. //Identify the particular interactive grid  
  3. var ig$     = apex.region("my_region_name").widget();  
  5. //Fetch the model for the interactive grid  
  6. var grid    = ig$.interactiveGrid("getViews","grid");  
  8. //Fetch the model for the interactive grid  
  9. var model   = ig$.interactiveGrid("getViews","grid").model;  
  11. //Fetch selected records  
  12. var selectedRecords = apex.region("my_region_name").widget().interactiveGrid("getViews","grid").view$.grid("getSelectedRecords");  
  14. //Loop through selected records and update value of the STATUS column  
  15. for (idx=0; idx < selectedRecords.length; idx++)   
  16. {  
  17. //Get the record  
  18. record = model.getRecord(selectedRecords[idx][0]);  
  20. // set Value von column STATUS on "VALID"     
  21. model.setValue(record,"STATUS"'VALID');  
  22. // optional...  
  23. model.setValue(record,"ROW_AMENDED_BY"'&APP_USER.');  
  24. model.setValue(record,"ROW_AMENDED_DATE"'&P14_DATE.');  
  25.        }  

execution options:
Event: Update_rows_DA
Fire when event result is: TRUEFire on initialisation: NO

Samstag, 4. August 2018

APEX 18.1 und Jasper Reports (2) - Subreports und mehrere Parameter

Nach meinen ersten Schritten mit Jasper Reports habe ich inzwischen auch einen sehr umfassenden Report gebaut mit einem Hauptreport und 2 Subreports und der Übergabe von 4 Parametern (Kunde_id, Kunde_Name, weitere_ID, weitere_ID2).

Die Schritte hier wie folgt:

1. Hauptreport anlegen

2. Subreport 1 anlegen (mit den gleichen Parametern wie 1)

3. Subreport 2 anlegen (mit den gleichen Parametern wie 1)

Im "Summary Band" die Subreports einfügen....

Es gibt bestimmt noch andere Wege... - aber dieser funktioniert.


Der Aufruf in APEX erfolgt über einen "Drucken"-Button und einen pl/sql Prozess:

Wie man im Code sieht, ruft der Prozess (von Dietmar Aust, Opal Consulting)
das package: xlib_jasperreports auf und darin "set_report_url' ....
In "show_report" werden die Parameter für die Übergabe in der URL zusammengebaut.

Zur Ausgabe stehen in Jasper Reports neben PDF, DOCX, RTF noch weitere Formate zur Verfügung wie ODT, ODS, PPT, XLS, CSV usw..

Update 18.02.2019
Ich habe mittlerweile Listen (siehe oben) und Formulare als PDF am Laufen... Einzeldruck Formular (PDF) oder auch Mehrfachdruck Formular (pro Datensatz eine Seite).
Aktuell arbeite ich an einer Lösung für "PDF-Formular" als E-Mail attachment aus Jasper Report.

Bei Fragen gerne fragen --> oder

Donnerstag, 21. Juni 2018

ODTUG - Kscope #LetsWreckThisTogether APEX Talks - recorded LIVESTREAM (1:27:25 hrs)

sorry for cross-posting - aber in DE mögen das nicht alle mitbekommen haben...

Free replay from ODTUG Kscope18 Deep Dive

Did you miss the Oracle APEX / JavaScript talks from the ODTUG #Kscope18 "deep dive" on Thursday? No worries, you can watch the replay!

These are 6 short, highly-informative & entertaining sessions from globally-recognized leaders in the APEX community. Every APEX developer on the planet should watch this at least once. You'll thank me later.

Jeder Speaker hatte 12 Min. Zeit...

Moderator: Dietmar Aust, Opal Consulting

Speaker: (topic) - Min. NN Startpunkt des Beitrags im 90 Min. video

Peter Raganitsch,  (Ground Use of JS)

Vincent Morneau, Insum (organize JS code, structures {namespace.module.function} ) recommending code editor "intellisense" - Min. 14

Menno Hoogendijk, Qualogy (widget architecture) - Min 30

John Scott - (Perfomance) - Min. 44:30

Kai Donato, MT AG - (Debugging) - Min. 57

Dan McGhan - how to start with JS - quoting experts advices  - Std. 1:13

Dienstag, 1. Mai 2018

APEX 18.1 und Jasper Reports 6.5.1 (1)

Business Case:
"Schön, Business adequat, Template basiert drucken" (pdf, rtf..) aus APEX heraus..
Listen, Rechnungen, Briefe, Newsletter (??)  u.ä.

Jasper Reports wird als OpenSource da schon ordentlich beworben. Also mal ran...
Opal Consulting (Dietmar Aust) - hat da bereits 2012 etwas drüber geschrieben und eine sehr hilfreiche Test-Application zur Verfügung gestellt (hier).

Es braucht schon etwas Geduld, um die Integration von APEX (18.1) und Jasper Reports zum fliegen zu bringen.
Man stösst auf allerlei altes "Geraffel" (e.g. iReports und die "Inkompatibilität" mit JDK 8, usw.)...

Bis ich dann die folgende Konfiguration zum Laufen (oder fliegen) bekam:

1. Download Jasper Reports Studio (hat scheinbar TIBCO, der große "Integrierer" jetzt gekauft...) von dieser Site:

Das ganze ist Eclipse basiert... und ließ sich erstaunlicherweise smart installieren und starten (im Gegensatz zu iReport 5.6 (dem Vorgänger), wo erst ein altes (1.7 u45) JDK/JRE nötig war.
So müllt man sich dann voll mit den verschiedenen Java Versionen... - aber Ok, der iReport 5.6 (Netbeans basiert) wird auch nicht weiter supported von der Community - und Netbeans hat Schuld an der "alten" Java Version..(einer muss ja Schuld haben).

2. Für "Connection" zur DB gibt es zwar einen Oracle JDBC Driver, dessen "OJDBC6.jar"aber nicht enthalten ist (wahrscheinlich lizenzrechtliche Gründe).
Also: download des Treibers von: (11.2.)
oder für 12.1 usw.:

3. Installation des "externen JAR" ... in Jasper Reports Studio:
.. in "Projects" --> Properties:

--> ersten Eintrag rechts "add JARs..." - ich habe das .jar mit in ein Verzeichnis von JasperRports gelegt

4. Data Adapter anlegen:

... und es funzte sogleich - kaum macht man es richtig... cool.

4. eclipse und die Project Jar files: - interessant zu sehen....

5. Über den Project Explorer legt man ein neues Projekt an:

Ein 6-Min. Video zur Einführung der Komponenten und zur Erstellung eines Reports von Jaspersoft gibt es auf Youtube (inkl. Data Connection, Design Report, usw.) 

Kurzform: Myreport --> New --> Jasper Report --> Wizard startet... - Report Template (oder blank) auswählen --> "Report_File" (Name vergeben) vom Typ .jrxml... --> Next --> Data-Source wählen und mit "select * from Table" alle Spalten der Tabelle verfügbar machen
Über den Data Field Wizard die Spalten auswählen....--> Next "Group By" Wizard (einsetzen oder)  "Next" --> Finish ("Congratulations"-Meldung). --> Ergebnis:

wenn man dann auf "Preview" klickt, erscheint:

6. Nun das Ganze für APEX .... (18.1)

Dazu muss ich den Report kompilieren (rechte Maustaste) auf dem DEMO_Customers.jrxml... und es wird ein Demo_customers.jasper generiert.
Beide Dateien auf den Jasper Report Server kopieren... - zusätzlich die "coffee.jpg" und "coffee_stain.png", da diese im Header des Templates genutzt werden.
Wie? Rechte Maustaste: Copy Files_to.... --> lokal kopieren und dann per FTP auf den JR Server hochladen.
Da ich mit arbeite, konnte ich keine JR Server Verbindung herstellen (da geht es nur per FTP) - aber es scheint mir, dass man nach der Erstellung einer Connection zum JR Server (Erstellung wie eine Connection zu einer Data-Source) auch direkt dorthin hochladen kann mit "export" (z.B. bei lokaler Installation).

7. APEX 18.1
Dietmar Aust's Test-Application 
"JasperReportsIntegration Test (v1.3.0.2)" herunterladen, unzippen und als Application importieren.

entsprechend das Setup anpassen, bis alle Haken rechts grün sind.

Dann zur "Testpage" wechseln und die eigenen Parameter eintragen:

Zu Step 3. und 4. oben: der Jasper Reports Server lag bei mir (bei auf dem Server und ist deshalb ROT.

Der erste Button "Show report directly" brachte bei mir Fehler mit einem doppelten // for report...
Über den 2.Button "Show report (through APEX proxy)" den Report als pdf oder rtf oder xls/csv aufrufen:

Update 22.6.2018:

Zur Parameterübergabe siehe bitte den "alten" BLOG von Dietmar Aust.

Ich habe lange "rumprobiert".... - hier die Lösung:

Den von Dietmar erwähnten Prozess (siehe unten) auf der Seite, wo man drucken möchte hinzufügen, auf die eigenen Werte anpassen und dann per Button auslösen, dann erscheint der PDF- Report auf der Folgeseite.

Die Steps:
1. Selektliste der (bei mir) Kunden mit Return Value ID anlegen P1_KUNDE_ID
2. Interactive/Classic Report darunter anlegen mit
select * from SERVICES where KUNDE_ID = :P1_KUNDE_ID
damit der Benutzer sieht, was er ausgewählt hat (z.B. Services oder Kontakte des Kunden)
.. diese Auswahl möchte ich nun in der Corporate Identity des Kunden etwas nett ausdrucken...
3. Button anlegen: "Drucken"
4. Process anlegen mit u.e. pl/sql. - condition: when Button pressed: Drucken
(PS: die anderen JS und pl/sql Funktionen auf der Seite 5 USAGE von Dietmar Aust kann man ignorieren - ist aber gut zum Setup und Testen.

Hier der von mir angepasste pl/sql Prozess (von Dietmar Aust):

das Package xlib_jaspereports bringt die Installation der JRI Lösung von Dietmar Aust mit!

Re: xlib_jasperreports.set_report_url(:G_REPORT_URL);

die Jasper reports server URL kan man natürlich auch als Globale APEX Variable bei der Application angelegt: mit: http://servername:port

Jasper Reports Studio:
Für die Parameter muss man das SQL natürlich anpassen:

1. Im Design Modus des JasperReports unten links im Outline Pane auf "Parameter"  mit echter Maustaste: Create Parameter - einen Parameter anlegen: "parameter1" - die Properties dazu findet man unten rechts - Typ muss sein: java.class.String

2. Danach erneut im Outline Pane mit rechter Maustaste auf den Namen des Reports klicken und "Dataset and Query" aufrufen (Schnellzugriff oben rechts über dem Report-design - auch zum Kompilieren)

3. Dataset und Query Dialog

Zunächst oben die Datasource wählen - dann hat man Zugriff auf die Tabellen und kann rechts daneben im TEXT-Modues gleich normales SQL schreiben:

FROM user_objects
WHERE OBJECT_TYPE  = $P{parameter1}

Es gibt unten im Dialog auch einen "Run-Modus" , der bei mir MIT einem Parameter keine Daten anzeigte. 

Zurück im Haupt-Design-Editor kann man mit "Preview" den Report Testen. Für den Parameter kommt dann ein extra-Pane hoch, wo man die Query-Werte eingeben kann, die später über die URL an den Jasper Report Server gegeben werden.
Tipp: auch gemäß Doku soll der "parameter" in der Query immer "vorne" stehen,
$P(parameter1) = ... usw.
Um Schreibfehler zu vermeiden kann man auch im Dataset und Query Dialog (s.oben) unten links auf den Tab: Parameter gehen und die Parameter auswählen und per drag and drop in die SQL-Abfrage hineinziehen.

Tipp: um zu testen, ob die Parameter-Übergabe aus APEX heraus geklappt hat, habe ich im Header des Seiten-Layouts einfach den "parameter1" mit reingenommen (von unten links einfach in den Report reinziehen). 

Viel Erfolg!

PS: ein SEHR umfassendes und informatives PDF hat Markus Hohloch zusammengestellt.
Inkl. der Parameter-Übergabe.
Ein großes Danke dafür Markus !!!
Es gibt auch eine APEX Demo (Apex-experts) dafür, die aber derzeitig (1.5.2018) nicht läuft.