Tampilkan postingan dengan label Tips. Tampilkan semua postingan
Tampilkan postingan dengan label Tips. Tampilkan semua postingan

Senin, 12 April 2021

APEX_JSON.WRITE Tips

  • For null case

Use: APEX_JSON.write('P_INVOICE_TRACKING', '', true);

Result: "P_INVOICE_TRACKING":null 

  • For Escaping "& /" character 

Use: APEX_JSON.write_raw('P_INVOICE_NUMBER', '"'||r_header.sppd_code||'"');

Result: "P_INVOICE_NUMBER":"0134/XYZ/084/RS/2021" 

Rabu, 29 Maret 2017

Query APEX Metadata out of APEX Context

For example you need to query on sql developer or execute apex_email from oracle job

example:
Select *
  from APEX_MAIL_QUEUE;

result : no row selected
Solution : Create procedure to mimic APEX context
create or replace procedure set_apex_context (
  p_app_id in number 
) as 
begin
 FOR c1 IN (
   SELECT workspace_id
    FROM apex_applications
   WHERE application_id = p_app_id
  )
 LOOP
   apex_util.set_security_group_id(p_security_group_id => c1.workspace_id);
 END LOOP;
end set_apex_context;

How to use :
before execute query run the procedure:
execute set_apex_context (140); --i40 is app id 
Select *
  from APEX_MAIL_QUEUE;

Rabu, 18 Mei 2016

How to relocate datafile from one drive to other without shutdown db


  1. Login to SQL*Plus
  2. Connect as SYS DBA with CONNECT / AS SYSDBA command
  3. Make offline the affected tablespace
  4. ALTER TABLESPACE tablespace_name OFFLINE;
    
  5. Modify the name or location of datafiles in Oracle data dictionary using following command syntax:
  6. ALTER TABLESPACE tablespace_name
    RENAME DATAFILE 'fully qualified path to original data file name' 
    TO 'new or original fully qualified path to new or original data file name';
    
  7. Bring the tablespace online again
  8. ALTER TABLESPACE tablespace_name ONLINE;
    
  9. If you experienced this error : ORA-01113, execute this syntax:
  10. recover datafile 'new fully qualified path to original data file name'
    

source : otn

Kamis, 21 April 2016

Can You Build Application and Go Live in Six Months?

The answer is Yes we can, if:


  • We have the Operations Team with the concept of mature business processes and understand the systems approach when transform a manual process into the IT system.
  • You are an experienced developer and willing to adopt the best standards.
  • You have the end-user militant to jointly perform data entry and testing of applications, and then use it in everyday transactions.
  • Full support of the company's management.

  • I post this to share how to build an aplication with the concept of RAD (Rapid Application Develoment) can be achieved. Four factors I described above should be synergized to get there, if you are in the position of the second factor (as developers) usually have a tendency of less expensive non-technical factors, can be guaranteed not to be. As well as any best software you have if no synergy of all four of these factors it is not unattainable.

    Okay, to measure the success of an app I would narrow the parameters of what is called success :
    • Applications have Go Live and in use in everyday transactions replace existing manual processes
    • Maintaining business continuity between the actual processes and processes used in the IT application.
    Process & Team

    This is an example of a case when building an application "Tailor-Made" called IP-ICOFR CSA Online, I was fortunate enough to do so by a synergy of the four factors that I mentioned earlier.

    I would normally ask for a team that includes: business analyst, I as a developer and other components depending on the needs will be called "Operation Team". This team will become one entity, no longer act as lonely developer, despite the fact that I am the only developer :D, but to the unity of IT application system will be talking about all the problems and decided by this team.

    For myself, I do the following:
    • Provide enough time to build the Blue-print business process applications, with interview and fairly intensive discussion, do not rush to the design phase of the application until the blue-print is obtained.
    • To the business analyst I ask: "Do not let me do the assumptions of a process, give me certainty"
    • Do not always accept an idea without giving an alternative that is better if there is one. Because the business user perspective they should also be viewed and considered how it goes in the IT system.
    • Study the business processes in depth so that we will be able to predict how these applications will evolve in the future.
    • Mutual open to understanding ideas and receive feedback about how the system they will be built.
    From the Operation Team: Business Analyst side
    • Giving a good presentation to the management about: the staging, the process, the planned schedule, and asked for support for every phase of which will be run.
    • Understand that there are stages that will be achieved requires the process to be accommodated in a certain phase, it will not necessarily have to be adopted at that time.
    • All demand/request for features will be through team and filter based on: the need, and readiness phase. I relayed: "I just listen to one side, namely through Operation Team".
    • Always provide certainty of process, if still doubt be delayed until absolutely sure as to what it should be.
    Finally, with hard work and synergies of these four factors we succeeded in realizing a Go Live application within 6 months, which has been implemented into the entire units of PT. Indonesia Power
    • Kantor Pusat (Headquarters)
    • Unit Jasa Pemeliharaan
    • UJP Banten 1 Suralaya
    • UJP Banten 2 Labuan
    • UJP Banten 3 Lontar
    • UJP Banten 4 Cilegon
    • UJP Pelabuhan Ratu
    • UJP Adipala
    • UJP Pangkalan Susu
    • UPJP Priok
    • UP Suralaya
    • UP Saguling
    • UPJP Kamojang
    • UP Mrica
    • UP Semarang
    • UP Perak Grati
    • UPJP Bali
    Rundown Phase
    • 01 Nopember 2015 : Kick Off Project



  • 27-29 Januari 2016 : Workshop/UAT (Operation Team Level) - Bandung
  • 17-19 Februari 2016 : Workshop/UAT (User Admin Level) - Semarang
  • 11-15 April 2016 : Workshop/UAT (End User Level) - Bali
  • 21-23 April 2016 : Go Live (Indonesia Power's Annual Financial Forum 2016) – Jogjakarta



  • Technology
    • Oracle Application Express (APEX) 5.0.3.00.03 with ORDS Listener 3.0.2.294.08.40
    • Oracle Database Enterprise Edition Release 12.1.0.2.0 - 64bit (Linux Redhat)
    • Oracle WebLogic Server 12.2.1.0.0
    • Oracle BI Publisher 11.1.1.6.8

    Features
    • Flexible Setup : BPM & Hierachy Team
    • Multiplatform browser
    • Responsive Web Design
    • Email notification & Subscription
    • Interactive Reports
    • Multi format Report
    • Online Video tutorial

    ICOFR- Control Self Assesment References

    Selasa, 03 Februari 2015

    How to use modal pop-up region

    APEX telah menyediakan banyak contoh applikasi, salah satunya adalah Sample Dialog. Disitu kita akan belajar tentang bagaimana memakai dialog dengan teknik jQuery UI atau Custom Modal region untuk theme 25.

    Namun untuk kasus modal region kita akan lihat bahwa modal dialog default adalah false. 
    oh ya..saran saya jika kita memakai Theme 25 untuk membangun applikasi lebih baik kita bangun dialog dengan memakai region modal jangan memakai UI dialog biasa untuk pertimbangan estetika tampilan yg lebih oke. Untuk membuat modal dialog menjadi "true" maka tambahkan kode berikut saat memanggil regionnya.
    function(){
      openModal('addDept');
      gBackground.off('click');
    }
    
    Untuk pemakaian dalam form process pop-up, nanti saya akan posting dengan kombinasi iFrame.

    Note : Terima kasih buat bro Hoki yang telah men-debug dan mencarikan solusinya.

    Sabtu, 17 Januari 2015

    Miscellaneous Javascript APIs

    • $x(pNd)
    • Adalah sebuah padanan dari getElementById(). Dengan pNd adalah id dari DOM atau string "id". returnnya adalah DOM element atau false jika tidak ada.
      contoh : $x(P43_TEXT) atau $x("P43_TEXT").
      Pemakaian untuk get: $x("P43_TEXT").value, $x("P43_TEXT").name
      Pemakaian untuk set: $x("P43_TEXT").value="Test", $x("P43_TEXT").name="test"
      Namun tidak semua jenis item dapat dilakukan operasi tersebut seperti checkbox, selectlist dan shuttle.
    • $v(pNd), $v2(pNd), apex.item(pNd).getValue(),$f_SelectValue(pNd) dan $("#pNd").val()
    • Semuanya pada dasarnya adalah untuk mendapatkan value dari sebuah item, namun memiliki beberapa perbedaan. Pada test kasus item berikut :
      • Hidden, text, text area, date picker, popup lov (basis input) semua berhasil memperoleh value, khusus untuk display only $("#pNd").val() memakai $("#pNd").text()
      • selectlist, checkbox, radiogroup, list manager hanya $v(pNd) $v2(pNd) apex.item(pNd).getValue() dan $f_SelectValue(pNd) yang bisa memperoleh value
      • $v2(pNd) adalah shortcut untuk apex.item(pNd).getValue()
      • untuk kasus item multiple value perbedaan dari $v(pNd) dan $v2(pNd) adalah $v(pNd) mendapatkan nilai persis string dari item sedangkan $v2(pNd) dalam bentuk array
      • Kesimpulan yang dapat diambil adalah selalu gunakan APEX APIs $v(pNd) atau $v2(pNd) untuk mengambil nilai item.
    • $s(pNd, pValue, pDisplayValue, pSuppressChangeEvent), apex.item( pNd ).setValue(pValue, pDisplayValue, pSuppressChangeEvent), $x_Value(pNd,pValue) dan $("#pNd").val("pValue")
    • Sama halnya dengan kasus get selalu gunakan APEX APIs, $s(pNd, pValue, pDisplayValue, pSuppressChangeEvent) adalah shortcut untuk apex.item( pNd ).setValue(pValue, pDisplayValue, pSuppressChangeEvent). Kelebihan dari $s( pNd,pValue, pDisplayValue, pSuppressChangeEvent) adlah kita bisa melakukan pada semua jenis item dengan bisa mengatur pSuppressChangeEvent property ini berguna dalam urusan Dynamic Actions
    • Silahkan coba fungsi2 diatas pada page demo berikut

    Jumat, 10 Oktober 2014

    Get Yahoo Exchange Rate using PL/SQL

    Setelah mencari api yang disediakan oleh Bank Indonesia atau bank-bank swasta/nasional indonesia tidak tersedia. maka dengan terpaksa kebutuhan exchange rate real time saya ambil dari yahoo api.

    Melalui Yahoo Query Language kita dapat peroleh URI untuk exchange rate USD-IDR :

    http://query.yahooapis.com/v1/public/yql?q=select * from yahoo.finance.xchange where pair in ("USDIDR")&env=store://datatables.org/alltableswithkeys
    

    Lalu kemudian kita bangun fungsi didalam oracle untuk bisa dipakai dalam operasi sql pl/sql atau di APEX.

    create or replace function get_yahoo_rate 
    return number 
    is
    
    /******************************************************************************
       NAME:       get_yahoo_rate
       PURPOSE:    get latest USD-IDR rate from Yahoo finance exchange
    
       REVISIONS:
       Ver        Date        Author           Description
       ---------  ----------  ---------------  ------------------------------------
       1.0        10/10/2014   Lutfi Hedir     1. Created this function.
    
    ******************************************************************************/
      l_xml xmltype;
      l_yahoo_uri constant varchar2(500) := 'http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.xchange%20where%20pair%20in%20(%22USDIDR%22)&env=store://datatables.org/alltableswithkeys';
      l_rate      varchar2(500);
      l_rate_n    number(10);
    begin
      -- get xml data
      l_xml := xmltype(utl_http.request(l_yahoo_uri));
      -- extract rate value from xml data  
      select extractvalue(l_xml, '/query/results/rate/Rate/text()') into l_rate
        from dual;  
      -- convert to number   
      l_rate_n := to_number(REGEXP_SUBSTR(l_rate,'[0-9]+'));
      
      return l_rate_n;
      
    end get_yahoo_rate;
    /
    
    

    Catatan :
    • Jangan lupa setting ACL untuk 11g supaya bisaakses internet.
    • Jika akses SSL buatlah wallet terlebih dahulu
    • Jika akses proxy modifikasi utl_http.request dengan signature proxy dan wallet

    Selasa, 23 September 2014

    How to create executable package/procedure on URL

    Posting ini sebenarnya pernah saya bahas, namun sekarang saya akan membahasnya lebih spesifik pada download file dengan web server apex listener.

    Adapun hal yang harus diperhatikan pada bagian
    1. Package/procedure
      • Contoh
      • create or replace PACKAGE BODY web_utils IS
          -- retrieves image from blob in product info
          PROCEDURE display_bu_logo (p_id number, p_product_name varchar2) 
          IS
            l_mime        varchar2 (255);
            l_length      number;
            l_file_name   varchar2 (2000);
            lob_loc       blob;
          begin
            if p_id is not null then
              select mimetype
                   , filename
                   , nvl(product_image, empty_blob()) blob_content
                   , dbms_lob.getlength(product_image)
                into l_mime
                   , l_file_name
                   , lob_loc 
                   , l_length
                from demo_product_info
               where product_id = p_id;    
            elsif p_product_name is not null then
              select mimetype
                   , filename
                   , nvl(product_image, empty_blob()) blob_content
                   , dbms_lob.getlength(product_image)
                into l_mime
                   , l_file_name
                   , lob_loc 
                   , l_length
                from demo_product_info
               where lower(product_name) = lower(p_product_name);     
            end if;
        
        
           owa_util.mime_header (nvl (l_mime, 'application/octet'), false);
        
           -- set the size so the browser knows how much to download
           htp.p ('Content-length: ' || l_length);
           -- the filename will be used by the browser if the users does a save as
           htp.p (   'Content-Disposition:  attachment; filename="'
                  || replace (replace (substr (l_file_name,
                                               instr (l_file_name, '/') + 1
                                              ),
                                       chr (10),
                                       null
                                      ),
                              chr (13),
                              null
                             )
                  || '"'
                 );
        
           -- close the headers
           owa_util.http_header_close;
           -- download the BLOB
           wpg_docload.download_file (lob_loc);
        
          END display_bu_logo;
        END web_utils;
        
      • Tambahkan nvl(lob_column, empty_blob())
      • Gunakan htp.p
      • Untuk kasus image jika ingin tampil inline, lakukan comment pada bagian
      • --   htp.p (   'Content-Disposition:  attachment; filename="'
        --          || replace (replace (substr (l_file_name,
        --                                       instr (l_file_name, '/') + 1
        --                                      ),
        --                               chr (10),
        --                               null
        --                              ),
        --                      chr (13),
        --                      null
        --                     )
        --          || '"'
        --         );
        
    2. Security
      • Anda harus tahu environment server apa yang dipakai, apakah EPG, OHS atau APEX Listener
      • Untuk APEX Listener/OHS anda cukup grant APEX_PUBLIC_USER
      • Untuk OHS grant APEX_PUBLIC_USER dan daftarkan procedure yang akan dipanggil di APEX_XXXXXX.wwv_flow_epg_include_mod_local
      • Untuk EPG anda grant ke ANONYMOUS dan aktifkan procedure di APEX_XXXXXX.wwv_flow_epg_include_mod_local
    3. Cara memanggil dengan signature parameter.
      • mulai dengan ? pisahkan dengan &
      • Posisi tidak penting namun harus disebutkan semua kecuali punya default value
      • Untuk kasus APEX listener parameter signature akan selalu dirubah dengan menjadi lowercase, hati-hati jika memakai parameter non-case-sensitive seperti BI Publisher web service
      • contoh
      • http://localhost:8888/ords/hr.web_utils.display_bu_logo?p_product_name=Blouse&p_id=
        
      • contoh array parameter
      • http://localhost:8888/ords/!hr.web_utils.display_bu_logo?p_product_name=Blouse&p_id=
        
    Catatan :
    • APEX Listener / ORDS 2.0.8.163.10.40

    Sabtu, 14 Juni 2014

    ORA-02069: global_names parameter must be set to TRUE for this operation

    Pernah mengalami error seperti itukah?
    jika anda menggunakan operasi DML terhadap sebuah database link maka mungkin anda akan mengalami hal tersebut.

    Cause : You are trying to make DML operation on the remote database using local function.
    artinya anda memakai sebuah lokal function untuk digunakan dalam proses DML.
    contoh :
     
    insert into mytable@mylink 
         ( ename
         , nipeg
         , start_date
         , end_date)
    select ename
         , nipeg
         , get_start(nipeg)
         , get_end(nipeg)
      from emp;
    

    Itu karena  value dari global name database anda adalah false :
    SELECT NAME, VALUE 
      FROM V$PARAMETER
     WHERE NAME = 'global_names'

    Biasanya developer bukan seorang DBA, maka solusi yang bisa pakai tanpa merubah value global name menjadi true adalah merubah proses DML dengan tidak memakai fungsi get_start,get_end secara langsung dalam proses insert. bisa memakai sebuah cursor atau collection. Merubah global name value menjadi TRUE juga memberi implikasi pada dblink yang lain, kemungkinan besar akan error jika tidak memakai nama link seperti global names db tujuan
    Contoh dalam cursor :
    begin
      for c_emp in ( select ename
                          , nipeg
                          , get_start(nipeg) start_date
                          , get_end(nipeg) end_date
                       from emp)
      loop
        insert into mytable@mylink 
             ( ename
             , nipeg
             , start_date
             , end_date)
        values 
             ( c_emp.ename
             , c_emp.nipeg
             , c_emp.start_date
             , c_emp.end_date);
      end loop;
    end;
    
    contoh dalam collection :
    declare
     type t_emp is table of mytable@mylink%rowtype
          index by pls_integer;
     c_emp t_emp;
    begin
      select ename
           , nipeg
           , get_start(nipeg) start_date
           , get_end(nipeg) end_date
        bulk  collect  
        into c_emp;
    
      for i in c_emp.first .. c_emp.last
      loop
        insert into mytable@mylink 
             ( ename
             , nipeg
             , start_date
             , end_date)
        values (c_emp(i).ename
             , c_emp(i).nipeg
             , c_emp(i).start_date
             , c_emp(i).end_date);
      end loop;
    end;

    Catatan : anda tidak bisa memakai operasi forall thd database link;

    Kamis, 01 Mei 2014

    Hidden treasure of Interactive Report

    Salah satu feature terbaik dari APEX adalah Interactive Report. Pada posting kali ini saya akan membuka feature dari IR dalam hal query reference.

    • Feature query IR<OPERATOR>_<COLUMN_ALIAS>.
    • Salah satu yang sering kita pakai adalah IR_DEPARTMENT_ID artinya kita melakukan filter terhadap kolom department ID, IR by default: EQUAL. Ternyata banyak lagi operator yang bisa kita pakai dalam melakukan filter.
      Daftar valid operator
    Operator Description
    EQ Equals (this is the default)
    NEQ Not equals
    LT Less than
    LTE Less than or equal to
    GT Greater than
    GTE Greater than or equal to
    LIKE SQL 'like' operator
    N is null
    NN is not null
    C Contains
    NC not contains
    IN SQL 'in' Operator
    NIN SQL 'not in' Operator
      sumber : Advanced Interactive Report by David Peake.
       
    • URL reference terhadap saved report.
    • Jika kita memiliki beberapa saved report, maka kita bisa melakukan reference ke page tujuan dengan memilih apakah memakai saved report 1 atau yang lain dalam contoh : IR_REPORT_DEFAULT atau IR_REPORT_CHART.

    Selasa, 04 Maret 2014

    Handling ssl on Soap UI

    Jika anda mengalami masalah saat url ssl pada Soap UI seperti berikut :


    Maka perlu lakukan hal berikut untuk menambahkan certificate keystore ke dalam cacerts Soap UI:
    • Import certificate root kedalam file contoh : D:\myca.cer (gunakan Chrome atau IE).
    • lalu memakai bantuan java buka command prompt, pastikan PC anda telah terinstall java sdk
    • lalu jalankan perintah berikut : keytool -import -alias owsservices -file -keystore "c:\program files (x86)\smartbear\soapui-4.6.4\jre\lib\security\cacerts".
    Jika masih bermasalah coba jalankan script diatas di java bin lengkap contoh : C:\Program Files\Java\jdk1.6.0_31\bin

    Note : Thanks Hoki for point this out.

    Jumat, 14 Februari 2014

    APEX, QR Code dan googleapis

    Pada dasarnya QR code bisa memakai third party atau bisa di install sendiri untuk menghasilkan return URL atau binary.Pada kasus ini kita akan mencoba memakai googleapis yang mengembalikan image .png (binary).

    Adapun hal yang bisa kita lakukan pada Oracle APEX adalah.

    --- create new ACL for HR
    BEGIN
      DBMS_NETWORK_ACL_ADMIN.create_acl (
        acl          => 'hr_acl_file.xml', 
        description  => 'A test of the ACL functionality',
        principal    => 'HR',
        is_grant     => TRUE, 
        privilege    => 'connect',
        start_date   => SYSTIMESTAMP,
        end_date     => NULL);
    
      COMMIT;
    END;
    /
    -- assign ACL to networks chart.googleapis.com
    BEGIN
      DBMS_NETWORK_ACL_ADMIN.assign_acl (
        acl         => 'hr_acl_file.xml',
        host        => '*.googleapis.com', 
        lower_port  => 80,
        upper_port  => 9999); 
    
      COMMIT;
    END;
    /
    
    • Buat wallet memakai OWM atau ORAPKI (jika akses SSL).
    • Buat function atau procedure input URL yang mereturn Binary.
    • Lalu tampilkan dalam Report dan Form process APEX untuk menyimpan ke dalam BLOB kolom. 
    • declare
        v_encode_url varchar2 (1000);
      begin
       v_encode_url := 'https://chart.googleapis.com/chart?chs='||:P2_SIZE||'&cht=qr&chl='||utl_url.escape(:P2_QRCODE);
          update emp
          set EMP_PHOTO =  return_binary_from_url (v_encode_url)           
             , ATTACH_MIMETYPE =  'image/png'         
             , ATTACH_FILENAME  =  :P2_EMPNO||'_QR_CODE.png'          
             , ATTACH_LAST_UPDATE = sysdate            
          where empno = :P2_EMPNO;
      end;
      
    Penampakan sebelum upload:

    Penampakan sesudah upload:

    Cara test koneksi tanpa proxy :
     
    select utl_http.request('https://www.google.com'
                             , null
                             , 'file:/mywallets/google.com'
                             , 'your wallet password')
      from dual;
    

    Cara test koneksi dengan proxy :
     
    select utl_http.request('https://www.google.com'
                             , 'username:pwdproxy@yourproxyhost:yourproxyport'
                             , 'file:/mywallets/google.com'
                             , 'your wallet password')
      from dual;
    

    Demo tidak bisa dibuat di apex.oracle karena tidak memungkinkan setup ACL dan wallet

    Sabtu, 08 Februari 2014

    QR Codes on APEX

    Anda ingin menampilkan QR code kedalam APEX seperti ini ?
    Jangan khawatir anda bisa memakai bantuan Google Developer untuk menampilkan di APEX.

    Demo : di sini

    Sabtu, 01 Februari 2014

    Dynamic Highlight on classic & interactive report

    Pada posting kali ini sya akan menunjukkan bagaimana melakukan highlight secara bersamaan pada classic report dan interactive report memakai Dynamic Action(DA).

    Skenario :
    • Sebuah Item Parameter bisa hidden atau select list : PXX_DEPT_HL.
    • Sebuah report classic thd : DEPT 
    • select null "icon"
      ,deptno, DNAME
      ,case when deptno = :PXX_DEPT_HL then 'HIGHLIGHT' else null end HIGHLIGHT 
      from dept
      
    • Sebuah report interactive EMP.
    • select EMP.EMPNO as EMPNO,
          EMP.ENAME as ENAME,
          EMP.JOB as JOB,
          EMP.MGR as MGR,
          EMP.HIREDATE as HIREDATE,
          EMP.SAL as SAL,
          EMP.COMM as COMM,
          EMP.DEPTNO as DEPTNO ,case when deptno = :PXX_DEPT_HL then 'HIGHLIGHT' else null end HIGHLIGHT 
       from EMP EMP
      
    • Saat icon pada report calssic di clik / atau nilai PXX_DEPT_HL berubah akan memeri hilghlight pada kedua report sesuai nilainya

    Logic :
    • Pada column icon buatlah sebuah link dengan action url:
      javascript:$s('PXX_DEPT_HL','#DEPTNO#');
    • Pada column dname HTML Expression:
      <span id="#HIGHLIGHT#DNAME#R#">#DNAME#</span>
    • Pada report interactive buatlah format highlight row dengan kodisi highlight=HIGHLIGHT.
    • Buatlah DA thd item PXX_DEPT_HL dengan event : change dan action : refresh report classic.
    • Buatlah DA pada report classic dengan event : after refresh dengan action : Execute Javascript Code :
      $("[id^=HIGHLIGHT]").closest('tr').children('td').css("background-color", "#FD4");
      dan Refresh region report interactive.

    Demo : disini

    Selasa, 28 Januari 2014

    Dynamic Interactive Report Using Collection

    Salah satu kelemahan Interactive Report (IR) adalah hanya menyediakan type source SQL tidak ada pilihan untuk PL/SQL. Sehingga kita tidak bisa membuat dynamic query seperti pada classic report.


    Namun hal tersebut masih kita bisa cari solusinya dengan cara :
    • Membuat function return table pipelined atau.
    • Memakai bantuan query terhadap APEX collection.
    Pada posting saya ini akan menjelaskan pada teknik kedua yaitu Memakai bantuan query terhadap APEX collection.

    Skenario :
    • Kita akan membuat IR thd semua tabel yang ada di  skema HR untuk contoh demo (EMP & OEHR_EMPLOYEES).
    • Kita hanya membatasi max  kolom sejumlah 10.
    • Skema akses apex memiliki system privilege : SELECT ANY DICTIONARY.
    Logic & Process :
    • Membuat sebuah fungsi  yg secara dinamis bisa me-return 10 nama kolom tabel input.
    • create or replace 
      function get_report_headers 
      (
        p_table     in varchar2 default 'EMP'
      , p_separator in varchar2 default ','
      , p_type      in varchar2 default 'HEADER'
      , p_num       in number default 1
      ) return varchar2 as 
        v_temp_arr apex_application_global.vc_arr2;
        v_list varchar2(32767);
      begin
       if p_type = 'HEADER' then
        SELECT column_name bulk collect
          into v_temp_arr
          FROM USER_TAB_COLUMNS
         WHERE owner = 'HR'
           and table_name = p_table
           and owner = 'HR'
           and data_type <> 'BLOB'
         order by column_id;
        v_list := apex_util.table_to_string(v_temp_arr,p_separator); 
        return v_list;
       else
        if p_num > 10 then
         v_list := null;
        else
         begin 
          SELECT initcap(REPLACE(column_name,'_',' ')) 
            into v_list
            FROM USER_TAB_COLUMNS
           WHERE owner = 'HR'
             and table_name = p_table
             and owner = 'HR'
             and column_id = p_num; 
          exception when others then v_list := null;   
         end;    
         end if;
        return v_list;   
        
       end if;
      end get_report_headers;
      
    • Buatlah sebuah page dengan 10 item dan sebuah IR.
    • Pada before header buatlah sebuah process untuk membuat sebuah collection unik.
    • declare
       v_query VARCHAR2(32767):=null;
       v_collection varchar2(100) := nvl(:P20_COLL_NAME,'DYNAMIC_'||:SESSION_ID);
      begin
       v_query := 'select '||
                   get_report_headers(p_table => :P20_TABLE_NAME) ||
                  ' from HR.' || nvl(:P20_TABLE_NAME,'EMP');
      
      IF APEX_COLLECTION.COLLECTION_EXISTS (p_collection_name => v_collection) THEN                 
        APEX_COLLECTION.DELETE_COLLECTION(p_collection_name => v_collection);
        APEX_COLLECTION.CREATE_COLLECTION_FROM_QUERY(p_collection_name => v_collection
                                                    ,p_query           => v_query );
      else
        APEX_COLLECTION.CREATE_COLLECTION_FROM_QUERY(p_collection_name => v_collection
                                                    ,p_query           => v_query );
      end if;
      end;
      
    • Pada before header buatlah sebuah process mengisi 10 item yang telah dipersiapkan untuk nama header kolom.
    • :P20_C01 := get_report_headers(p_table => :P20_TABLE_NAME,p_type => 'COLUMN', p_num => 1);
      :P20_C02 := get_report_headers(p_table => :P20_TABLE_NAME,p_type => 'COLUMN', p_num => 2);
      :P20_C03 := get_report_headers(p_table => :P20_TABLE_NAME,p_type => 'COLUMN', p_num => 3);
      :P20_C04 := get_report_headers(p_table => :P20_TABLE_NAME,p_type => 'COLUMN', p_num => 4);
      :P20_C05 := get_report_headers(p_table => :P20_TABLE_NAME,p_type => 'COLUMN', p_num => 5);
      :P20_C06 := get_report_headers(p_table => :P20_TABLE_NAME,p_type => 'COLUMN', p_num => 6);
      :P20_C07 := get_report_headers(p_table => :P20_TABLE_NAME,p_type => 'COLUMN', p_num => 7);
      :P20_C08 := get_report_headers(p_table => :P20_TABLE_NAME,p_type => 'COLUMN', p_num => 8);
      :P20_C09 := get_report_headers(p_table => :P20_TABLE_NAME,p_type => 'COLUMN', p_num => 9);
      :P20_C10 := get_report_headers(p_table => :P20_TABLE_NAME,p_type => 'COLUMN', p_num => 10);
      
    • Buatlah IR :
    • select *
        from APEX_collections
       where collection_name = :P20_COLL_NAME;
      
    • Buatlah heading column secara dinamis me-refer ke item serta kondisi thd nilai item reference (C001...C010).
    • Buatlah semua kolom condition : never (selain C001...C010).
    Demo :  Dynamic IR with collection

    Sabtu, 25 Januari 2014

    Shuttle Item on APEX

    Pada posting kali ini saya akan membahas bagaimana memakai Shuttle Item pada APEX. yang meliputi bagaimana :
    • Membuat default value berdasarkan isi tabel.
    • Submit kedalam tabel.
    • Melakukan filter nilai lihat detil di post ini : Enhanced Shuttle Item by Christoper Beck.
    • Dynamic Action (DA) terhadap Shuttle Item untuk mengambil nilai.
    • Dynamic Action (DA) terhadap Shuttle Item untuk melakukan query thd report EMP-DEPT.
    Skenario kita adalah table EMP sebagai source pegawai dan EMP_ASSIGN sebagai data pegawai yang telah dipilih dalam Shuttle Ittem. Table EMP_ASSGIN hanya berisi satu kolom atau lebih yang menyimpan data EMPNO dan EMPNAME.

    • Membuat default value berdasarkan isi tabel.
    Pada bagian ini anda harus sudah membuat shuttle item (PXX_SELECTED_EMPLOYEES) dengan query sbb:
    SELECT ENAME
         , EMPNO
      FROM EMP
    ORDER by 1
    
    Lalu pada bagian render before header buatlah process : GET_SELECTED:

    declare
     l_emp_array wwv_flow_global.vc_arr2;
     l_list varchar2(32767);
    begin
     -- get all selected emp into array
     select empno 
       bulk collect
      into l_emp_array
      from emp_assign;
     -- convert array to colon seperated string
      l_list := apex_util.table_to_string(l_emp_array,':');
     :PXX_SELECTED_EMPLOYEES := l_list;
    end;
    

    Proses selanjutnya adalah bagaimana cara melakukan submit pegawai yang dipilih kedalam sebuah tabel.
    • Submit kedalam tabel.
    Pada bagian submitting page buatlah sebuah proces : SUBMIT_ASSIGNMENT :
    DECLARE
    v_selected APEX_APPLICATION_GLOBAL.VC_ARR2;
    BEGIN
     --delete existing assignment
     delete emp_assign;
    
     -- Convert the colon separated string into an array
     v_selected := APEX_UTIL.STRING_TO_TABLE(:PXX_SELECTED_EMPLOYEES);
    
     -- Loop over array and insert into table
     FOR i IN 1..v_selected.count LOOP
       insert into emp_assign
         (empno)
       values
         (v_selected(i));
    END LOOP;
    END;
    

    Lalu proses selanjutnya adalah bagaimana memberi sebuah proses DA thd shuttle, dalam contoh ini kita akan mengambil nilai EMPNO yang dipilih kedalam sebuah text item : PXX_SELECTED_EMPNO.
    • Dynamic Action (DA) terhadap Shuttle Item untuk mengambil nilai.
    Pada proses ini buatlah DA thd PXX_SELECTED_EMPLOYEES beri nama :shuttle_changed dengan event : CHANGE. dengan kondisi is null, ini adalah bagian tricky khusus untuk tipe item shuttle, karena untum item biasa kita tidak pelu membuat kondisi biasanya :D.

    Lalu pada TRUE action lakukan proses action Set Value dengan PL/SQL Expression : null.
    Pada FALSE action Set Value dengan Javascript Expression :
    $v("PXX_SELECTED_EMPLOYEES")
    .
    Keduanya terhadap Effected Elements : item : PXX_SELECTED_EMPNO.

    Beres....

    Keterangan :

    Rabu, 05 Juni 2013

    Beberapa hal yang harus diperhatikan saat memakai apex_mail

    Salah satu API yang disediakan oleh APEX adalah send email melalui APEX_MAIL. Dari contoh API kita bisa mengirimkan email baik text atau format html. Contoh :
    DECLARE
     l_body CLOB;
     l_body_html CLOB;
    BEGIN
     l_body := 'To view the content of this message, please use an HTML enabled mail client.'||utl_tcp.crlf;
     l_body_html := '<html>
                     <head>
                     <style type="text/css">
                     body{font-family: Arial, Helvetica, sans-serif;
                     font-size:10pt;
                     margin:30px;
                     background-color:#ffffff;}
                     span.sig{font-style:italic;
                     font-weight:bold;
                     color:#811919;}
                     </style>
                     </head>
                     <body>'||utl_tcp.crlf;
     l_body_html := l_body_html ||'<p>Thank you for your interest in the <strong>APEX_MAIL</strong> package.</p>'||utl_tcp.crlf;
     l_body_html := l_body_html ||' Sincerely,<br />'||utl_tcp.crlf;
     l_body_html := l_body_html ||' <span class="sig">The APEX Dev Team</span><br/>'||utl_tcp.crlf;
     l_body_html := l_body_html ||'</body></html>';
     apex_mail.send( p_to => 'some_user@somewhere.com', -- change to your email address
                     p_from => 'some_sender@somewhere.com', -- change to a real senders email address
                     p_body => l_body,
                     p_body_html => l_body_html,
                     p_subj => 'APEX_MAIL Package - HTML formatted message');
    END;
    /
    

    Beberapa error yang muncul seperti :

    • PLS-00307: too many declarations of 'SEND'
    • Hal ini terjadi jika type yang tidak sama anda berikan pada value p_body dan p_body_html pastikan jika memakai varchar2 semua atau clob semua

    • ORA-06502: PL/SQL: numeric or value error
    • Hal ini terjadi kita memakai clob dengan data memakai concate '||'yang melebihi kapasitas varchar2(32767)

      Solusinya kita dapat mengganti dengan tipe data CLOB dengan memakai DBMS_LOB.APPEND, pada contoh diatas dapat dimodifikasi dengan cara

      DECLARE
       l_body CLOB;
       l_body_html CLOB;
      BEGIN
       l_body := 'To view the content of this message, please use an HTML enabled mail client.'||utl_tcp.crlf;
       dbms_lob.createtemporary (l_body_html,true);
       DBMS_LOB.append (l_body_html,'<html>
                       <head>
                       <style type="text/css">
                       body{font-family: Arial, Helvetica, sans-serif;
                       font-size:10pt;
                       margin:30px;
                       background-color:#ffffff;}
                       span.sig{font-style:italic;
                       font-weight:bold;
                       color:#811919;}
                       </style>
                       </head>
                       <body>');
       DBMS_LOB.append (l_body_html,'<p>Thank you for your interest in the <strong>APEX_MAIL</strong> package.</p>');
       DBMS_LOB.append (l_body_html,' Sincerely,<br />');
       DBMS_LOB.append (l_body_html,' <span class="sig">The APEX Dev Team</span><br/>');
       DBMS_LOB.append (l_body_html,'</body></html>');
       apex_mail.send(p_to => 'some_user@somewhere.com', -- change to your email address
                      p_from => 'some_sender@somewhere.com', -- change to a real senders email address
                      p_body => l_body,
                      p_body_html => l_body_html,
                      p_subj => 'APEX_MAIL Package - HTML formatted message');
       dbms_lob.freetemporary (l_body_html);  
      END;
      /
      

    Selasa, 14 Mei 2013

    Multiple Interactive Report with Synchronize Link

    Beberapa pertanyaan tentang bagaimana memanipulasi interactive report (IR) dalam satu page sambil menunggu APEX 5. kita bisa lakukan dengan cara berikut.
    Contoh kasus kita akan membuat sebuah 3 IR dalam satu page.

    • Page 27 adalah IR1 (DEMO_CUSTOMERS).
    • Page 29 adalah IR2 (DEMO_ORDERS).
    • Page 30 adalah IR3 (DEMO_ORDERS).

    Pada page 27 buatlah 3 region seperti gambar berikut :

    • Region IR 1 : IR report dengan link: redirect ke page 27 dengan ngisi item P27_CUSTOMER_ID dengan value #CUSTOMER_ID# dengan request REDIR
    • Region IR 2 : dengan subregion Frame 2.
      • Bagian header
      • <iframe src="f?p=&APP_ID.:29:&SESSION."
              style="width:500px;height:500px"
              name="details"
              scrolling="no" marginwidth="0" marginheight="0"
              frameborder="0" vspace="0" hspace="0" >
        
      • Bagian footer
      • </iframe>
        
    • Region IR 3 : dengan subregion Frame 3.
      • Bagian header
      • <iframe src="f?p=&APP_ID.:30:&SESSION."
              style="width:500px;height:500px"
              name="details1"
              scrolling="no" marginwidth="0" marginheight="0"
              frameborder="0" vspace="0" hspace="0" >
        
      • Bagian footer
      • </iframe>
        

    Lalu pada page 29 dan 30 buatlah IR dengan hidden item P29_CUSTOMER_ID dan P30_CUSTOMER_ID dengan query report:
    select ORDER_ID, CUSTOMER_ID, ORDER_TOTAL, ORDER_TIMESTAMP
    from DEMO_ORDERS
    where customer_id=:P29_CUSTOMER_ID
    

    Lalu langkah terakhir pada page 27 buatlah sebuah dynamic action
    • Event:Page Load
    • Condition: Request=Expression1 dengan Expression 1 =REDIR
    • True Actions : Execute javascript Code
    • code :
    • top.frames['details'].location.href = 'f?p=&APP_ID.:29:&SESSION.::&DEBUG.::P29_CUSTOMER_ID:&P27_CUSTOMER_ID.';top.frames['details1'].location.href = 'f?p=&APP_ID.:30:&SESSION.::&DEBUG.::P30_CUSTOMER_ID:&P27_CUSTOMER_ID.';
      

    Demo aplikasi bisa lihat disini.

    Sabtu, 30 Maret 2013

    Merubah cookie APP_USER secara permanen

    Cookie APP_USER adalah sebuah penampung yang dibuat APEX untuk menyimpan nama user Aunthenticated. contoh username kita entry lutfi hedir. Lalu cookies tersebut bisa kita ubah didalam aplikasi menjadi lutfi.hedir dengan cara membuat sebuah proses dengan block seperti ini.
    begin
    --set user menjadi nama tertentu cara 1
    apex_custom_auth.set_user('lutfi.hedir');
    --set user menjadi nama tertentu cara 2
    wwv_flow.g_user := 'lutfi.hedir';
    end;
    

    Yang harus diperhatikan adalah dimana akan dijalankan code tersebut. Jika anda tidak ingin secara permanen maka dapat dilakukan di proses page on load before header atau tempat lain sesuai keinginan. Namun jika ingin merubah secara permanen maka satu-satunya cara harus di lakukan pada Post-Authentication Procedure Name. Karena jika dilakukan diluar itu maka APP_USER akan tetap seperti USERNAME dimana kita entry pada saat login. meskipun kita lakukan proses di application proses on load before header, tetap APP_USER tidak berubah yang berubah disaat proses render saja, tapi jika digunakan dalam proses authorization APP_USER kembali seperti semula, atau jika digunakan dalam database trigger dengan memanggil v('APP_USER') maka kembali APP_USER akan dikenali sebagai lutfi hedir bukan lutfi.hedir.
    Jadi anda harus buat sebuah procedure dalam database contoh my_post_login dengan code sbb:
    create or replace procedure my_post_login is 
     begin 
       apex_custom_auth.set_user('lutfi.hedir'); 
     end my_post_login;
    

    lalu gunakan my_post_login dalam Post-Authentication Procedure Name. Selamat mencoba
    Sumber : Oracle APEX Forum

    Rabu, 27 Maret 2013

    Delete multiple file on APEX metadata

    Untuk keperluan delete file yang ada di aplikasi APEX, APEX telah menyediakan tool untuk melakukan delete file, cuma masih harus satu persatu. jadi kalau kita ingin melakukan banyak file itu yang jadi masalah.

    Namun di dalam apex sendiri telah diberikan script untuk melakukan delete metadata tsb contoh saat kita ingin menghapus image "xxx.jpg" maka scriptnya adalah
    begin
        wwv_flow_api.create_or_remove_file( 
            p_location => 'APPLICATION',
            p_name     => 'xxx.jpg',
            p_mode     => 'REMOVE',
            p_type     => 'IMAGE');
    end;
    /
    

    Yang perlu diperhatikan adalah p_type bisa 'IMAGE','CSS'atau 'STATIC'. jadi untuk hapus secara banyak contoh satu WS maka kita harus modifikasi seperti ini. contoh dibawah adalah saya ingin menghapus seluruh image yang tersimpan dalam WS='TEST'.

    declare
     v_id number;
     v_ws varchar2(100):='TEST';
    begin
    --- cari workspace ID
    select workspace_id into v_id
    from apex_workspaces
    where WORKSPACE=upper(v_ws);
    ---set security supaya bisa di exsekusi diluar apex 
    wwv_flow_api.set_security_group_id(v_id);
    ---cursor 
    FOR x IN (select *
    from APEX_WORKSPACE_FILES
    where MIME_TYPE like 'image/%') LOOP
        wwv_flow_api.create_or_remove_file( 
            p_location => 'WORKSPACE',
            p_name     => x.FILE_NAME,
            p_mode     => 'REMOVE',
            p_type     => 'IMAGE');
    END LOOP;
    commit;
    end;
    /