Archive for the ‘ExcelDocumentType’ Category

ExcelDocTypeUtils Update

Sunday, January 15th, 2012

At the suggestion of  a user (Paul Jensen … thanks for the sample code as well), I have updated the ExcelDocTypeUtils package making the COL_COUNT attribute of the T_WORKSHEET_DATA type optional.  This will allow users to introduce queries with varying numbers of columns dynamically, or use queries such as SELECT * FROM some_table.  In the previous version, the COL_COUNT attribute was mandatory.  I’ve also added a new function called getColHeaderString that will generate a delimited column name list for use with the COL_HEADER_LIST attribute of the T_WORKSHEET_DATA.  This could be used with a ‘SELECT * FROM …’ type query string.

Example:

v_worksheet_rec.col_header_list       := ExcelDocTypeUtils.getColHeaderString(v_worksheet_rec.query,v_worksheet_rec.worksheet_list_delimiter)

(Download the code here:Code)

ExcelDocTypeUtils New Features: Worksheet Orientation and Repeating Column Headers

Monday, May 31st, 2010

At the request of several folks, I’ve added two new features to the ExcelDocumentType and ExcelDocTypeUtils PL/SQL package:

1. The ability to specify whether or not a worksheet’s orientation is Portrait or Landscape.

2. The ability to specify whether or not column headers for a worksheet will repeat at the top of each printed page.

See the EmployeeReport demo files in the code bundle (or download the ExcelDocTypeUtils Developer Guide) for specifics.

(Download the code here:Code)

ExcelDocTypeUtils API Guide

Monday, April 26th, 2010

I finally broke down and documented the ExcelDocTypeUtils PL/SQL API  in a 34 page document. Sorry about the long wait …

Here it is:  (opens in new window):ExcelDocTypeUtils API Guide

ExcelDocumentType: Create Hyperlinks between Worksheets

Monday, December 28th, 2009

This post  introduces a new feature in the ExcelDocTypeUtils PL/SQL package that allows a developer to create hyper linked cell data that points from one worksheet to another.   The feature is implemented by a  new function called createWorksheetLink.  The function takes two parameters: the cell data, and the name of the target worksheet.  The function is called from the dynamic SQL statement that is passed as part of a worksheet data object (ExcelDocTypeUtils.T_WORKSHEET_DATA).

The following code sample demonstrates how this feature can be used to generate a summary worksheet containing a hyper linked list of department names. Each hyper linked department name points to a worksheet containing employee data for that particular department.    The department related worksheets each contain a hyper link back to the summary worksheet that contains the department listings. The data for this demo comes from Oracle HR demo schema.

CREATE OR REPLACE PROCEDURE ExcelHyperlinkHR
IS

– This cursor will be used to generate the individual Department worksheets.
CURSOR crsrDepatmentWS IS
SELECT
department_id,
SUBSTR(UPPER(DEPARTMENT_NAME),1,20) sheet_name
FROM
hr.departments dp
WHERE
EXISTS (select ‘x’ from HR.employees where DEPARTMENT_ID = dp.department_id)
ORDER BY
dp.department_name;

– Base SQL statement for loading each departmental worksheet
v_employee_base_sql VARCHAR2(500) := ‘SELECT last_name||”, ”||first_name,email,phone_number,to_char(hire_date,”MM/DD/YYYY”) ‘||
‘FROM hr.employees ‘||
‘WHERE department_id = :id ‘||
‘ORDER BY last_name,first_name’;

– SQL statement based on v_employee_base_sql, but with the :id replaced with department_id.
v_employee_dept_sql VARCHAR2(500) := NULL;

– SQL statement used to generate hyperlinked worksheet listing all departments containing employees
v_department_sql    VARCHAR2(500) := ‘SELECT ExcelDocTypeUtils.createWorksheetLink(UPPER(department_name),department_name) ‘||
‘FROM hr.departments dp ‘||
‘WHERE EXISTS (select ”x” from HR.employees where DEPARTMENT_ID = dp.department_id) ‘||
‘ORDER BY DP.DEPARTMENT_NAME ‘;

excelReport         ExcelDocumentType := ExcelDocumentType();
documentArray       ExcelDocumentLine := ExcelDocumentLine();

v_worksheet_rec     ExcelDocTypeUtils.T_WORKSHEET_DATA := NULL;
v_worksheet_array   ExcelDocTypeUtils.WORKSHEET_TABLE  := ExcelDocTypeUtils.WORKSHEET_TABLE();

v_sheet_title       ExcelDocTypeUtils.T_SHEET_TITLE := NULL;

– Objects for Defining Document Styles (Optional)

v_style_def         ExcelDocTypeUtils.T_STYLE_DEF := NULL;
v_style_array       ExcelDocTypeUtils.STYLE_LIST  := ExcelDocTypeUtils.STYLE_LIST();

BEGIN

– Add Styles

v_style_def.p_style_id     := ‘HyperlinkStyle’;
v_style_def.p_text_color   := ‘Blue’;

ExcelDocTypeUtils.addStyleType(v_style_array,v_style_def);

v_style_def := NULL;
v_style_def.p_style_id          := ‘SheetTitleStyle’;
v_style_def.p_align_horizontal  := ‘Center’;
v_style_def.p_bold              := ‘Y’;
v_style_def.p_text_color        := ‘Black’;

ExcelDocTypeUtils.addStyleType(v_style_array,v_style_def);

v_style_def := NULL;
v_style_def.p_style_id          := ‘SheetTitleStyleLink’;
v_style_def.p_align_horizontal  := ‘Center’;
v_style_def.p_bold              := ‘Y’;
v_style_def.p_text_color        := ‘Blue’;

ExcelDocTypeUtils.addStyleType(v_style_array,v_style_def);

– Define Sheet Title
v_sheet_title.title      := ‘Employee Listing By Department’;
v_sheet_title.cell_span  := ’4′;
v_sheet_title.style      := ‘SheetTitleStyle’;

v_worksheet_rec.query             := v_department_sql;
v_worksheet_rec.worksheet_name    := ‘Departments’;
v_worksheet_rec.title             := v_sheet_title;
v_worksheet_rec.col_count         := 1;
v_worksheet_rec.col_width_list    := ’40′;
v_worksheet_rec.col_header_list   := ‘Department’;
v_worksheet_rec.col_datatype_list := ‘String’;
v_worksheet_rec.col_style_list    := ‘HyperlinkStyle’;

ExcelDocTypeUtils.addWorksheetType(v_worksheet_array,v_worksheet_rec);

– Construct Department worksheets

FOR data_rec IN crsrDepatmentWS LOOP

v_worksheet_rec      := NULL;
v_employee_dept_sql  := REPLACE(v_employee_base_sql,’:id’,data_rec.department_id);

v_sheet_title.title      := ExcelDocTypeUtils.createWorksheetLink(‘Departments’,'Back to Department Listing’);
v_sheet_title.cell_span  := ’3′;
v_sheet_title.style      := ‘SheetTitleStyleLink’;

v_worksheet_rec.query             := v_employee_dept_sql;
v_worksheet_rec.worksheet_name    := data_rec.sheet_name;
v_worksheet_rec.title             := v_sheet_title;
v_worksheet_rec.col_count         := 4;
v_worksheet_rec.col_width_list    := ’50,20,20,15′;
v_worksheet_rec.col_header_list   := ‘Name,Email,Phone Number,Hire Date’;
v_worksheet_rec.col_datatype_list := ‘String,String,String,String’;

ExcelDocTypeUtils.addWorksheetType(v_worksheet_array,v_worksheet_rec);

END LOOP;

excelReport := ExcelDocTypeUtils.createExcelDocument(v_worksheet_array,v_style_array);

excelReport.displayDocument;

END;

This video clip demonstrates the output from the source code.

Download the code for the procedure here:ExcelHyperlinkHR.sql.
(Note … you must have the latest version of the ExcelDocumentType and ExcelDocTypeUtils)

Convert Oracle Date Format to Excel Date Format

Monday, November 23rd, 2009

MS Excel uses a numeric format, called Serial Date format, when storing and dealing with dates and times.   Serial date is calculated by taking a given date and determining the number of days that have passed since that date and 01-Jan-1900 (actually 00-Jan1900, but that’s a story for another time).  Why is this important to an Oracle developer?  If you are using a tool such as the ExcelDocumentType to generate an Excel document with PL/SQL and you are trying to apply an Excel style to an Oracle Date data type … it will not work.  The Oracle Date column must be converted to serial format before Excel will recognize it as a date and apply any kind of special date formatting to it.  Luckily, the conversion formula is simple.  The following function will take an Oracle Date data type and convert it to an Excel Date data type (or serial date):

CREATE OR REPLACE FUNCTION convertOracleToSerialDate(p_date DATE) RETURN NUMBER
IS

v_date_differential NUMBER(1) := 0;

BEGIN

IF TRUNC(p_date) >= TO_DATE(’01-MAR-1900′,’DD-MON-YYYY’) THEN

v_date_differential := 1;

END IF;

RETURN ((trunc(p_date) + v_date_differential) – (TO_DATE(’01-JAN-1900′,’DD-MON-YYYY’)-1));

END;
/

SQL*Plus: Release 10.2.0.4.0 – Production on Mon Nov 23 22:31:54 2009

Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.

Connected to:
Oracle Database 10g Express Edition Release 10.2.0.1.0 – Production

SQL> select convertOracleToSerialDate(’05-MAY-1968′) from dual;

CONVERTORACLETOSERIALDATE(’05-MAY-1968′)
—————————————-
24963

If we pass in the value ’05-MAY-1968′ to the function above, we will get the value 24963.  Now, if we place this value in an Excel Spreadsheet and format the cell as a Date type, it will be converted to ’5/5/1968′ (or what ever date format you choose for that cell or cells).

The reverse is also possible.  If we have a Serial Date value, and we want to convert it to an Oracle Date type, we would use a function such as:

CREATE OR REPLACE FUNCTION convertSerialToOracleDate(p_serial_date NUMBER) RETURN DATE
IS

v_orcl_date DATE := NULL;

BEGIN

v_orcl_date := (((TO_DATE(’01-JAN-1900′,’DD-MON-YYYY’)) + p_serial_date-1));

IF TRUNC(v_orcl_date) > TO_DATE(’01-MAR-1900′,’DD-MON-YYYY’) THEN

v_orcl_date := v_orcl_date – 1;

END IF;

RETURN v_orcl_date;

END;
/

SQL*Plus: Release 10.2.0.4.0 – Production on Mon Nov 23 22:45:44 2009

Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.

Connected to:
Oracle Database 10g Express Edition Release 10.2.0.1.0 – Production

SQL> select convertSerialToOracleDate(24963) from dual;

CONVERTSE
———
05-MAY-68

SQL>

If we take the result we obtained from the first function, 24963, and apply the second formula (using SQL*Plus, SQL Developer, TOAD, etc), we get …05-May-68.