This document describes a new method for generating Excel reports from Oracle using user defined types and a utility package called ExcelDocTypeUtils. The method allows creating a multi-worksheet Excel document from different queries with little coding. It uses record and collection types to store worksheet data, which is then passed to a function to generate the ExcelDocumentType object. Downloading the provided code package allows testing the simplified report generation process.
Original Description:
Creating reports using Excel Document Type
Original Title
A Simple Method for Creating Excel Reports Using the ExcelDocumentType
This document describes a new method for generating Excel reports from Oracle using user defined types and a utility package called ExcelDocTypeUtils. The method allows creating a multi-worksheet Excel document from different queries with little coding. It uses record and collection types to store worksheet data, which is then passed to a function to generate the ExcelDocumentType object. Downloading the provided code package allows testing the simplified report generation process.
This document describes a new method for generating Excel reports from Oracle using user defined types and a utility package called ExcelDocTypeUtils. The method allows creating a multi-worksheet Excel document from different queries with little coding. It uses record and collection types to store worksheet data, which is then passed to a function to generate the ExcelDocumentType object. Downloading the provided code package allows testing the simplified report generation process.
A couple of years ago, I created a user defined type called the ExcelDocumentType that allows a developer to create a custom Excel (XM! document using "#$%& The user defined type has 'een well received, 'ut a few fol(s have commented on how tedious the coding can 'ecome when creating multiple reports (with a similar ta'ular layout!& I came to the same conclusion recently, and have created a method that greatly simplifies the process& The method ma(es use of a couple of new user defined types and a "#$% pac(age (all provided for your use!& It ma(es creating a multi wor(sheet document (with a different )uery for each wor(sheet! a 'ree*e and with very little ExcelDocumentType coding involved& The Basics As mentioned a'ove, this new method for generating ExcelDocumentType reports uses a few +racle user defined types and a small utility pac(age called ExcelDoc,tils& -efore I get into the details of the "#$% pac(age and the supporting user defined types, let.s loo( at a code sample that will generate an Excel document containing three wor(sheets& /or this example I used the EM"+0EE$ ta'le from the +racle 12 demo schema& 32EATE +2 2E"A3E "2+3ED,2E employee2eport A$ v4s)l4salary 5A231A26(677! 89 :$EE3T last4name,first4name,salary /2+M hr&employees +2DE2 -0 last4name,first4name:; v4s)l4contact 5A231A26(677! 89 :$EE3T last4name,first4name,phone4num'er,email /2+M hr&employees +2DE2 -0 last4name,first4name:; v4s)l4hiredate 5A231A26(677! 89 :$EE3T last4name,first4name,to4char(hire4date,::MM#DD#0000::! hire4date /2+M hr&employees +2DE2 -0 last4name,first4name:; excelReport ExcelDocumentType := ExcelDocumentType(); v_worksheet_rec ExcelDocTypeUtils.T_!R"#$EET_D%T% := &U''; v_worksheet_(rr(y ExcelDocTypeUtils.!R"#$EET_T%)'E := ExcelDocTypeUtils.!R"#$EET_T%)'E(); -E<I= >> $alary v4wor(sheet4rec&)uery 89 v4s)l4salary; v4wor(sheet4rec&wor(sheet4name 89 :$alaries:; v4wor(sheet4rec&col4count 89 ?; v4wor(sheet4rec&col4width4list 89 :6@,67,A@:; v4wor(sheet4rec&col4header4list 89 :astname,/irstname,$alary:; v4wor(sheet4array&EXTE=D; v4wor(sheet4array(v4wor(sheet4array&count! 89 v4wor(sheet4rec; >> 3ontact v4wor(sheet4rec&)uery 89 v4s)l4contact; v4wor(sheet4rec&wor(sheet4name 89 :3ontact4Info:; v4wor(sheet4rec&col4count 89 B; v4wor(sheet4rec&col4width4list 89 :6@,67,67,6@:; v4wor(sheet4rec&col4header4list 89 :astname,/irstname,"hone,Email:; v4wor(sheet4array&EXTE=D; v4wor(sheet4array(v4wor(sheet4array&count! 89 v4wor(sheet4rec; >> 3ontact v4wor(sheet4rec&)uery 89 v4s)l4hiredate; v4wor(sheet4rec&wor(sheet4name 89 :1iredate:; v4wor(sheet4rec&col4count 89 ?; v4wor(sheet4rec&col4width4list 89 :6@,67,67:; v4wor(sheet4rec&col4header4list 89 :astname,/irstname,1iredate:; v4wor(sheet4array&EXTE=D; v4wor(sheet4array(v4wor(sheet4array&count! 89 v4wor(sheet4rec; excel2eport 89 ExcelDocType,tils&createExcelDocument(v4wor(sheet4array!; excel2eport&displayDocument; E=D; # The code a'ove generates the following Excel document8 $o, what are we loo(ing at hereC /irst, a drastic reduction in the amount of code it ta(es to generate a 'asic Excel report& $econd, we see some interesting data structures that allow us to accomplish that feat& The code a'ove centers around three structures and a new "#$% pac(age called ExcelDocTypeUtils8 (A! A recor* type called T_WORKSHEET_DATA that holds8 the )uery string that generates the wor(sheet data; the wor(sheet name; the num'er of columns displayed in the sheet; a list containing the column width for each displayed column; a list of column headers& This record is defined in the ExcelDocType,tils pac(age& (6! A collection o+,ect of T_WORKSHEET_DATA records called WORKSHEET_TABLE& Each item in the collection represents one wor(sheet in the Excel document& (?! The ExcelDocumentType is that third structure& The WORKSHEET_TABLE collection is passed to a function in the ExcelDocTypeUtils pac(age that returns a fully populated ExcelDocumentType o'Dect& (B! The ExcelDocTypeUtils pac(age contains a single pu'lic utility function called createExcelDocument& This function creates and returns an ExcelDocumentType o'Dect 'ased upon the WORKSHEET_TABLE input parameter& The Code I have provided a lin( in this 'log entry that will allow you to download the code and all of the re)uired o'Dects& Download it and give it a try& I have 'een using at it at my place of employment to generate scheduled reports for various departments and individuals& $o far so goodE /or those who Dust want to ta(e a loo( at the code, here is the code for the ExcelDocType,tils pac(age8 32EATE +2 2E"A3E T0"E T42+F A$ TA-E +/ 5A231A26(@77!; # 32EATE +2 2E"A3E T0"E T42+F4=,M-E2 A$ TA-E +/ =,M-E2(?!; # 32EATE +2 2E"A3E T0"E 2E$,T4TA-E A$ TA-E +/ T42+F; # 32EATE +2 2E"A3E "A3GA<E ExcelDocType,tils A$
T0"E t4refcursor I$ 2E/ 3,2$+2; #H This record contains all of the components re)uired to create an Excel 2eport wor(sheet& H# T0"E T4F+2G$1EET4DATA I$ 2E3+2D( )uery 5A231A26(B777!, wor(sheet4name 5A231A26(67!, col4count =,M-E2(?!, col4width4list 5A231A26(@77!, col4header4list 5A231A26(6777! !; #H An Array of T4F+2G$1EET4DATA allows us to create an excel document with multiple wor(sheets 'ased on different )ueries& H# T0"E F+2G$1EET4TA-E I$ TA-E +/ T4F+2G$1EET4DATA; /,=3TI+= createExcelDocument(p4wor(sheet4data F+2G$1EET4TA-E! 2ET,2= ExcelDocumentType; E=D; # sho err; #HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH# #HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH "A3GA<E -+D0 HHHHHHHHHHHHHHHHHHHHHHHHHHHHHH# #HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH# 32EATE +2 2E"A3E "A3GA<E -+D0 ExcelDocType,tils A$ #H /unction that returns the element at the re)uested position in a delimited string& H# /,=3TI+= get$tringElement(p4string 5A231A26, p4element =,M-E2, p4delimiter 5A231A26 89 :,:, p4level =,M-E2 89 7! 2ET,2= 5A231A26 I$ v4string 5A231A26(6777! 89 =,; v4element 5A231A26(6777! 89 =,; v4next 5A231A26(6777! 89 =,; v4level =,M-E2(B! 89 7; -E<I= v4level 89 p4level I A; v4element 89 su'str(p4stringJJp4delimiter,A, instr(p4stringJJp4delimiter,p4delimiter!>A!; >> need to loo( ahead to ma(e sure we handle the null elements& v4next 89 su'str(p4stringJJp4delimiter, instr(p4stringJJp4delimiter,p4delimiter!,length(p4delimiter!!; I/ ((v4level K9 p4element! +2 (v4element I$ =, A=D v4next E9 p4delimiter!! T1E= 2ET,2= v4element; E$E v4string 89 su'str(p4stringJJp4delimiter, instr(p4stringJJp4delimiter,p4delimiter!IA,length(p4string!!; 2ET,2= get$tringElement(v4string,p4element,p4delimiter,v4level!; E=D I/; E=D; #H999999999999999999999999999999999999999999999999999999999999999999999999999999H# #H This function executes the given )uery and returns the data in a 2E$,T4TA-E 3ollection o'Dect& H# /,=3TI+= 'uildData$et(p4)uery4string 5A231A26 89 =,, p4col4count =,M-E2 89 7! 2ET,2= 2E$,T4TA-E I$ r4ta'le 2E$,T4TA-E 89 2E$,T4TA-E(!; v4row4sym'ol 5A231A26(67! 89 :v4row:; v4row4fetch 5A231A26(A777! 89 =,; v4row4extend =,M-E2(?! 89 p4col4count; v4anydata $0$&A=0DATA 89 =,; v4func4result "$4I=TE<E2 89 7; v4)uery 5A231A26(AL777! 89 p4)uery4string; func2esultTa'le Anonymous/unction 89 Anonymous/unction(!; v4result4func 5A231A26(?6777! 89 :/,=3TI+= get2ow$et 2ET,2= 2E$,T4TA-E :JJ :I$ :JJ : T0"E t4refcursor I$ 2E/ 3,2$+2; :JJ : v4ta'le 2E$,T4TA-E 89 result4ta'le(!; :JJ : v4row T42+F 89 T42+F(!; :JJ : v4)uery 5A231A26(B777! 89 ::M)K::; :JJ : v4refcur t4refcursor; :JJ :-E<I= :JJ : +"E= v4refcur /+2 v4)uery; :JJ : ++" :JJ : v4row&extend(MeK!; :JJ : /ET31 v4refcur I=T+ MfK ;:JJ : EXIT F1E= v4refcurN=+T/+,=D; :JJ : v4ta'le&EXTE=D; :JJ : v4ta'le(v4ta'le&3+,=T! 89 v4row; :JJ : v4row&DEETE; :JJ : E=D ++"; :JJ : 2ET,2= v4ta'le; :JJ :E=D; :; -E<I= /+2 x I= A && v4row4extend ++" v4row4fetch 89 v4row4fetchJJv4row4sym'olJJ:(:JJxJJ:!,:;
rapping !t "p As with all of the code I post in my 'log entries, please feel to use it and modify it as you see fit& "lease feel free to contact me with any )uestionsE I hope this ma(es generating Excel reports a little more easy and lot less tedious&