Thursday, October 29, 2009

Calling a PL/SQL Procedure from Form Persnalization

Question: How to invoke PL/SQL Code from Form personalization.

Answer: Using Action Type: "Builtin" and Builtin Type: "Execute a Procedure".
Little background about my requirement here..
- Wanted to gather inventory valuations in system.
- When ? -  At Period closing time in Inventory.
In short - need to capture Inventory On-Hand quanties as at month-end closing period.

So to implement solution for the above requirement, I did small R&D shown below,  before starting actual development.
Initially thought of developing a DB trigger, which will based the standard table - 'org_acct_periods'.  But later droped that idea, as it is difficult to enable or disable, when ever we want.
---
create table temp1(n1 number);

create or replace procedure proc1
is
begin
insert into temp1 values(1);
end ;
/

Do the form personalization in the following way..


















Now create an item and save it. So that form personalization process will invoke the procedure and execute the same.
















Query the tables and verify if data is inserted or not.

SQL> select * from temp1;

N1
----------
1
1

So the conclusion is - It works.


Monday, October 26, 2009

Distinct your data in PL/SQL tables

Question: How do you eliminate duplicate values from a PL/SQL table.

Answer: It is easy to select unique values from database table, with the help of SELECT DISTINCT query.
But if you have some data in PL/SQL table, then it is very difficult to eliminate duplicate records.

But Oracle 10g made it easy to filter out duplicate data from PL/SQL table or Nested table as well.
This is possible in 10g with a concept called - MULTISET 

See following example..
-------
declare
type nested_typ is table of varchar2(200);
v_test_type nested_typ := nested_typ();
v_temp nested_typ ;
begin
v_test_type.extend(8);
-- read values into array.
v_test_type(1) := 'NEW YORK';
v_test_type(2) := 'SYDNEY';
v_test_type(3) := 'SINGAPORE';
v_test_type(4) := 'PERTH';
v_test_type(5) := 'NEW YORK';
v_test_type(6) := 'NEW YORK';
v_test_type(7) := 'DELHI';
v_test_type(8) := 'PERTH';

dbms_output.put_line('Cities before distinct..'||chr(10)||'------------------------');
-- display values before distinct..
for i in v_test_type.first..v_test_type.last
loop
dbms_output.put_line(v_test_type(i));
end loop ;
-- assign all values to v_temp, which are in v_test_type
v_temp := v_test_type ;
-- take ditinct values out of v_temp, v_test_type into v_test_type
v_test_type := v_test_type MULTISET UNION DISTINCT v_temp ;
dbms_output.put_line(chr(10)||'...'||chr(10)||'Cities after distinct..'||char(10)||'-----------------------');
-- display values after distinct..
for i in v_test_type.first..v_test_type.last
loop
dbms_output.put_line(v_test_type(i));
end loop ;
end ;
/
out put
========
Cities before distinct..


------------------------
NEW YORK
SYDNEY
SINGAPORE
PERTH
NEW YORK
NEW YORK
DELHI
PERTH
...
Cities after distinct..
-----------------------
NEW YORK
SYDNEY
SINGAPORE
PERTH
DELHI

PL/SQL procedure successfully completed.
===
In the same way we can use other SET operations like UNION, UNION ALL, MINUS, INTERSECT on pl/sql tables.

Here is another way of doing it..


DECLARE
            presidents_t person_names_t ;
            presidents_t1 person_names_t ;
            cursor cur_user is select user_name from fnd_user where rownum < 5;
            cursor cur_user1 is select user_name from fnd_user where rownum < 10;

BEGIN
    open cur_user ;
    fetch cur_user bulk collect into presidents_t ;
    close cur_user ;
  
     open cur_user1 ;
    fetch cur_user1 bulk collect into presidents_t1 ;
    close cur_user1 ;

          
    FOR rec IN (SELECT column_value
                  FROM TABLE (CAST (presidents_t AS person_names_t))
                          union
                        SELECT column_value
                  FROM TABLE (CAST (presidents_t1 AS person_names_t))
                 )
        LOOP
            DBMS_OUTPUT.PUT_LINE(rec.column_value);
        END LOOP;
END;
/




Friday, October 16, 2009

BI Publisher: How to Print check box on BI Publisher

Question: How to print Check box on BI Publisher(XML Publisher) Reports.?
Answer:
Follow these steps to create checkboxes or any symbols for your XML Publisher Reports.
1. Design RTF template.
2. Place your check boxes on the template.

    For MS WORRD-2007, check box available under "Developer" menu/Legacy tools.
3. Right Click on checkbox and etnter criteria how the check box should behave.
      Ex: Which means, when the "DFF_FUMIGATION" is Y, then check box is checked. Otherwise un-checked.

4. Design other check boxes in similar way.

Note: Do not enter criteria under “BI Publisher Properties”. Enter criteria only on “Form field Help Text”.

5. Save template as RTF. If you test/preview your template it will not show check boxes properly. Instead it will show diamond shaped pictures or any other junk characters.

This is expected behavior, as Bi Publisher could not find exact mappings for the check boxes when generating output.

6. To do character set/fonts mappings..
Take “xdo example.cfg” file, which will be available in your machine “ /BI Publisher\BI Publisher Desktop\Template Builder for Word\config”

Save as this file as “xdo.cfg” in the same folder.

Verify the “Wingdings” family property is correctly pointing to the “fonts” directory in your machine or not.

You may also notice that “rtf-checkbox-glyph” property already available in .cfg file and which is set to “Wingdings;0254;0160”.
These two steps are important to show check boxes correctly.

7. Test your RTF template. You may notice check boxes displayed properly in the output.



After changing above property in “xdo.cfg” file and placed it under “ /BI Publisher\BI Publisher Desktop\Template Builder for Word\config”

Return to RTF template and click on preview again to verify the results.
 

Now RTF Template creation and setups steps required to generate check boxes are completed.
Create Data definition, Template and then upload your RTF template.

To complete font mappings at server side,

1. Log in as XML Publisher Administrator.

2. Navigate to Administration->Font Files->Create Font File.

3. Fields are Font Name and File.

For Font Name choose any descriptive name.

File will browse your PC to locate the font file.

4. Navigate to Font Mappings->Create Font Mapping Set.

5. Mapping name is the name you will give to a set of fonts.

6. Mapping code is the internal name you will give to this set.

7. Type: 'PDF Form' for PDF templates. 'FO to PDF' for all other template types.
 

 
  8. Create Font Mapping (this allows you to add fonts to a set).

 
9. Font Family is the exact same name you see in Word under Fonts.

If you don't use the same name the font will not be picked up at runtime.

10. Style and weight must also match how you use the font in windows.

Normal and Normal are good defaults.

11. Language and Territory should remain blank (NULL).






12. Navigate to Configuration General-> FO Processing->Font Mapping Set.
Can also be done at data def and template level under Edit Configuration.

Hierarchy is Site-> Data Def -> Template.
13. Select your new mapping set.

14. Make sure the font is not referenced under File->Properties->Custom in the RTF template file.

15. Under General set a Temporary Directory.
The font will be downloaded here under /fonts to be used at runtime, the first time the font is used.




16. Upload a template that uses your special font and test using preview or by submitting a concurrent request.

Wednesday, October 14, 2009

Sort your nested table data.

Question: How do I sort data which is in a nested table.?

Answer: You might've enjoyed the power of set operations(MINUS,INTERSECT,UNION) in SQL many times.
For example - To combine to sets of data, to eliminate duplicated data among two sets etc.

How about using similar set operations in PL/SQL or Nested tables. ?
With Oracle 10g we can have Multiset operations on Nested tables.

Have you ever come accross a situation, where you need to sort data which is in a nested table.
Below is the sample code to sort nested table and then display it.
---

declare
-- I used one nested table type, which is already available(seeded) in APPS schema.
-- If required, create one table type as you reuired.

v_arr VARCHAR2_TABLE_200 := VARCHAR2_TABLE_200();

begin

v_arr:= VARCHAR2_TABLE_200 ('NEW YORK','SYDNEY', 'SINGAPORE','PERTH', 'NEW DELHI','',NULL,'LONDON');

            -- just print and see, how data is stored in nested table.
                dbms_output.put_line(chr(10)'Cities before sorting..'chr(10)'-----------------------');

for i in v_arr.first..v_arr.last
loop
         dbms_output.put_line(nvl(v_arr(i),'NULL'));

end loop ;

-- watch out NVL function above... wanted to show 'NULL' word, where ever there is NULL.
select cast(multiset(
select * from table(v_arr)
order by 1 asc NULLS FIRST) as VARCHAR2_TABLE_200)
into v_arr from dual;

-- NULLS FIRST in above statement is to display nulls first and then data. Default is nulls displayed last.
-- see if data is sorted or not...

dbms_output.put_line(chr(10)'Cities after sorting..'chr(10)'-----------------------');

for i in v_arr.first..v_arr.last
loop
          dbms_output.put_line(nvl(v_arr(i),'NULL'));
end loop ;
end ;
/

---- here's the output. -------

Cities before sorting..
-----------------------
NEW YORK
SYDNEY
SINGAPORE
PERTH
NEW DELHI
NULL
NULL
LONDON

Cities after sorting..
-----------------------
NULL
NULL
LONDON
NEW DELHI
NEW YORK
PERTH
SINGAPORE
SYDNEY

PL/SQL procedure successfully completed.
..

Write to ".out" file from shell script.

Question: How to write messages to FND OUT file.?
Ans:
Here are the steps, to write something into fnd out file.
In shell script what ever we echo something that will be written in log file. This is expected behaviour.!
To write some content into ".out" file, one need to do it explicitly.
Here are the steps.
1. findout out file name. which is --> o.out
2. findout out directory name. Mostly $APPLCSF/out or something like this.
3. write the intended content/text to ".out" file.
4. if you are able to write text in .out file correctly, then same can be seen from "View Output" button as soon as concurrent program is completed.

Sample code:
# do sed on f2 and add 'o' and '.out' as suffix and prefix.
OUTFILE_NAME=o`echo $1 cut -d" " -f2 sed 's/FCP_REQID=//g' sed 's/"//g' `.outecho $OUTFILE_NAME
# any other code here ..
# finally write text in to outfile. In my case, I am writing contents of temp.txt to out file.
cat temp.txt >> $APPLCSF/out/$OUTFILE_NAME

..